diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs index 3a540d80998d0..157a91c249d4f 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs @@ -10,7 +10,7 @@ use rustc_feature::{ use rustc_hir::attrs::CfgEntry; use rustc_hir::lints::AttributeLintKind; use rustc_hir::{AttrPath, RustcVersion, Target}; -use rustc_parse::parser::{ForceCollect, Parser}; +use rustc_parse::parser::{ForceCollect, Parser, Recovery}; use rustc_parse::{exp, parse_in}; use rustc_session::Session; use rustc_session::config::ExpectedValues; @@ -360,8 +360,10 @@ fn parse_cfg_attr_internal<'a>( ) -> PResult<'a, (CfgEntry, Vec<(ast::AttrItem, Span)>)> { // Parse cfg predicate let pred_start = parser.token.span; - let meta = - MetaItemOrLitParser::parse_single(parser, ShouldEmit::ErrorsAndLints { recover: true })?; + let meta = MetaItemOrLitParser::parse_single( + parser, + ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed }, + )?; let pred_span = pred_start.with_hi(parser.token.span.hi()); let cfg_predicate = AttributeParser::parse_single_args( @@ -376,7 +378,7 @@ fn parse_cfg_attr_internal<'a>( CRATE_NODE_ID, Target::Crate, features, - ShouldEmit::ErrorsAndLints { recover: true }, + ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed }, &meta, parse_cfg_entry, &CFG_ATTR_TEMPLATE, diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs index ca844758daaa6..4005ad2cba111 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs @@ -5,7 +5,7 @@ use rustc_feature::{AttributeTemplate, Features}; use rustc_hir::attrs::CfgEntry; use rustc_hir::{AttrPath, Target}; use rustc_parse::exp; -use rustc_parse::parser::Parser; +use rustc_parse::parser::{Parser, Recovery}; use rustc_session::Session; use rustc_span::{ErrorGuaranteed, Span, sym}; @@ -78,9 +78,11 @@ pub fn parse_cfg_select( } } } else { - let meta = - MetaItemOrLitParser::parse_single(p, ShouldEmit::ErrorsAndLints { recover: true }) - .map_err(|diag| diag.emit())?; + let meta = MetaItemOrLitParser::parse_single( + p, + ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed }, + ) + .map_err(|diag| diag.emit())?; let cfg_span = meta.span(); let cfg = AttributeParser::parse_single_args( sess, @@ -95,7 +97,7 @@ pub fn parse_cfg_select( // Doesn't matter what the target actually is here. Target::Crate, features, - ShouldEmit::ErrorsAndLints { recover: true }, + ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed }, &meta, parse_cfg_entry, &AttributeTemplate::default(), diff --git a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs index a367e699fcb96..557dfe09853ba 100644 --- a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs +++ b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs @@ -274,3 +274,12 @@ impl NoArgsAttributeParser for NoBuiltinsParser { const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoBuiltins; } + +pub(crate) struct RustcPreserveUbChecksParser; + +impl NoArgsAttributeParser for RustcPreserveUbChecksParser { + const PATH: &[Symbol] = &[sym::rustc_preserve_ub_checks]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcPreserveUbChecks; +} diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs index 53120dece916e..71a8fb0dd47d9 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs @@ -7,36 +7,36 @@ use crate::attributes::{NoArgsAttributeParser, OnDuplicate}; use crate::context::Stage; use crate::target_checking::AllowedTargets; -pub(crate) struct RustcDumpUserArgs; +pub(crate) struct RustcDumpUserArgsParser; -impl NoArgsAttributeParser for RustcDumpUserArgs { +impl NoArgsAttributeParser for RustcDumpUserArgsParser { const PATH: &[Symbol] = &[sym::rustc_dump_user_args]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpUserArgs; } -pub(crate) struct RustcDumpDefParents; +pub(crate) struct RustcDumpDefParentsParser; -impl NoArgsAttributeParser for RustcDumpDefParents { +impl NoArgsAttributeParser for RustcDumpDefParentsParser { const PATH: &[Symbol] = &[sym::rustc_dump_def_parents]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpDefParents; } -pub(crate) struct RustcDumpItemBounds; +pub(crate) struct RustcDumpItemBoundsParser; -impl NoArgsAttributeParser for RustcDumpItemBounds { +impl NoArgsAttributeParser for RustcDumpItemBoundsParser { const PATH: &[Symbol] = &[sym::rustc_dump_item_bounds]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::AssocTy)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpItemBounds; } -pub(crate) struct RustcDumpPredicates; +pub(crate) struct RustcDumpPredicatesParser; -impl NoArgsAttributeParser for RustcDumpPredicates { +impl NoArgsAttributeParser for RustcDumpPredicatesParser { const PATH: &[Symbol] = &[sym::rustc_dump_predicates]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ @@ -49,9 +49,9 @@ impl NoArgsAttributeParser for RustcDumpPredicates { const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpPredicates; } -pub(crate) struct RustcDumpVtable; +pub(crate) struct RustcDumpVtableParser; -impl NoArgsAttributeParser for RustcDumpVtable { +impl NoArgsAttributeParser for RustcDumpVtableParser { const PATH: &[Symbol] = &[sym::rustc_dump_vtable]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 0cabc0895053e..32362403ed678 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -10,6 +10,7 @@ use rustc_feature::{AttrSuggestionStyle, AttributeTemplate}; use rustc_hir::attrs::AttributeKind; use rustc_hir::lints::AttributeLintKind; use rustc_hir::{AttrPath, HirId}; +use rustc_parse::parser::Recovery; use rustc_session::Session; use rustc_session::lint::{Lint, LintId}; use rustc_span::{ErrorGuaranteed, Span, Symbol}; @@ -31,7 +32,8 @@ use crate::attributes::crate_level::{ CrateNameParser, CrateTypeParser, MoveSizeLimitParser, NeedsPanicRuntimeParser, NoBuiltinsParser, NoCoreParser, NoMainParser, NoStdParser, PanicRuntimeParser, PatternComplexityLimitParser, ProfilerRuntimeParser, RecursionLimitParser, - RustcCoherenceIsCoreParser, TypeLengthLimitParser, WindowsSubsystemParser, + RustcCoherenceIsCoreParser, RustcPreserveUbChecksParser, TypeLengthLimitParser, + WindowsSubsystemParser, }; use crate::attributes::debugger::DebuggerViualizerParser; use crate::attributes::deprecation::DeprecationParser; @@ -71,8 +73,8 @@ use crate::attributes::rustc_allocator::{ RustcDeallocatorParser, RustcReallocatorParser, }; use crate::attributes::rustc_dump::{ - RustcDumpDefParents, RustcDumpItemBounds, RustcDumpPredicates, RustcDumpUserArgs, - RustcDumpVtable, + RustcDumpDefParentsParser, RustcDumpItemBoundsParser, RustcDumpPredicatesParser, + RustcDumpUserArgsParser, RustcDumpVtableParser, }; use crate::attributes::rustc_internal::{ RustcHasIncoherentInherentImplsParser, RustcLayoutParser, RustcLayoutScalarValidRangeEndParser, @@ -293,11 +295,11 @@ attribute_parsers!( Single>, Single>, Single>, - Single>, - Single>, - Single>, - Single>, - Single>, + Single>, + Single>, + Single>, + Single>, + Single>, Single>, Single>, Single>, @@ -309,6 +311,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, @@ -383,7 +386,7 @@ impl Stage for Late { } fn should_emit(&self) -> ShouldEmit { - ShouldEmit::ErrorsAndLints { recover: true } + ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed } } } @@ -770,10 +773,10 @@ pub enum ShouldEmit { ErrorsAndLints { /// Whether [`ArgParser`] will attempt to recover from errors. /// - /// If true, it will attempt to recover from bad input (like an invalid literal). Setting - /// this to false will instead return early, and not raise errors except at the top level - /// (in [`ArgParser::from_attr_args`]). - recover: bool, + /// Whether it is allowed to recover from bad input (like an invalid literal). Setting + /// this to `Forbidden` will instead return early, and not raise errors except at the top + /// level (in [`ArgParser::from_attr_args`]). + recovery: Recovery, }, /// The operation will *not* emit errors and lints. /// diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index 7f3c6d28005ff..973635f432e8c 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -15,7 +15,7 @@ use rustc_ast_pretty::pprust; use rustc_errors::{Diag, PResult}; use rustc_hir::{self as hir, AttrPath}; use rustc_parse::exp; -use rustc_parse::parser::{ForceCollect, Parser, PathStyle, token_descr}; +use rustc_parse::parser::{ForceCollect, Parser, PathStyle, Recovery, token_descr}; use rustc_session::errors::create_lit_error; use rustc_session::parse::ParseSess; use rustc_span::{Ident, Span, Symbol, sym}; @@ -121,7 +121,7 @@ impl ArgParser { &args.tokens, args.dspan.entire(), psess, - ShouldEmit::ErrorsAndLints { recover: false }, + ShouldEmit::ErrorsAndLints { recovery: Recovery::Forbidden }, ) { Ok(p) => return Some(ArgParser::List(p)), Err(e) => { @@ -373,7 +373,10 @@ fn expr_to_lit<'sess>( } Err(err) => { let err = create_lit_error(psess, err, token_lit, expr.span); - if matches!(should_emit, ShouldEmit::ErrorsAndLints { recover: false }) { + if matches!( + should_emit, + ShouldEmit::ErrorsAndLints { recovery: Recovery::Forbidden } + ) { Err(err) } else { let lit = MetaItemLit { @@ -431,7 +434,10 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> { if !lit.kind.is_unsuffixed() { // Emit error and continue, we can still parse the attribute as if the suffix isn't there let err = self.parser.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span }); - if matches!(self.should_emit, ShouldEmit::ErrorsAndLints { recover: false }) { + if matches!( + self.should_emit, + ShouldEmit::ErrorsAndLints { recovery: Recovery::Forbidden } + ) { return Err(err); } else { self.should_emit.emit_err(err) @@ -569,6 +575,10 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> { should_emit: ShouldEmit, ) -> PResult<'sess, MetaItemListParser> { let mut parser = Parser::new(psess, tokens, None); + if let ShouldEmit::ErrorsAndLints { recovery } = should_emit { + parser = parser.recovery(recovery); + } + let mut this = MetaItemListParserContext { parser: &mut parser, should_emit }; // Presumably, the majority of the time there will only be one attr. diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs index 8e925cfe09a2e..3ebde949b99bc 100644 --- a/compiler/rustc_builtin_macros/src/cfg.rs +++ b/compiler/rustc_builtin_macros/src/cfg.rs @@ -13,6 +13,7 @@ use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpa use rustc_hir::attrs::CfgEntry; use rustc_hir::{AttrPath, Target}; use rustc_parse::exp; +use rustc_parse::parser::Recovery; use rustc_span::{ErrorGuaranteed, Span, sym}; use crate::errors; @@ -42,7 +43,7 @@ fn parse_cfg(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream) -> Result, span: Span, tts: TokenStream) -> Result StripUnconfigured<'a> { fn in_cfg(&self, attrs: &[Attribute]) -> bool { attrs.iter().all(|attr| { !is_cfg(attr) - || self.cfg_true(attr, ShouldEmit::ErrorsAndLints { recover: true }).as_bool() + || self + .cfg_true(attr, ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed }) + .as_bool() }) } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index cfa7725c74008..48e2ee8e9abd1 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -26,7 +26,7 @@ use rustc_hir::def::MacroKinds; use rustc_hir::limit::Limit; use rustc_parse::parser::{ AllowConstBlockItems, AttemptLocalParseRecovery, CommaRecoveryMode, ForceCollect, Parser, - RecoverColon, RecoverComma, token_descr, + RecoverColon, RecoverComma, Recovery, token_descr, }; use rustc_session::Session; use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS}; @@ -2170,7 +2170,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { call.span(), self.cx.current_expansion.lint_node_id, Some(self.cx.ecfg.features), - ShouldEmit::ErrorsAndLints { recover: true }, + ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed }, ); let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span }; @@ -2220,7 +2220,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { // Target doesn't matter for `cfg` parsing. Target::Crate, self.cfg().features, - ShouldEmit::ErrorsAndLints { recover: true }, + ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed }, parse_cfg, &CFG_TEMPLATE, ) else { diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 92dda79b09203..13e36a0ed8e65 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1123,6 +1123,9 @@ pub enum AttributeKind { /// Represents `#[rustc_pass_indirectly_in_non_rustic_abis]` RustcPassIndirectlyInNonRusticAbis(Span), + /// Represents `#[rustc_preserve_ub_checks]` + RustcPreserveUbChecks, + /// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint). RustcPubTransparent(Span), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 816ed07c1dc4c..4ffabf82dceba 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -133,6 +133,7 @@ impl AttributeKind { RustcParenSugar(..) => No, RustcPassByValue(..) => Yes, RustcPassIndirectlyInNonRusticAbis(..) => No, + RustcPreserveUbChecks => No, RustcPubTransparent(..) => Yes, RustcReallocator => No, RustcScalableVector { .. } => Yes, diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index b3889849430ae..249368fd1194f 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -231,7 +231,12 @@ pub(crate) fn run_in_thread_pool_with_globals< .name("rustc query cycle handler".to_string()) .spawn(move || { let on_panic = defer(|| { - eprintln!("internal compiler error: query cycle handler thread panicked, aborting process"); + // Split this long string so that it doesn't cause rustfmt to + // give up on the entire builder expression. + // + const MESSAGE: &str = "\ +internal compiler error: query cycle handler thread panicked, aborting process"; + eprintln!("{MESSAGE}"); // We need to abort here as we failed to resolve the deadlock, // otherwise the compiler could just hang, process::abort(); @@ -244,11 +249,16 @@ pub(crate) fn run_in_thread_pool_with_globals< tls::with(|tcx| { // Accessing session globals is sound as they outlive `GlobalCtxt`. // They are needed to hash query keys containing spans or symbols. - let query_map = rustc_span::set_session_globals_then(unsafe { &*(session_globals as *const SessionGlobals) }, || { - // Ensure there was no errors collecting all active jobs. - // We need the complete map to ensure we find a cycle to break. - QueryCtxt::new(tcx).collect_active_jobs(false).expect("failed to collect active queries in deadlock handler") - }); + let query_map = rustc_span::set_session_globals_then( + unsafe { &*(session_globals as *const SessionGlobals) }, + || { + // Ensure there were no errors collecting all active jobs. + // We need the complete map to ensure we find a cycle to break. + QueryCtxt::new(tcx).collect_active_jobs(false).expect( + "failed to collect active queries in deadlock handler", + ) + }, + ); break_query_cycles(query_map, ®istry); }) }) diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index fa9ceb018dd5a..84d642ea4ebc0 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -1,8 +1,8 @@ //! Performs various peephole optimizations. use rustc_abi::ExternAbi; -use rustc_ast::attr; -use rustc_hir::LangItem; +use rustc_hir::attrs::AttributeKind; +use rustc_hir::{LangItem, find_attr}; use rustc_middle::bug; use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::*; @@ -31,7 +31,7 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let preserve_ub_checks = - attr::contains_name(tcx.hir_krate_attrs(), sym::rustc_preserve_ub_checks); + find_attr!(tcx.hir_krate_attrs(), AttributeKind::RustcPreserveUbChecks); if !preserve_ub_checks { SimplifyUbCheck { tcx }.visit_body(body); } diff --git a/compiler/rustc_mir_transform/src/liveness.rs b/compiler/rustc_mir_transform/src/liveness.rs index cf977be4c3df9..9bafee9f31c39 100644 --- a/compiler/rustc_mir_transform/src/liveness.rs +++ b/compiler/rustc_mir_transform/src/liveness.rs @@ -1243,9 +1243,12 @@ struct TransferFunction<'a, 'tcx> { impl<'tcx> Visitor<'tcx> for TransferFunction<'_, 'tcx> { fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { match statement.kind { - // `ForLet(None)` fake read erroneously marks the just-assigned local as live. - // This defeats the purpose of the analysis for `let` bindings. - StatementKind::FakeRead(box (FakeReadCause::ForLet(None), _)) => return, + // `ForLet(None)` and `ForGuardBinding` fake reads erroneously mark the just-assigned + // locals as live. This defeats the purpose of the analysis for such bindings. + StatementKind::FakeRead(box ( + FakeReadCause::ForLet(None) | FakeReadCause::ForGuardBinding, + _, + )) => return, // Handle self-assignment by restricting the read/write they do. StatementKind::Assign(box (ref dest, ref rvalue)) if self.self_assignment.contains(&location) => diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 8cf68b280850e..f93d420fb06d1 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -318,6 +318,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcParenSugar(..) | AttributeKind::RustcPassByValue (..) | AttributeKind::RustcPassIndirectlyInNonRusticAbis(..) + | AttributeKind::RustcPreserveUbChecks | AttributeKind::RustcReallocator | AttributeKind::RustcScalableVector { .. } | AttributeKind::RustcShouldNotBeCalledOnConstItems(..) @@ -406,8 +407,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::register_tool | sym::rustc_no_implicit_bounds | sym::test_runner - | sym::reexport_test_harness_main - | sym::rustc_preserve_ub_checks, + | sym::reexport_test_harness_main, .. ] => {} [name, rest@..] => { diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 2d4e10a0380c8..cfcfffa0fdfbd 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -24,7 +24,7 @@ use rustc_middle::ty::codec::TyEncoder; use rustc_middle::ty::print::with_reduced_queries; use rustc_middle::ty::tls::{self, ImplicitCtxt}; use rustc_middle::ty::{self, TyCtxt}; -use rustc_query_system::dep_graph::{DepNodeParams, HasDepContext}; +use rustc_query_system::dep_graph::{DepNodeParams, FingerprintStyle, HasDepContext}; use rustc_query_system::ich::StableHashingContext; use rustc_query_system::query::{ QueryCache, QueryContext, QueryDispatcher, QueryJobId, QueryMap, QuerySideEffect, @@ -519,7 +519,11 @@ pub(crate) fn make_dep_kind_vtable_for_query<'tcx, Q>( where Q: QueryDispatcherUnerased<'tcx>, { - let fingerprint_style = ::Key::fingerprint_style(); + let fingerprint_style = if is_anon { + FingerprintStyle::Opaque + } else { + ::Key::fingerprint_style() + }; if is_anon || !fingerprint_style.reconstructible() { return DepKindVTable { diff --git a/compiler/rustc_query_system/src/dep_graph/dep_node.rs b/compiler/rustc_query_system/src/dep_graph/dep_node.rs index 72bdcd2d534d9..b9d35bc5a9379 100644 --- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs +++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs @@ -237,8 +237,9 @@ pub struct DepKindVTable { /// cached within one compiler invocation. pub is_eval_always: bool, - /// Whether the query key can be recovered from the hashed fingerprint. - /// See [DepNodeParams] trait for the behaviour of each key type. + /// Indicates whether and how the query key can be recovered from its hashed fingerprint. + /// + /// The [`DepNodeParams`] trait determines the fingerprint style for each key type. pub fingerprint_style: FingerprintStyle, /// The red/green evaluation system will try to mark a specific DepNode in the diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index 8f714a2c96d65..c3ac1c7bc2d5a 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -39,11 +39,7 @@ pub trait DepContext: Copy { #[inline(always)] fn fingerprint_style(self, kind: DepKind) -> FingerprintStyle { - let vtable = self.dep_kind_vtable(kind); - if vtable.is_anon { - return FingerprintStyle::Opaque; - } - vtable.fingerprint_style + self.dep_kind_vtable(kind).fingerprint_style } #[inline(always)] @@ -148,6 +144,9 @@ impl HasDepContext for (T, Q) { } /// Describes the contents of the fingerprint generated by a given query. +/// +/// This is mainly for determining whether and how we can reconstruct a key +/// from the fingerprint. #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum FingerprintStyle { /// The fingerprint is actually a DefPathHash. @@ -156,7 +155,7 @@ pub enum FingerprintStyle { HirId, /// Query key was `()` or equivalent, so fingerprint is just zero. Unit, - /// Some opaque hash. + /// The fingerprint is an opaque hash, and a key cannot be reconstructed from it. Opaque, } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 75bd2c62f9b47..e33970713b5c3 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -8,6 +8,7 @@ // tidy-alphabetical-start #![allow(internal_features)] +#![cfg_attr(bootstrap, feature(ptr_as_ref_unchecked))] #![feature(arbitrary_self_types)] #![feature(assert_matches)] #![feature(box_patterns)] @@ -18,7 +19,6 @@ #![feature(default_field_values)] #![feature(if_let_guard)] #![feature(iter_intersperse)] -#![feature(ptr_as_ref_unchecked)] #![feature(rustc_attrs)] #![feature(trim_prefix_suffix)] #![recursion_limit = "256"] diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index e8c9d26fb3b51..432ca50b33613 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -97,7 +97,6 @@ // tidy-alphabetical-start #![feature(array_ptr_get)] #![feature(asm_experimental_arch)] -#![feature(bigint_helper_methods)] #![feature(bstr)] #![feature(bstr_internals)] #![feature(cfg_select)] @@ -107,6 +106,7 @@ #![feature(const_destruct)] #![feature(const_eval_select)] #![feature(const_select_unpredictable)] +#![feature(const_unsigned_bigint_helpers)] #![feature(core_intrinsics)] #![feature(coverage_attribute)] #![feature(disjoint_bitor)] @@ -120,6 +120,7 @@ #![feature(ptr_alignment_type)] #![feature(ptr_metadata)] #![feature(set_ptr_value)] +#![feature(signed_bigint_helpers)] #![feature(slice_ptr_get)] #![feature(str_internals)] #![feature(str_split_inclusive_remainder)] @@ -129,6 +130,7 @@ #![feature(unsafe_pinned)] #![feature(utf16_extra)] #![feature(variant_count)] +#![feature(widening_mul)] // tidy-alphabetical-end // // Language features: diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 9a27f8a0b5e65..b21865a9ae546 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -2522,7 +2522,7 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(bigint_helper_methods)] + /// #![feature(signed_bigint_helpers)] /// // Only the most significant word is signed. /// // #[doc = concat!("// 10 MAX (a = 10 × 2^", stringify!($BITS), " + 2^", stringify!($BITS), " - 1)")] @@ -2544,7 +2544,7 @@ macro_rules! int_impl { /// /// assert_eq!((sum1, sum0), (6, 8)); /// ``` - #[unstable(feature = "bigint_helper_methods", issue = "85532")] + #[unstable(feature = "signed_bigint_helpers", issue = "151989")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2625,7 +2625,7 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(bigint_helper_methods)] + /// #![feature(signed_bigint_helpers)] /// // Only the most significant word is signed. /// // #[doc = concat!("// 6 8 (a = 6 × 2^", stringify!($BITS), " + 8)")] @@ -2647,7 +2647,7 @@ macro_rules! int_impl { /// #[doc = concat!("assert_eq!((diff1, diff0), (10, ", stringify!($UnsignedT), "::MAX));")] /// ``` - #[unstable(feature = "bigint_helper_methods", issue = "85532")] + #[unstable(feature = "signed_bigint_helpers", issue = "151989")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2717,12 +2717,12 @@ macro_rules! int_impl { /// Please note that this example is shared among integer types, which is why `i32` is used. /// /// ``` - /// #![feature(bigint_helper_methods)] + /// #![feature(widening_mul)] /// assert_eq!(5i32.widening_mul(-2), (4294967286, -1)); /// assert_eq!(1_000_000_000i32.widening_mul(-10), (2884901888, -3)); /// ``` - #[unstable(feature = "bigint_helper_methods", issue = "85532")] - #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] + #[unstable(feature = "widening_mul", issue = "152016")] + #[rustc_const_unstable(feature = "widening_mul", issue = "152016")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2747,7 +2747,7 @@ macro_rules! int_impl { /// Please note that this example is shared among integer types, which is why `i32` is used. /// /// ``` - /// #![feature(bigint_helper_methods)] + /// #![feature(signed_bigint_helpers)] /// assert_eq!(5i32.carrying_mul(-2, 0), (4294967286, -1)); /// assert_eq!(5i32.carrying_mul(-2, 10), (0, 0)); /// assert_eq!(1_000_000_000i32.carrying_mul(-10, 0), (2884901888, -3)); @@ -2757,8 +2757,8 @@ macro_rules! int_impl { "(", stringify!($SelfT), "::MAX.unsigned_abs() + 1, ", stringify!($SelfT), "::MAX / 2));" )] /// ``` - #[unstable(feature = "bigint_helper_methods", issue = "85532")] - #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] + #[unstable(feature = "signed_bigint_helpers", issue = "151989")] + #[rustc_const_unstable(feature = "signed_bigint_helpers", issue = "151989")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2784,7 +2784,7 @@ macro_rules! int_impl { /// Please note that this example is shared among integer types, which is why `i32` is used. /// /// ``` - /// #![feature(bigint_helper_methods)] + /// #![feature(signed_bigint_helpers)] /// assert_eq!(5i32.carrying_mul_add(-2, 0, 0), (4294967286, -1)); /// assert_eq!(5i32.carrying_mul_add(-2, 10, 10), (10, 0)); /// assert_eq!(1_000_000_000i32.carrying_mul_add(-10, 0, 0), (2884901888, -3)); @@ -2794,8 +2794,8 @@ macro_rules! int_impl { "(", stringify!($UnsignedT), "::MAX, ", stringify!($SelfT), "::MAX / 2));" )] /// ``` - #[unstable(feature = "bigint_helper_methods", issue = "85532")] - #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] + #[unstable(feature = "signed_bigint_helpers", issue = "151989")] + #[rustc_const_unstable(feature = "signed_bigint_helpers", issue = "151989")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index c48320c0eab3d..5c263ea845cc2 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -2807,7 +2807,7 @@ macro_rules! uint_impl { /// assert_eq!((sum1, sum0), (9, 6)); /// ``` #[stable(feature = "unsigned_bigint_helpers", since = "1.91.0")] - #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] + #[rustc_const_unstable(feature = "const_unsigned_bigint_helpers", issue = "152015")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2899,7 +2899,7 @@ macro_rules! uint_impl { #[doc = concat!("assert_eq!((diff1, diff0), (3, ", stringify!($SelfT), "::MAX));")] /// ``` #[stable(feature = "unsigned_bigint_helpers", since = "1.91.0")] - #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] + #[rustc_const_unstable(feature = "const_unsigned_bigint_helpers", issue = "152015")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -3011,14 +3011,14 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(bigint_helper_methods)] + /// #![feature(widening_mul)] #[doc = concat!("assert_eq!(5_", stringify!($SelfT), ".widening_mul(7), (35, 0));")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.widening_mul(", stringify!($SelfT), "::MAX), (1, ", stringify!($SelfT), "::MAX - 1));")] /// ``` /// /// Compared to other `*_mul` methods: /// ``` - /// #![feature(bigint_helper_methods)] + /// #![feature(widening_mul)] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::widening_mul(1 << ", stringify!($BITS_MINUS_ONE), ", 6), (0, 3));")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::overflowing_mul(1 << ", stringify!($BITS_MINUS_ONE), ", 6), (0, true));")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::wrapping_mul(1 << ", stringify!($BITS_MINUS_ONE), ", 6), 0);")] @@ -3028,12 +3028,12 @@ macro_rules! uint_impl { /// Please note that this example is shared among integer types, which is why `u32` is used. /// /// ``` - /// #![feature(bigint_helper_methods)] + /// #![feature(widening_mul)] /// assert_eq!(5u32.widening_mul(2), (10, 0)); /// assert_eq!(1_000_000_000u32.widening_mul(10), (1410065408, 2)); /// ``` - #[unstable(feature = "bigint_helper_methods", issue = "85532")] - #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] + #[unstable(feature = "widening_mul", issue = "152016")] + #[rustc_const_unstable(feature = "widening_mul", issue = "152016")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -3072,7 +3072,7 @@ macro_rules! uint_impl { /// implementing it for wider-than-native types. /// /// ``` - /// #![feature(bigint_helper_methods)] + /// #![feature(const_unsigned_bigint_helpers)] /// fn scalar_mul_eq(little_endian_digits: &mut Vec, multiplicand: u16) { /// let mut carry = 0; /// for d in little_endian_digits.iter_mut() { @@ -3097,7 +3097,7 @@ macro_rules! uint_impl { /// except that it gives the value of the overflow instead of just whether one happened: /// /// ``` - /// #![feature(bigint_helper_methods)] + /// #![feature(const_unsigned_bigint_helpers)] /// let r = u8::carrying_mul(7, 13, 0); /// assert_eq!((r.0, r.1 != 0), u8::overflowing_mul(7, 13)); /// let r = u8::carrying_mul(13, 42, 0); @@ -3109,14 +3109,14 @@ macro_rules! uint_impl { /// [`wrapping_add`](Self::wrapping_add) methods: /// /// ``` - /// #![feature(bigint_helper_methods)] + /// #![feature(const_unsigned_bigint_helpers)] /// assert_eq!( /// 789_u16.carrying_mul(456, 123).0, /// 789_u16.wrapping_mul(456).wrapping_add(123), /// ); /// ``` #[stable(feature = "unsigned_bigint_helpers", since = "1.91.0")] - #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] + #[rustc_const_unstable(feature = "const_unsigned_bigint_helpers", issue = "152015")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -3182,7 +3182,7 @@ macro_rules! uint_impl { /// ); /// ``` #[stable(feature = "unsigned_bigint_helpers", since = "1.91.0")] - #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] + #[rustc_const_unstable(feature = "const_unsigned_bigint_helpers", issue = "152015")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 2566d1471ab7f..75777144dfb85 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -239,7 +239,7 @@ impl *const T { /// let ptr: *const u8 = &10u8 as *const u8; /// /// unsafe { - /// let val_back = &*ptr; + /// let val_back = ptr.as_ref_unchecked(); /// assert_eq!(val_back, &10); /// } /// ``` @@ -259,6 +259,7 @@ impl *const T { /// /// [`is_null`]: #method.is_null /// [`as_uninit_ref`]: #method.as_uninit_ref + /// [`as_ref_unchecked`]: #method.as_ref_unchecked #[stable(feature = "ptr_as_ref", since = "1.9.0")] #[rustc_const_stable(feature = "const_ptr_is_null", since = "1.84.0")] #[inline] @@ -283,15 +284,14 @@ impl *const T { /// # Examples /// /// ``` - /// #![feature(ptr_as_ref_unchecked)] /// let ptr: *const u8 = &10u8 as *const u8; /// /// unsafe { /// assert_eq!(ptr.as_ref_unchecked(), &10); /// } /// ``` - // FIXME: mention it in the docs for `as_ref` and `as_uninit_ref` once stabilized. - #[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")] + #[stable(feature = "ptr_as_ref_unchecked", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "ptr_as_ref_unchecked", since = "CURRENT_RUSTC_VERSION")] #[inline] #[must_use] pub const unsafe fn as_ref_unchecked<'a>(self) -> &'a T { diff --git a/library/core/src/ptr/docs/as_ref.md b/library/core/src/ptr/docs/as_ref.md index 0c0d2768c7482..2c7d6e149b76a 100644 --- a/library/core/src/ptr/docs/as_ref.md +++ b/library/core/src/ptr/docs/as_ref.md @@ -1,6 +1,7 @@ Returns `None` if the pointer is null, or else returns a shared reference to the value wrapped in `Some`. If the value may be uninitialized, [`as_uninit_ref`] -must be used instead. +must be used instead. If the value is known to be non-null, [`as_ref_unchecked`] +can be used instead. # Safety @@ -14,6 +15,5 @@ determined to be null or not. See [`is_null`] for more information. # Null-unchecked version -If you are sure the pointer can never be null and are looking for some kind of -`as_ref_unchecked` that returns the `&T` instead of `Option<&T>`, know that you can -dereference the pointer directly. +If you are sure the pointer can never be null, you can use `as_ref_unchecked` which returns +`&mut T` instead of `Option<&mut T>`. diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 20e71bc2a1a56..02e12d56fa659 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -230,7 +230,7 @@ impl *mut T { /// let ptr: *mut u8 = &mut 10u8 as *mut u8; /// /// unsafe { - /// let val_back = &*ptr; + /// let val_back = ptr.as_ref_unchecked(); /// println!("We got back the value: {val_back}!"); /// } /// ``` @@ -252,7 +252,8 @@ impl *mut T { /// For the mutable counterpart see [`as_mut`]. /// /// [`is_null`]: #method.is_null-1 - /// [`as_uninit_ref`]: pointer#method.as_uninit_ref-1 + /// [`as_uninit_ref`]: #method.as_uninit_ref-1 + /// [`as_ref_unchecked`]: #method.as_ref_unchecked-1 /// [`as_mut`]: #method.as_mut #[stable(feature = "ptr_as_ref", since = "1.9.0")] @@ -281,15 +282,14 @@ impl *mut T { /// # Examples /// /// ``` - /// #![feature(ptr_as_ref_unchecked)] /// let ptr: *mut u8 = &mut 10u8 as *mut u8; /// /// unsafe { /// println!("We got back the value: {}!", ptr.as_ref_unchecked()); /// } /// ``` - // FIXME: mention it in the docs for `as_ref` and `as_uninit_ref` once stabilized. - #[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")] + #[stable(feature = "ptr_as_ref_unchecked", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "ptr_as_ref_unchecked", since = "CURRENT_RUSTC_VERSION")] #[inline] #[must_use] pub const unsafe fn as_ref_unchecked<'a>(self) -> &'a T { @@ -531,11 +531,13 @@ impl *mut T { /// Returns `None` if the pointer is null, or else returns a unique reference to /// the value wrapped in `Some`. If the value may be uninitialized, [`as_uninit_mut`] - /// must be used instead. + /// must be used instead. If the value is known to be non-null, [`as_mut_unchecked`] + /// can be used instead. /// /// For the shared counterpart see [`as_ref`]. /// /// [`as_uninit_mut`]: #method.as_uninit_mut + /// [`as_mut_unchecked`]: #method.as_mut_unchecked /// [`as_ref`]: pointer#method.as_ref-1 /// /// # Safety @@ -564,14 +566,13 @@ impl *mut T { /// /// # Null-unchecked version /// - /// If you are sure the pointer can never be null and are looking for some kind of - /// `as_mut_unchecked` that returns the `&mut T` instead of `Option<&mut T>`, know that - /// you can dereference the pointer directly. + /// If you are sure the pointer can never be null, you can use `as_mut_unchecked` which returns + /// `&mut T` instead of `Option<&mut T>`. /// /// ``` /// let mut s = [1, 2, 3]; /// let ptr: *mut u32 = s.as_mut_ptr(); - /// let first_value = unsafe { &mut *ptr }; + /// let first_value = unsafe { ptr.as_mut_unchecked() }; /// *first_value = 4; /// # assert_eq!(s, [4, 2, 3]); /// println!("{s:?}"); // It'll print: "[4, 2, 3]". @@ -603,7 +604,6 @@ impl *mut T { /// # Examples /// /// ``` - /// #![feature(ptr_as_ref_unchecked)] /// let mut s = [1, 2, 3]; /// let ptr: *mut u32 = s.as_mut_ptr(); /// let first_value = unsafe { ptr.as_mut_unchecked() }; @@ -611,8 +611,8 @@ impl *mut T { /// # assert_eq!(s, [4, 2, 3]); /// println!("{s:?}"); // It'll print: "[4, 2, 3]". /// ``` - // FIXME: mention it in the docs for `as_mut` and `as_uninit_mut` once stabilized. - #[unstable(feature = "ptr_as_ref_unchecked", issue = "122034")] + #[stable(feature = "ptr_as_ref_unchecked", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "ptr_as_ref_unchecked", since = "CURRENT_RUSTC_VERSION")] #[inline] #[must_use] pub const unsafe fn as_mut_unchecked<'a>(self) -> &'a mut T { diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 52f3d43dfd6dd..5f438d72ac13c 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -690,7 +690,7 @@ impl Result { /// Converts from `Result` to [`Option`]. /// /// Converts `self` into an [`Option`], consuming `self`, - /// and discarding the error, if any. + /// and converting the error to `None`, if any. /// /// # Examples /// diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 9054eada12fb7..d085e4ad1a8fe 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -8,7 +8,6 @@ #![feature(ascii_char_variants)] #![feature(async_iter_from_iter)] #![feature(async_iterator)] -#![feature(bigint_helper_methods)] #![feature(bool_to_result)] #![feature(bstr)] #![feature(cfg_target_has_reliable_f16_f128)] @@ -34,6 +33,7 @@ #![feature(const_result_trait_fn)] #![feature(const_select_unpredictable)] #![feature(const_trait_impl)] +#![feature(const_unsigned_bigint_helpers)] #![feature(control_flow_ok)] #![feature(core_float_math)] #![feature(core_intrinsics)] @@ -98,6 +98,7 @@ #![feature(portable_simd)] #![feature(ptr_metadata)] #![feature(result_option_map_or_default)] +#![feature(signed_bigint_helpers)] #![feature(slice_from_ptr_range)] #![feature(slice_index_methods)] #![feature(slice_internals)] @@ -122,6 +123,7 @@ #![feature(uint_gather_scatter_bits)] #![feature(unsize)] #![feature(unwrap_infallible)] +#![feature(widening_mul)] // tidy-alphabetical-end #![allow(internal_features)] #![deny(fuzzy_provenance_casts)] diff --git a/library/stdarch/crates/core_arch/src/lib.rs b/library/stdarch/crates/core_arch/src/lib.rs index 3992eaee30fd2..039a4c4411f2e 100644 --- a/library/stdarch/crates/core_arch/src/lib.rs +++ b/library/stdarch/crates/core_arch/src/lib.rs @@ -33,7 +33,6 @@ f16, aarch64_unstable_target_feature, target_feature_inline_always, - bigint_helper_methods, funnel_shifts, avx10_target_feature, const_trait_impl, diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version index 795271ee0ef03..209f4226eae7a 100644 --- a/src/doc/rustc-dev-guide/rust-version +++ b/src/doc/rustc-dev-guide/rust-version @@ -1 +1 @@ -370143facfb348ad3b29749c0393402d76b280c3 +44e34e1ac6d7e69b40856cf1403d3da145319c30 diff --git a/src/doc/rustc-dev-guide/src/autodiff/debugging.md b/src/doc/rustc-dev-guide/src/autodiff/debugging.md index 7c7af8589868f..3b2278f1a0759 100644 --- a/src/doc/rustc-dev-guide/src/autodiff/debugging.md +++ b/src/doc/rustc-dev-guide/src/autodiff/debugging.md @@ -16,7 +16,7 @@ Before generating the llvm-ir, keep in mind two techniques that can help ensure ## 1) Generate an llvm-ir reproducer ```sh -RUSTFLAGS="-Z autodiff=Enable,PrintModbefore" cargo +enzyme build --release &> out.ll +RUSTFLAGS="-Z autodiff=Enable,PrintModBefore" cargo +enzyme build --release &> out.ll ``` This also captures a few warnings and info messages above and below your module. open out.ll and remove every line above `; moduleid = `. Now look at the end of the file and remove everything that's not part of llvm-ir, i.e. remove errors and warnings. The last line of your llvm-ir should now start with `! = `, i.e. `!40831 = !{i32 0, i32 1037508, i32 1037538, i32 1037559}` or `!43760 = !dilocation(line: 297, column: 5, scope: !43746)`. diff --git a/src/doc/rustc-dev-guide/src/backend/debugging.md b/src/doc/rustc-dev-guide/src/backend/debugging.md index 84efa72f4c46d..eaa9e399a0524 100644 --- a/src/doc/rustc-dev-guide/src/backend/debugging.md +++ b/src/doc/rustc-dev-guide/src/backend/debugging.md @@ -6,16 +6,15 @@ [codegen]: ./codegen.md This section is about debugging compiler bugs in code generation (e.g. why the -compiler generated some piece of code or crashed in LLVM). LLVM is a big -project on its own that probably needs to have its own debugging document (not -that I could find one). But here are some tips that are important in a rustc -context: +compiler generated some piece of code or crashed in LLVM). +LLVM is a big project that probably needs to have its own debugging document, +but following are some tips that are important in a rustc context. ### Minimize the example As a general rule, compilers generate lots of information from analyzing code. -Thus, a useful first step is usually to find a minimal example. One way to do -this is to +Thus, a useful first step is usually to find a minimal example. +One way to do this is to 1. create a new crate that reproduces the issue (e.g. adding whatever crate is at fault as a dependency, and using it from there) @@ -35,14 +34,13 @@ For more discussion on methodology for steps 2 and 3 above, there is an The official compilers (including nightlies) have LLVM assertions disabled, which means that LLVM assertion failures can show up as compiler crashes (not -ICEs but "real" crashes) and other sorts of weird behavior. If you are -encountering these, it is a good idea to try using a compiler with LLVM +ICEs but "real" crashes) and other sorts of weird behavior. +If you are encountering these, it is a good idea to try using a compiler with LLVM assertions enabled - either an "alt" nightly or a compiler you build yourself -by setting `[llvm] assertions=true` in your bootstrap.toml - and see whether -anything turns up. +by setting `llvm.assertions = true` in your bootstrap.toml - and see whether anything turns up. -The rustc build process builds the LLVM tools into -`./build//llvm/bin`. They can be called directly. +The rustc build process builds the LLVM tools into `build/host/llvm/bin`. +They can be called directly. These tools include: * [`llc`], which compiles bitcode (`.bc` files) to executable code; this can be used to replicate LLVM backend bugs. @@ -55,9 +53,10 @@ These tools include: [`bugpoint`]: https://llvm.org/docs/Bugpoint.html By default, the Rust build system does not check for changes to the LLVM source code or -its build configuration settings. So, if you need to rebuild the LLVM that is linked +its build configuration settings. +So, if you need to rebuild the LLVM that is linked into `rustc`, first delete the file `.llvm-stamp`, which should be located -in `build//llvm/`. +in `build/host/llvm/`. The default rustc compilation pipeline has multiple codegen units, which is hard to replicate manually and means that LLVM is called multiple times in @@ -66,26 +65,27 @@ disappear), passing `-C codegen-units=1` to rustc will make debugging easier. ### Get your hands on raw LLVM input -For rustc to generate LLVM IR, you need to pass the `--emit=llvm-ir` flag. If -you are building via cargo, use the `RUSTFLAGS` environment variable (e.g. -`RUSTFLAGS='--emit=llvm-ir'`). This causes rustc to spit out LLVM IR into the -target directory. +For rustc to generate LLVM IR, you need to pass the `--emit=llvm-ir` flag. +If you are building via cargo, +use the `RUSTFLAGS` environment variable (e.g. `RUSTFLAGS='--emit=llvm-ir'`). +This causes rustc to spit out LLVM IR into the target directory. -`cargo llvm-ir [options] path` spits out the LLVM IR for a particular function -at `path`. (`cargo install cargo-asm` installs `cargo asm` and `cargo -llvm-ir`). `--build-type=debug` emits code for debug builds. There are also -other useful options. Also, debug info in LLVM IR can clutter the output a lot: +`cargo llvm-ir [options] path` spits out the LLVM IR for a particular function at `path`. +(`cargo install cargo-asm` installs `cargo asm` and `cargo llvm-ir`). +`--build-type=debug` emits code for debug builds. +There are also other useful options. +Also, debug info in LLVM IR can clutter the output a lot: `RUSTFLAGS="-C debuginfo=0"` is really useful. `RUSTFLAGS="-C save-temps"` outputs LLVM bitcode at -different stages during compilation, which is sometimes useful. The output LLVM -bitcode will be in `.bc` files in the compiler's output directory, set via the +different stages during compilation, which is sometimes useful. +The output LLVM bitcode will be in `.bc` files in the compiler's output directory, set via the `--out-dir DIR` argument to `rustc`. * If you are hitting an assertion failure or segmentation fault from the LLVM backend when invoking `rustc` itself, it is a good idea to try passing each - of these `.bc` files to the `llc` command, and see if you get the same - failure. (LLVM developers often prefer a bug reduced to a `.bc` file over one + of these `.bc` files to the `llc` command, and see if you get the same failure. + (LLVM developers often prefer a bug reduced to a `.bc` file over one that uses a Rust crate for its minimized reproduction.) * To get human readable versions of the LLVM bitcode, one just needs to convert @@ -100,7 +100,7 @@ you should: ```bash $ rustc +local my-file.rs --emit=llvm-ir -O -C no-prepopulate-passes \ -C codegen-units=1 -$ OPT=./build/$TRIPLE/llvm/bin/opt +$ OPT=build/$TRIPLE/llvm/bin/opt $ $OPT -S -O2 < my-file.ll > my ``` @@ -112,8 +112,8 @@ llvm-args='-filter-print-funcs=EXACT_FUNCTION_NAME` (e.g. `-C llvm-args='-filter-print-funcs=_ZN11collections3str21_$LT$impl$u20$str$GT$\ 7replace17hbe10ea2e7c809b0bE'`). -That produces a lot of output into standard error, so you'll want to pipe that -to some file. Also, if you are using neither `-filter-print-funcs` nor `-C +That produces a lot of output into standard error, so you'll want to pipe that to some file. +Also, if you are using neither `-filter-print-funcs` nor `-C codegen-units=1`, then, because the multiple codegen units run in parallel, the printouts will mix together and you won't be able to read anything. @@ -125,8 +125,8 @@ printouts will mix together and you won't be able to read anything. * Within LLVM itself, calling `F.getParent()->dump()` at the beginning of `SafeStackLegacyPass::runOnFunction` will dump the whole module, which - may provide better basis for reproduction. (However, you - should be able to get that same dump from the `.bc` files dumped by + may provide better basis for reproduction. + (However, you should be able to get that same dump from the `.bc` files dumped by `-C save-temps`.) If you want just the IR for a specific function (say, you want to see why it @@ -145,29 +145,29 @@ $ ./build/$TRIPLE/llvm/bin/llvm-extract \ If you are seeing incorrect behavior due to an optimization pass, a very handy LLVM option is `-opt-bisect-limit`, which takes an integer denoting the index -value of the highest pass to run. Index values for taken passes are stable +value of the highest pass to run. +Index values for taken passes are stable from run to run; by coupling this with software that automates bisecting the -search space based on the resulting program, an errant pass can be quickly -determined. When an `-opt-bisect-limit` is specified, all runs are displayed +search space based on the resulting program, an errant pass can be quickly determined. +When an `-opt-bisect-limit` is specified, all runs are displayed to standard error, along with their index and output indicating if the pass was run or skipped. Setting the limit to an index of -1 (e.g., `RUSTFLAGS="-C llvm-args=-opt-bisect-limit=-1"`) will show all passes and their corresponding index values. If you want to play with the optimization pipeline, you can use the [`opt`] tool -from `./build//llvm/bin/` with the LLVM IR emitted by rustc. +from `./build/host/llvm/bin/` with the LLVM IR emitted by rustc. When investigating the implementation of LLVM itself, you should be aware of its [internal debug infrastructure][llvm-debug]. This is provided in LLVM Debug builds, which you enable for rustc LLVM builds by changing this setting in the bootstrap.toml: ``` -[llvm] # Indicates whether the LLVM assertions are enabled or not -assertions = true +llvm.assertions = true # Indicates whether the LLVM build is a Release or Debug build -optimize = false +llvm.optimize = false ``` The quick summary is: * Setting `assertions=true` enables coarse-grain debug messaging. @@ -190,8 +190,8 @@ specifically the `#t-compiler/wg-llvm` channel. ### Compiler options to know and love The `-C help` and `-Z help` compiler switches will list out a variety -of interesting options you may find useful. Here are a few of the most -common that pertain to LLVM development (some of them are employed in the +of interesting options you may find useful. +Here are a few of the most common that pertain to LLVM development (some of them are employed in the tutorial above): - The `--emit llvm-ir` option emits a `.ll` file with LLVM IR in textual format @@ -201,7 +201,8 @@ tutorial above): e.g. `-C llvm-args=-print-before-all` to print IR before every LLVM pass. - The `-C no-prepopulate-passes` will avoid pre-populate the LLVM pass - manager with a list of passes. This will allow you to view the LLVM + manager with a list of passes. + This will allow you to view the LLVM IR that rustc generates, not the LLVM IR after optimizations. - The `-C passes=val` option allows you to supply a space separated list of extra LLVM passes to run - The `-C save-temps` option saves all temporary output files during compilation @@ -211,18 +212,17 @@ tutorial above): - The `-Z no-parallel-backend` will disable parallel compilation of distinct compilation units - The `-Z llvm-time-trace` option will output a Chrome profiler compatible JSON file which contains details and timings for LLVM passes. -- The `-C llvm-args=-opt-bisect-limit=` option allows for bisecting LLVM - optimizations. +- The `-C llvm-args=-opt-bisect-limit=` option allows for bisecting LLVM optimizations. ### Filing LLVM bug reports When filing an LLVM bug report, you will probably want some sort of minimal -working example that demonstrates the problem. The Godbolt compiler explorer is -really helpful for this. +working example that demonstrates the problem. +The Godbolt compiler explorer is really helpful for this. 1. Once you have some LLVM IR for the problematic code (see above), you can -create a minimal working example with Godbolt. Go to -[llvm.godbolt.org](https://llvm.godbolt.org). +create a minimal working example with Godbolt. +Go to [llvm.godbolt.org](https://llvm.godbolt.org). 2. Choose `LLVM-IR` as programming language. @@ -230,8 +230,7 @@ create a minimal working example with Godbolt. Go to - There are some useful flags: `-mattr` enables target features, `-march=` selects the target, `-mcpu=` selects the CPU, etc. - Commands like `llc -march=help` output all architectures available, which - is useful because sometimes the Rust arch names and the LLVM names do not - match. + is useful because sometimes the Rust arch names and the LLVM names do not match. - If you have compiled rustc yourself somewhere, in the target directory you have binaries for `llc`, `opt`, etc. @@ -239,7 +238,8 @@ create a minimal working example with Godbolt. Go to optimizations transform it. 5. Once you have a godbolt link demonstrating the issue, it is pretty easy to - fill in an LLVM bug. Just visit their [github issues page][llvm-issues]. + fill in an LLVM bug. + Just visit their [github issues page][llvm-issues]. [llvm-issues]: https://github.com/llvm/llvm-project/issues @@ -251,8 +251,8 @@ gotten the fix yet (or perhaps you are familiar enough with LLVM to fix it yours In that case, we can sometimes opt to port the fix for the bug directly to our own LLVM fork, so that rustc can use it more easily. -Our fork of LLVM is maintained in [rust-lang/llvm-project]. Once -you've landed the fix there, you'll also need to land a PR modifying +Our fork of LLVM is maintained in [rust-lang/llvm-project]. +Once you've landed the fix there, you'll also need to land a PR modifying our submodule commits -- ask around on Zulip for help. [rust-lang/llvm-project]: https://github.com/rust-lang/llvm-project/ diff --git a/src/doc/rustc-dev-guide/src/backend/updating-llvm.md b/src/doc/rustc-dev-guide/src/backend/updating-llvm.md index 70deeebf8bec4..3d0e130b6aaa6 100644 --- a/src/doc/rustc-dev-guide/src/backend/updating-llvm.md +++ b/src/doc/rustc-dev-guide/src/backend/updating-llvm.md @@ -3,16 +3,16 @@ Rust supports building against multiple LLVM versions: -* Tip-of-tree for the current LLVM development branch is usually supported - within a few days. PRs for such fixes are tagged with `llvm-main`. +* Tip-of-tree for the current LLVM development branch is usually supported within a few days. + PRs for such fixes are tagged with `llvm-main`. * The latest released major version is always supported. * The one or two preceding major versions are usually supported. By default, Rust uses its own fork in the [rust-lang/llvm-project repository]. This fork is based on a `release/$N.x` branch of the upstream project, where `$N` is either the latest released major version, or the current major version -in release candidate phase. The fork is never based on the `main` development -branch. +in release candidate phase. +The fork is never based on the `main` development branch. Our LLVM fork only accepts: @@ -32,16 +32,15 @@ There are three types of LLVM updates, with different procedures: ## Backports (upstream supported) While the current major LLVM version is supported upstream, fixes should be -backported upstream first, and the release branch then merged back into the -Rust fork. +backported upstream first, and the release branch then merged back into the Rust fork. 1. Make sure the bugfix is in upstream LLVM. -2. If this hasn't happened already, request a backport to the upstream release - branch. If you have LLVM commit access, follow the [backport process]. - Otherwise, open an issue requesting the backport. Continue once the - backport has been approved and merged. -3. Identify the branch that rustc is currently using. The `src/llvm-project` - submodule is always pinned to a branch of the +2. If this hasn't happened already, request a backport to the upstream release branch. + If you have LLVM commit access, follow the [backport process]. + Otherwise, open an issue requesting the backport. + Continue once the backport has been approved and merged. +3. Identify the branch that rustc is currently using. + The `src/llvm-project` submodule is always pinned to a branch of the [rust-lang/llvm-project repository]. 4. Fork the rust-lang/llvm-project repository. 5. Check out the appropriate branch (typically named `rustc/a.b-yyyy-mm-dd`). @@ -51,26 +50,23 @@ Rust fork. 7. Merge the `upstream/release/$N.x` branch. 8. Push this branch to your fork. 9. Send a Pull Request to rust-lang/llvm-project to the same branch as before. - Be sure to reference the Rust and/or LLVM issue that you're fixing in the PR - description. + Be sure to reference the Rust and/or LLVM issue that you're fixing in the PR description. 10. Wait for the PR to be merged. -11. Send a PR to rust-lang/rust updating the `src/llvm-project` submodule with - your bugfix. This can be done locally with `git submodule update --remote - src/llvm-project` typically. +11. Send a PR to rust-lang/rust updating the `src/llvm-project` submodule with your bugfix. + This can be done locally with `git submodule update --remote src/llvm-project` typically. 12. Wait for PR to be merged. -An example PR: -[#59089](https://github.com/rust-lang/rust/pull/59089) +An example PR: [#59089](https://github.com/rust-lang/rust/pull/59089) ## Backports (upstream not supported) -Upstream LLVM releases are only supported for two to three months after the -GA release. Once upstream backports are no longer accepted, changes should be +Upstream LLVM releases are only supported for two to three months after the GA release. +Once upstream backports are no longer accepted, changes should be cherry-picked directly to our fork. 1. Make sure the bugfix is in upstream LLVM. -2. Identify the branch that rustc is currently using. The `src/llvm-project` - submodule is always pinned to a branch of the +2. Identify the branch that rustc is currently using. + The `src/llvm-project` submodule is always pinned to a branch of the [rust-lang/llvm-project repository]. 3. Fork the rust-lang/llvm-project repository. 4. Check out the appropriate branch (typically named `rustc/a.b-yyyy-mm-dd`). @@ -80,16 +76,13 @@ cherry-picked directly to our fork. 6. Cherry-pick the relevant commit(s) using `git cherry-pick -x`. 7. Push this branch to your fork. 8. Send a Pull Request to rust-lang/llvm-project to the same branch as before. - Be sure to reference the Rust and/or LLVM issue that you're fixing in the PR - description. + Be sure to reference the Rust and/or LLVM issue that you're fixing in the PR description. 9. Wait for the PR to be merged. -10. Send a PR to rust-lang/rust updating the `src/llvm-project` submodule with - your bugfix. This can be done locally with `git submodule update --remote - src/llvm-project` typically. +10. Send a PR to rust-lang/rust updating the `src/llvm-project` submodule with your bugfix. + This can be done locally with `git submodule update --remote src/llvm-project` typically. 11. Wait for PR to be merged. -An example PR: -[#59089](https://github.com/rust-lang/rust/pull/59089) +An example PR: [#59089](https://github.com/rust-lang/rust/pull/59089) ## New LLVM Release Updates @@ -110,14 +103,12 @@ so let's go through each in detail. 1. Create a new branch in the [rust-lang/llvm-project repository] from this `release/$N.x` branch, and name it `rustc/a.b-yyyy-mm-dd`, - where `a.b` is the current version number of LLVM in-tree - at the time of the branch, + where `a.b` is the current version number of LLVM in-tree at the time of the branch, and the remaining part is the current date. 1. Apply Rust-specific patches to the llvm-project repository. All features and bugfixes are upstream, - but there's often some weird build-related patches - that don't make sense to upstream. + but there's often some weird build-related patches that don't make sense to upstream. These patches are typically the latest patches in the rust-lang/llvm-project branch that rustc is currently using. @@ -145,13 +136,14 @@ so let's go through each in detail. This is done by having the following setting in `bootstrap.toml`: ```toml - [llvm] - download-ci-llvm = false + llvm.download-ci-llvm = false ``` -1. Test for regressions across other platforms. LLVM often has at least one bug +1. Test for regressions across other platforms. + LLVM often has at least one bug for non-tier-1 architectures, so it's good to do some more testing before - sending this to bors! If you're low on resources you can send the PR as-is + sending this to bors! + If you're low on resources you can send the PR as-is now to bors, though, and it'll get tested anyway. Ideally, build LLVM and test it on a few platforms: @@ -168,9 +160,11 @@ so let's go through each in detail. * `./src/ci/docker/run.sh dist-various-2` * `./src/ci/docker/run.sh armhf-gnu` -1. Prepare a PR to `rust-lang/rust`. Work with maintainers of +1. Prepare a PR to `rust-lang/rust`. + Work with maintainers of `rust-lang/llvm-project` to get your commit in a branch of that repository, - and then you can send a PR to `rust-lang/rust`. You'll change at least + and then you can send a PR to `rust-lang/rust`. + You'll change at least `src/llvm-project` and will likely also change [`llvm-wrapper`] as well. @@ -192,14 +186,12 @@ so let's go through each in detail. We will often want to have those bug fixes as well. The merge process for that is to use `git merge` itself to merge LLVM's `release/a.b` branch with the branch created in step 2. - This is typically - done multiple times when necessary while LLVM's release branch is baking. + This is typically done multiple times when necessary while LLVM's release branch is baking. 1. LLVM then announces the release of version `a.b`. 1. After LLVM's official release, - we follow the process of creating a new branch on the - rust-lang/llvm-project repository again, + we follow the process of creating a new branch on the rust-lang/llvm-project repository again, this time with a new date. It is only then that the PR to update Rust to use that version is merged. diff --git a/src/doc/rustc-dev-guide/src/building/compiler-documenting.md b/src/doc/rustc-dev-guide/src/building/compiler-documenting.md index b031462ea15fb..026a42907493f 100644 --- a/src/doc/rustc-dev-guide/src/building/compiler-documenting.md +++ b/src/doc/rustc-dev-guide/src/building/compiler-documenting.md @@ -39,8 +39,7 @@ like the standard library (std) or the compiler (rustc). To create it by default with `x doc`, modify `bootstrap.toml`: ```toml - [build] - compiler-docs = true + build.compiler-docs = true ``` Note that when enabled, diff --git a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md index d0a38b12c550f..fc8fe402bfa9e 100644 --- a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md +++ b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md @@ -4,22 +4,25 @@ For `profile = "library"` users, or users who use `download-rustc = true | "if-unchanged"`, please be advised that the `./x test library/std` flow where `download-rustc` is active (i.e. no compiler changes) is currently broken. -This is tracked in . Only the `./x test` flow is affected in this +This is tracked in . +Only the `./x test` flow is affected in this case, `./x {check,build} library/std` should still work. -In the short-term, you may need to disable `download-rustc` for `./x test library/std`. This can be done either by: +In the short-term, you may need to disable `download-rustc` for `./x test library/std`. +This can be done either by: 1. `./x test library/std --set rust.download-rustc=false` -2. Or set `rust.download-rustc=false` in `bootstrap.toml`. +2. Or set `rust.download-rustc = false` in `bootstrap.toml`. -Unfortunately that will require building the stage 1 compiler. The bootstrap team is working on this, but +Unfortunately that will require building the stage 1 compiler. +The bootstrap team is working on this, but implementing a maintainable fix is taking some time. -The compiler is built using a tool called `x.py`. You will need to -have Python installed to run it. +The compiler is built using a tool called `x.py`. +You will need to have Python installed to run it. ## Quick Start @@ -28,7 +31,8 @@ For a less in-depth quick-start of getting the compiler running, see [quickstart ## Get the source code -The main repository is [`rust-lang/rust`][repo]. This contains the compiler, +The main repository is [`rust-lang/rust`][repo]. +This contains the compiler, the standard library (including `core`, `alloc`, `test`, `proc_macro`, etc), and a bunch of tools (e.g. `rustdoc`, the bootstrapping infrastructure, etc). @@ -86,8 +90,8 @@ cd rust ## What is `x.py`? -`x.py` is the build tool for the `rust` repository. It can build docs, run tests, and compile the -compiler and standard library. +`x.py` is the build tool for the `rust` repository. +It can build docs, run tests, and build the compiler and standard library. This chapter focuses on the basics to be productive, but if you want to learn more about `x.py`, [read this chapter][bootstrap]. @@ -103,11 +107,13 @@ Also, using `x` rather than `x.py` is recommended as: (You can find the platform related scripts around the `x.py`, like `x.ps1`) -Notice that this is not absolute. For instance, using Nushell in VSCode on Win10, -typing `x` or `./x` still opens `x.py` in an editor rather than invoking the program. :) +Notice that this is not absolute. +For instance, using Nushell in VSCode on Win10, +typing `x` or `./x` still opens `x.py` in an editor rather than invoking the program. +:) -In the rest of this guide, we use `x` rather than `x.py` directly. The following -command: +In the rest of this guide, we use `x` rather than `x.py` directly. +The following command: ```bash ./x check @@ -164,9 +170,10 @@ Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser #### Running `x.py` slightly more conveniently -There is a binary that wraps `x.py` called `x` in `src/tools/x`. All it does is -run `x.py`, but it can be installed system-wide and run from any subdirectory -of a checkout. It also looks up the appropriate version of `python` to use. +There is a binary that wraps `x.py` called `x` in `src/tools/x`. +All it does is run `x.py`, but it can be installed system-wide and run from any subdirectory +of a checkout. +It also looks up the appropriate version of `python` to use. You can install it with `cargo install --path src/tools/x`. @@ -177,18 +184,20 @@ shell to run the platform related scripts. ## Create a `bootstrap.toml` -To start, run `./x setup` and select the `compiler` defaults. This will do some initialization -and create a `bootstrap.toml` for you with reasonable defaults. If you use a different default (which +To start, run `./x setup` and select the `compiler` defaults. +This will do some initialization and create a `bootstrap.toml` for you with reasonable defaults. +If you use a different default (which you'll likely want to do if you want to contribute to an area of rust other than the compiler, such as rustdoc), make sure to read information about that default (located in `src/bootstrap/defaults`) as the build process may be different for other defaults. -Alternatively, you can write `bootstrap.toml` by hand. See `bootstrap.example.toml` for all the available -settings and explanations of them. See `src/bootstrap/defaults` for common settings to change. +Alternatively, you can write `bootstrap.toml` by hand. +See `bootstrap.example.toml` for all the available settings and what they do. +See `src/bootstrap/defaults` for common settings to change. If you have already built `rustc` and you change settings related to LLVM, then you may have to -execute `./x clean --all` for subsequent configuration changes to take effect. Note that `./x -clean` will not cause a rebuild of LLVM. +execute `./x clean --all` for subsequent configuration changes to take effect. +Note that `./x clean` will not cause a rebuild of LLVM. ## Common `x` commands @@ -202,28 +211,28 @@ working on `rustc`, `std`, `rustdoc`, and other tools. | `./x test` | Runs all tests | | `./x fmt` | Formats all code | -As written, these commands are reasonable starting points. However, there are -additional options and arguments for each of them that are worth learning for -serious development work. In particular, `./x build` and `./x test` -provide many ways to compile or test a subset of the code, which can save a lot -of time. +As written, these commands are reasonable starting points. +However, there are additional options and arguments for each of them that are worth learning for +serious development work. +In particular, `./x build` and `./x test` +provide many ways to compile or test a subset of the code, which can save a lot of time. Also, note that `x` supports all kinds of path suffixes for `compiler`, `library`, -and `src/tools` directories. So, you can simply run `x test tidy` instead of -`x test src/tools/tidy`. Or, `x build std` instead of `x build library/std`. +and `src/tools` directories. +So, you can simply run `x test tidy` instead of `x test src/tools/tidy`. +Or, `x build std` instead of `x build library/std`. [rust-analyzer]: suggested.html#configuring-rust-analyzer-for-rustc -See the chapters on -[testing](../tests/running.md) and [rustdoc](../rustdoc.md) for more details. +See the chapters on [testing](../tests/running.md) and [rustdoc](../rustdoc.md) for more details. ### Building the compiler Note that building will require a relatively large amount of storage space. You may want to have upwards of 10 or 15 gigabytes available to build the compiler. -Once you've created a `bootstrap.toml`, you are now ready to run -`x`. There are a lot of options here, but let's start with what is +Once you've created a `bootstrap.toml`, you are now ready to run `x`. +There are a lot of options here, but let's start with what is probably the best "go to" command for building a local compiler: ```console @@ -236,8 +245,7 @@ What this command does is: - Assemble a working stage1 sysroot, containing the stage1 compiler and stage1 standard libraries. This final product (stage1 compiler + libs built using that compiler) -is what you need to build other Rust programs (unless you use `#![no_std]` or -`#![no_core]`). +is what you need to build other Rust programs (unless you use `#![no_std]` or `#![no_core]`). You will probably find that building the stage1 `std` is a bottleneck for you, but fear not, there is a (hacky) workaround... @@ -245,12 +253,12 @@ see [the section on avoiding rebuilds for std][keep-stage]. [keep-stage]: ./suggested.md#faster-rebuilds-with---keep-stage-std -Sometimes you don't need a full build. When doing some kind of -"type-based refactoring", like renaming a method, or changing the +Sometimes you don't need a full build. +When doing some kind of "type-based refactoring", like renaming a method, or changing the signature of some function, you can use `./x check` instead for a much faster build. -Note that this whole command just gives you a subset of the full `rustc` -build. The **full** `rustc` build (what you get with `./x build +Note that this whole command just gives you a subset of the full `rustc` build. +The **full** `rustc` build (what you get with `./x build --stage 2 rustc`) has quite a few more steps: - Build `rustc` with the stage1 compiler. @@ -262,8 +270,8 @@ You almost never need to do this. ### Build specific components If you are working on the standard library, you probably don't need to build -every other default component. Instead, you can build a specific component by -providing its name, like this: +every other default component. +Instead, you can build a specific component by providing its name, like this: ```bash ./x build --stage 1 library @@ -275,12 +283,13 @@ default). ## Creating a rustup toolchain Once you have successfully built `rustc`, you will have created a bunch -of files in your `build` directory. In order to actually run the -resulting `rustc`, we recommend creating rustup toolchains. The first -command listed below creates the stage1 toolchain, which was built in the -steps above, with the name `stage1`. The second command creates the stage2 -toolchain using the stage1 compiler. This will be needed in the future -if running the entire test suite, but will not be built in this page. +of files in your `build` directory. +In order to actually run the resulting `rustc`, we recommend creating rustup toolchains. +The first command listed below creates the stage1 toolchain, which was built in the +steps above, with the name `stage1`. +The second command creates the stage2 toolchain using the stage1 compiler. +This will be needed in the future +if running the entire test suite, but will not be built in this page. Building stage2 is done with the same `./x build` command as for stage1, specifying that the stage is 2 instead. @@ -289,8 +298,8 @@ rustup toolchain link stage1 build/host/stage1 rustup toolchain link stage2 build/host/stage2 ``` -Now you can run the `rustc` you built with via the toolchain. If you run with -`-vV`, you should see a version number ending in `-dev`, indicating a build from +Now you can run the `rustc` you built with via the toolchain. +If you run with `-vV`, you should see a version number ending in `-dev`, indicating a build from your local environment: ```bash @@ -308,15 +317,19 @@ The rustup toolchain points to the specified toolchain compiled in your `build` so the rustup toolchain will be updated whenever `x build` or `x test` are run for that toolchain/stage. -**Note:** the toolchain we've built does not include `cargo`. In this case, `rustup` will +**Note:** the toolchain we've built does not include `cargo`. + In this case, `rustup` will fall back to using `cargo` from the installed `nightly`, `beta`, or `stable` toolchain -(in that order). If you need to use unstable `cargo` flags, be sure to run -`rustup install nightly` if you haven't already. See the +(in that order). + If you need to use unstable `cargo` flags, be sure to run +`rustup install nightly` if you haven't already. + See the [rustup documentation on custom toolchains](https://rust-lang.github.io/rustup/concepts/toolchains.html#custom-toolchains). **Note:** rust-analyzer and IntelliJ Rust plugin use a component called -`rust-analyzer-proc-macro-srv` to work with proc macros. If you intend to use a -custom toolchain for a project (e.g. via `rustup override set stage1`) you may +`rust-analyzer-proc-macro-srv` to work with proc macros. +If you intend to use a +custom toolchain for a project (e.g. via `rustup override set stage1`), you may want to build this component: ```bash @@ -342,8 +355,7 @@ If you want to always build for other targets without needing to pass flags to ` you can configure this in the `[build]` section of your `bootstrap.toml` like so: ```toml -[build] -target = ["x86_64-unknown-linux-gnu", "wasm32-wasip1"] +build.target = ["x86_64-unknown-linux-gnu", "wasm32-wasip1"] ``` Note that building for some targets requires having external dependencies installed @@ -369,16 +381,14 @@ cargo +stage1 build --target wasm32-wasip1 ## Other `x` commands -Here are a few other useful `x` commands. We'll cover some of them in detail -in other sections: +Here are a few other useful `x` commands. +We'll cover some of them in detail in other sections: - Building things: - `./x build` – builds everything using the stage 1 compiler, not just up to `std` - - `./x build --stage 2` – builds everything with the stage 2 compiler including - `rustdoc` -- Running tests (see the [section on running tests](../tests/running.html) for - more details): + - `./x build --stage 2` – builds everything with the stage 2 compiler including `rustdoc` +- Running tests (see the [section on running tests](../tests/running.html) for more details): - `./x test library/std` – runs the unit tests and integration tests from `std` - `./x test tests/ui` – runs the `ui` test suite - `./x test tests/ui/const-generics` - runs all the tests in @@ -390,8 +400,8 @@ in other sections: Sometimes you need to start fresh, but this is normally not the case. If you need to run this then bootstrap is most likely not acting right and -you should file a bug as to what is going wrong. If you do need to clean -everything up then you only need to run one command! +you should file a bug as to what is going wrong. +If you do need to clean everything up then you only need to run one command! ```bash ./x clean @@ -403,15 +413,17 @@ a long time even on fast computers. ## Remarks on disk space Building the compiler (especially if beyond stage 1) can require significant amounts of free disk -space, possibly around 100GB. This is compounded if you have a separate build directory for +space, possibly around 100GB. +This is compounded if you have a separate build directory for rust-analyzer (e.g. `build-rust-analyzer`). This is easy to hit with dev-desktops which have a [set disk quota](https://github.com/rust-lang/simpleinfra/blob/8a59e4faeb75a09b072671c74a7cb70160ebef50/ansible/roles/dev-desktop/defaults/main.yml#L7) -for each user, but this also applies to local development as well. Occasionally, you may need to: +for each user, but this also applies to local development as well. +Occasionally, you may need to: - Remove `build/` directory. - Remove `build-rust-analyzer/` directory (if you have a separate rust-analyzer build directory). -- Uninstall unnecessary toolchains if you use `cargo-bisect-rustc`. You can check which toolchains - are installed with `rustup toolchain list`. +- Uninstall unnecessary toolchains if you use `cargo-bisect-rustc`. + You can check which toolchains are installed with `rustup toolchain list`. [^1]: issue[#1707](https://github.com/rust-lang/rustc-dev-guide/issues/1707) diff --git a/src/doc/rustc-dev-guide/src/building/new-target.md b/src/doc/rustc-dev-guide/src/building/new-target.md index d0ed787f520ad..73174aaa0adfb 100644 --- a/src/doc/rustc-dev-guide/src/building/new-target.md +++ b/src/doc/rustc-dev-guide/src/building/new-target.md @@ -52,7 +52,7 @@ own preinstalled LLVM, you will need to provide `FileCheck` in some other way. On Debian-based systems, you can install the `llvm-N-tools` package (where `N` is the LLVM version number, e.g. `llvm-8-tools`). Alternately, you can specify the path to `FileCheck` with the `llvm-filecheck` config item in `bootstrap.toml` -or you can disable codegen test with the `codegen-tests` item in `bootstrap.toml`. +or you can disable codegen test with the `rust.codegen-tests` item in `bootstrap.toml`. ## Creating a target specification @@ -72,8 +72,7 @@ somewhat successfully, you can copy the specification into the compiler itself. You will need to add a line to the big table inside of the `supported_targets` macro in the `rustc_target::spec` module. -You will then add a corresponding file for your new target containing a -`target` function. +You will then add a corresponding file for your new target containing a `target` function. Look for existing targets to use as examples. @@ -118,16 +117,10 @@ After this, run `cargo update -p libc` to update the lockfiles. Beware that if you patch to a local `path` dependency, this will enable warnings for that dependency. Some dependencies are not warning-free, and due -to the `deny-warnings` setting in `bootstrap.toml`, the build may suddenly start to fail. +to the `rust.deny-warnings` setting in `bootstrap.toml`, the build may suddenly start to fail. To work around warnings, you may want to: - Modify the dependency to remove the warnings -- Or for local development purposes, suppress the warnings by setting deny-warnings = false in bootstrap.toml. - -```toml -# bootstrap.toml -[rust] -deny-warnings = false -``` +- Or for local development purposes, suppress the warnings by setting `rust.deny-warnings = false` in bootstrap.toml. [`libc`]: https://crates.io/crates/libc [`cc`]: https://crates.io/crates/cc diff --git a/src/doc/rustc-dev-guide/src/building/optimized-build.md b/src/doc/rustc-dev-guide/src/building/optimized-build.md index 46def66d17823..0a6b82eba46ac 100644 --- a/src/doc/rustc-dev-guide/src/building/optimized-build.md +++ b/src/doc/rustc-dev-guide/src/building/optimized-build.md @@ -2,20 +2,20 @@ There are multiple additional build configuration options and techniques that can be used to compile a build of `rustc` that is as optimized as possible (for example when building `rustc` for a Linux -distribution). The status of these configuration options for various Rust targets is tracked [here]. +distribution). +The status of these configuration options for various Rust targets is tracked [here]. This page describes how you can use these approaches when building `rustc` yourself. [here]: https://github.com/rust-lang/rust/issues/103595 ## Link-time optimization -Link-time optimization is a powerful compiler technique that can increase program performance. To -enable (Thin-)LTO when building `rustc`, set the `rust.lto` config option to `"thin"` +Link-time optimization is a powerful compiler technique that can increase program performance. +To enable (Thin-)LTO when building `rustc`, set the `rust.lto` config option to `"thin"` in `bootstrap.toml`: ```toml -[rust] -lto = "thin" +rust.lto = "thin" ``` > Note that LTO for `rustc` is currently supported and tested only for @@ -30,13 +30,12 @@ Enabling LTO on Linux has [produced] speed-ups by up to 10%. ## Memory allocator -Using a different memory allocator for `rustc` can provide significant performance benefits. If you -want to enable the `jemalloc` allocator, you can set the `rust.jemalloc` option to `true` +Using a different memory allocator for `rustc` can provide significant performance benefits. +If you want to enable the `jemalloc` allocator, you can set the `rust.jemalloc` option to `true` in `bootstrap.toml`: ```toml -[rust] -jemalloc = true +rust.jemalloc = true ``` > Note that this option is currently only supported for Linux and macOS targets. @@ -48,17 +47,16 @@ You can modify the number of codegen units for `rustc` and `libstd` in `bootstra following options: ```toml -[rust] -codegen-units = 1 -codegen-units-std = 1 +rust.codegen-units = 1 +rust.codegen-units-std = 1 ``` ## Instruction set By default, `rustc` is compiled for a generic (and conservative) instruction set architecture -(depending on the selected target), to make it support as many CPUs as possible. If you want to -compile `rustc` for a specific instruction set architecture, you can set the `target_cpu` compiler -option in `RUSTFLAGS`: +(depending on the selected target), to make it support as many CPUs as possible. +If you want to compile `rustc` for a specific instruction set architecture, +you can set the `target_cpu` compiler option in `RUSTFLAGS`: ```bash RUSTFLAGS="-C target_cpu=x86-64-v3" ./x build ... @@ -68,22 +66,23 @@ If you also want to compile LLVM for a specific instruction set, you can set `ll in `bootstrap.toml`: ```toml -[llvm] -cxxflags = "-march=x86-64-v3" -cflags = "-march=x86-64-v3" +llvm.cxxflags = "-march=x86-64-v3" +llvm.cflags = "-march=x86-64-v3" ``` ## Profile-guided optimization Applying profile-guided optimizations (or more generally, feedback-directed optimizations) can -produce a large increase to `rustc` performance, by up to 15% ([1], [2]). However, these techniques +produce a large increase to `rustc` performance, by up to 15% ([1], [2]). +However, these techniques are not simply enabled by a configuration option, but rather they require a complex build workflow that compiles `rustc` multiple times and profiles it on selected benchmarks. There is a tool called `opt-dist` that is used to optimize `rustc` with [PGO] (profile-guided -optimizations) and [BOLT] (a post-link binary optimizer) for builds distributed to end users. You -can examine the tool, which is located in `src/tools/opt-dist`, and build a custom PGO build -workflow based on it, or try to use it directly. Note that the tool is currently quite hardcoded to +optimizations) and [BOLT] (a post-link binary optimizer) for builds distributed to end users. +You can examine the tool, which is located in `src/tools/opt-dist`, and build a custom PGO build +workflow based on it, or try to use it directly. +Note that the tool is currently quite hardcoded to the way we use it in Rust's continuous integration workflows, and it might require some custom changes to make it work in a different environment. @@ -97,9 +96,9 @@ changes to make it work in a different environment. To use the tool, you will need to provide some external dependencies: - A Python3 interpreter (for executing `x.py`). -- Compiled LLVM toolchain, with the `llvm-profdata` binary. Optionally, if you want to use BOLT, - the `llvm-bolt` and - `merge-fdata` binaries have to be available in the toolchain. +- Compiled LLVM toolchain, with the `llvm-profdata` binary. + Optionally, if you want to use BOLT, + the `llvm-bolt` and `merge-fdata` binaries have to be available in the toolchain. These dependencies are provided to `opt-dist` by an implementation of the [`Environment`] struct. It specifies directories where will the PGO/BOLT pipeline take place, and also external dependencies @@ -108,9 +107,8 @@ like Python or LLVM. Here is an example of how can `opt-dist` be used locally (outside of CI): 1. Enable metrics in your `bootstrap.toml` file, because `opt-dist` expects it to be enabled: - ```toml - [build] - metrics = true + ```toml + build.metrics = true ``` 2. Build the tool with the following command: ```bash diff --git a/src/doc/rustc-dev-guide/src/building/suggested.md b/src/doc/rustc-dev-guide/src/building/suggested.md index b5c9b9b4e3d12..3ed4f129d144e 100644 --- a/src/doc/rustc-dev-guide/src/building/suggested.md +++ b/src/doc/rustc-dev-guide/src/building/suggested.md @@ -118,8 +118,7 @@ requires extra disk space. Selecting `vscode` in `./x setup editor` will prompt you to create a `.vscode/settings.json` file which will configure Visual Studio code. -The recommended `rust-analyzer` settings live at -[`src/etc/rust_analyzer_settings.json`]. +The recommended `rust-analyzer` settings live at [`src/etc/rust_analyzer_settings.json`]. If running `./x check` on save is inconvenient, in VS Code you can use a [Build Task] instead: @@ -253,8 +252,7 @@ It can be configured through `.zed/settings.json`, as described [here](https://zed.dev/docs/configuring-languages). Selecting `zed` in `./x setup editor` will prompt you to create a `.zed/settings.json` file which will configure Zed with the recommended configuration. -The recommended `rust-analyzer` settings live -at [`src/etc/rust_analyzer_zed.json`]. +The recommended `rust-analyzer` settings live at [`src/etc/rust_analyzer_zed.json`]. ## Check, check, and check again @@ -277,14 +275,14 @@ This often helps reviewing. ## Configuring `rustup` to use nightly Some parts of the bootstrap process uses pinned, nightly versions of tools like rustfmt. -To make things like `cargo fmt` work correctly in your repo, run +To make things like `cargo fmt` work correctly in your repo, +[install a nightly toolchain] with rustup, then run this command: ```console cd rustup override set nightly ``` -After [installing a nightly toolchain] with `rustup`. Don't forget to do this for all directories you have [setup a worktree for]. You may need to use the pinned nightly version from `src/stage0`, but often the normal `nightly` channel will work. @@ -297,7 +295,7 @@ toolchain for your bootstrapped compiler You still have to use `x` to work on the compiler or standard library, this just lets you use `cargo fmt`. -[installing a nightly toolchain]: https://rust-lang.github.io/rustup/concepts/channels.html?highlight=nightl#working-with-nightly-rust +[install a nightly toolchain]: https://rust-lang.github.io/rustup/concepts/channels.html?highlight=nightl#working-with-nightly-rust [setup a worktree for]: ./suggested.md#working-on-multiple-branches-at-the-same-time [the section on vscode]: suggested.md#configuring-rust-analyzer-for-rustc [the section on rustup]: how-to-build-and-run.md?highlight=rustup#creating-a-rustup-toolchain @@ -441,7 +439,7 @@ ln -s ./src/tools/nix-dev-shell/envrc-shell ./.envrc # Use nix-shell ### Note Note that when using nix on a not-NixOS distribution, it may be necessary to set -**`patch-binaries-for-nix = true` in `bootstrap.toml`**. Bootstrap tries to detect +**`build.patch-binaries-for-nix = true` in `bootstrap.toml`**. Bootstrap tries to detect whether it's running in nix and enable patching automatically, but this detection can have false negatives. diff --git a/src/doc/rustc-dev-guide/src/compiler-debugging.md b/src/doc/rustc-dev-guide/src/compiler-debugging.md index 1944bf53378d4..d4c599a6edf74 100644 --- a/src/doc/rustc-dev-guide/src/compiler-debugging.md +++ b/src/doc/rustc-dev-guide/src/compiler-debugging.md @@ -1,26 +1,27 @@ # Debugging the compiler -This chapter contains a few tips to debug the compiler. These tips aim to be -useful no matter what you are working on. Some of the other chapters have +This chapter contains a few tips to debug the compiler. +These tips aim to be useful no matter what you are working on. +Some of the other chapters have advice about specific parts of the compiler (e.g. the [Queries Debugging and Testing chapter](./incrcomp-debugging.html) or the [LLVM Debugging chapter](./backend/debugging.md)). ## Configuring the compiler -By default, rustc is built without most debug information. To enable debug info, -set `debug = true` in your bootstrap.toml. +By default, rustc is built without most debug information. +To enable debug info, +set `rust.debug = true` in your bootstrap.toml. -Setting `debug = true` turns on many different debug options (e.g., `debug-assertions`, +Setting `rust.debug = true` turns on many different debug options (e.g., `debug-assertions`, `debug-logging`, etc.) which can be individually tweaked if you want to, but many people -simply set `debug = true`. +simply set `rust.debug = true`. If you want to use GDB to debug rustc, please set `bootstrap.toml` with options: ```toml -[rust] -debug = true -debuginfo-level = 2 +rust.debug = true +rust.debuginfo-level = 2 ``` > NOTE: @@ -36,8 +37,7 @@ This requires at least GDB v10.2, otherwise you need to disable new symbol-mangling-version in `bootstrap.toml`. ```toml -[rust] -new-symbol-mangling = false +rust.new-symbol-mangling = false ``` > See the comments in `bootstrap.example.toml` for more info. @@ -47,16 +47,16 @@ You will need to rebuild the compiler after changing any configuration option. ## Suppressing the ICE file By default, if rustc encounters an Internal Compiler Error (ICE) it will dump the ICE contents to an -ICE file within the current working directory named `rustc-ice--.txt`. If this is -not desirable, you can prevent the ICE file from being created with `RUSTC_ICE=0`. +ICE file within the current working directory named `rustc-ice--.txt`. +If this is not desirable, you can prevent the ICE file from being created with `RUSTC_ICE=0`. ## Getting a backtrace [getting-a-backtrace]: #getting-a-backtrace When you have an ICE (panic in the compiler), you can set -`RUST_BACKTRACE=1` to get the stack trace of the `panic!` like in -normal Rust programs. IIRC backtraces **don't work** on MinGW, -sorry. If you have trouble or the backtraces are full of `unknown`, +`RUST_BACKTRACE=1` to get the stack trace of the `panic!` like in normal Rust programs. +IIRC backtraces **don't work** on MinGW, sorry. +If you have trouble or the backtraces are full of `unknown`, you might want to find some way to use Linux, Mac, or MSVC on Windows. In the default configuration (without `debug` set to `true`), you don't have line numbers @@ -100,9 +100,10 @@ stack backtrace: ## `-Z` flags -The compiler has a bunch of `-Z *` flags. These are unstable flags that are only -enabled on nightly. Many of them are useful for debugging. To get a full listing -of `-Z` flags, use `-Z help`. +The compiler has a bunch of `-Z *` flags. +These are unstable flags that are only enabled on nightly. +Many of them are useful for debugging. +To get a full listing of `-Z` flags, use `-Z help`. One useful flag is `-Z verbose-internals`, which generally enables printing more info that could be useful for debugging. @@ -114,7 +115,8 @@ Right below you can find elaborate explainers on a selected few. If you want to get a backtrace to the point where the compiler emits an error message, you can pass the `-Z treat-err-as-bug=n`, which will make -the compiler panic on the `nth` error. If you leave off `=n`, the compiler will +the compiler panic on the `nth` error. +If you leave off `=n`, the compiler will assume `1` for `n` and thus panic on the first error it encounters. For example: @@ -190,13 +192,12 @@ Cool, now I have a backtrace for the error! The `-Z eagerly-emit-delayed-bugs` option makes it easy to debug delayed bugs. It turns them into normal errors, i.e. makes them visible. This can be used in -combination with `-Z treat-err-as-bug` to stop at a particular delayed bug and -get a backtrace. +combination with `-Z treat-err-as-bug` to stop at a particular delayed bug and get a backtrace. ### Getting the error creation location -`-Z track-diagnostics` can help figure out where errors are emitted. It uses `#[track_caller]` -for this and prints its location alongside the error: +`-Z track-diagnostics` can help figure out where errors are emitted. +It uses `#[track_caller]` for this and prints its location alongside the error: ``` $ RUST_BACKTRACE=1 rustc +stage1 error.rs -Z track-diagnostics @@ -238,11 +239,11 @@ For details see [the guide section on tracing](./tracing.md) ## Narrowing (Bisecting) Regressions The [cargo-bisect-rustc][bisect] tool can be used as a quick and easy way to -find exactly which PR caused a change in `rustc` behavior. It automatically -downloads `rustc` PR artifacts and tests them against a project you provide -until it finds the regression. You can then look at the PR to get more context -on *why* it was changed. See [this tutorial][bisect-tutorial] on how to use -it. +find exactly which PR caused a change in `rustc` behavior. +It automatically downloads `rustc` PR artifacts and tests them against a project you provide +until it finds the regression. +You can then look at the PR to get more context on *why* it was changed. + See [this tutorial][bisect-tutorial] on how to use it. [bisect]: https://github.com/rust-lang/cargo-bisect-rustc [bisect-tutorial]: https://rust-lang.github.io/cargo-bisect-rustc/tutorial.html @@ -252,8 +253,9 @@ it. The [rustup-toolchain-install-master][rtim] tool by kennytm can be used to download the artifacts produced by Rust's CI for a specific SHA1 -- this basically corresponds to the successful landing of some PR -- and then sets -them up for your local use. This also works for artifacts produced by `@bors -try`. This is helpful when you want to examine the resulting build of a PR +them up for your local use. +This also works for artifacts produced by `@bors try`. +This is helpful when you want to examine the resulting build of a PR without doing the build yourself. [rtim]: https://github.com/kennytm/rustup-toolchain-install-master @@ -261,10 +263,12 @@ without doing the build yourself. ## `#[rustc_*]` TEST attributes The compiler defines a whole lot of internal (perma-unstable) attributes some of which are useful -for debugging by dumping extra compiler-internal information. These are prefixed with `rustc_` and +for debugging by dumping extra compiler-internal information. +These are prefixed with `rustc_` and are gated behind the internal feature `rustc_attrs` (enabled via e.g. `#![feature(rustc_attrs)]`). -For a complete and up to date list, see [`builtin_attrs`]. More specifically, the ones marked `TEST`. +For a complete and up to date list, see [`builtin_attrs`]. +More specifically, the ones marked `TEST`. Here are some notable ones: | Attribute | Description | @@ -313,7 +317,8 @@ $ firefox maybe_init_suffix.pdf # Or your favorite pdf viewer ### Debugging type layouts The internal attribute `#[rustc_layout]` can be used to dump the [`Layout`] of -the type it is attached to. For example: +the type it is attached to. +For example: ```rust #![feature(rustc_attrs)] diff --git a/src/doc/rustc-dev-guide/src/effects.md b/src/doc/rustc-dev-guide/src/effects.md index 732ba71531167..26530a30d066b 100644 --- a/src/doc/rustc-dev-guide/src/effects.md +++ b/src/doc/rustc-dev-guide/src/effects.md @@ -2,16 +2,17 @@ ## The `HostEffect` predicate -[`HostEffectPredicate`]s are a kind of predicate from `~const Tr` or `const Tr` -bounds. It has a trait reference, and a `constness` which could be `Maybe` or -`Const` depending on the bound. Because `~const Tr`, or rather `Maybe` bounds +[`HostEffectPredicate`]s are a kind of predicate from `~const Tr` or `const Tr` bounds. +It has a trait reference, and a `constness` which could be `Maybe` or +`Const` depending on the bound. +Because `~const Tr`, or rather `Maybe` bounds apply differently based on whichever contexts they are in, they have different -behavior than normal bounds. Where normal trait bounds on a function such as +behavior than normal bounds. +Where normal trait bounds on a function such as `T: Tr` are collected within the [`predicates_of`] query to be proven when a function is called and to be assumed within the function, bounds such as `T: ~const Tr` will behave as a normal trait bound and add `T: Tr` to the result -from `predicates_of`, but also adds a `HostEffectPredicate` to the -[`const_conditions`] query. +from `predicates_of`, but also adds a `HostEffectPredicate` to the [`const_conditions`] query. On the other hand, `T: const Tr` bounds do not change meaning across contexts, therefore they will result in `HostEffect(T: Tr, const)` being added to @@ -23,17 +24,17 @@ therefore they will result in `HostEffect(T: Tr, const)` being added to ## The `const_conditions` query -`predicates_of` represents a set of predicates that need to be proven to use an -item. For example, to use `foo` in the example below: +`predicates_of` represents a set of predicates that need to be proven to use an item. +For example, to use `foo` in the example below: ```rust fn foo() where T: Default {} ``` -We must be able to prove that `T` implements `Default`. In a similar vein, +We must be able to prove that `T` implements `Default`. +In a similar vein, `const_conditions` represents a set of predicates that need to be proven to use -an item *in const contexts*. If we adjust the example above to use `const` trait -bounds: +an item *in const contexts*. If we adjust the example above to use `const` trait bounds: ```rust const fn foo() where T: ~const Default {} @@ -45,13 +46,13 @@ prove that `T` has a const implementation of `Default`. ## Enforcement of `const_conditions` -`const_conditions` are currently checked in various places. +`const_conditions` are currently checked in various places. Every call in HIR from a const context (which includes `const fn` and `const` items) will check that `const_conditions` of the function we are calling hold. -This is done in [`FnCtxt::enforce_context_effects`]. Note that we don't check -if the function is only referred to but not called, as the following code needs -to compile: +This is done in [`FnCtxt::enforce_context_effects`]. +Note that we don't check +if the function is only referred to but not called, as the following code needs to compile: ```rust const fn hi() -> T { @@ -61,8 +62,8 @@ const X: fn() -> u32 = hi::; ``` For a trait `impl` to be well-formed, we must be able to prove the -`const_conditions` of the trait from the `impl`'s environment. This is checked -in [`wfcheck::check_impl`]. +`const_conditions` of the trait from the `impl`'s environment. +This is checked in [`wfcheck::check_impl`]. Here's an example: @@ -77,10 +78,11 @@ impl const Foo for () {} ``` Methods of trait impls must not have stricter bounds than the method of the -trait that they are implementing. To check that the methods are compatible, a +trait that they are implementing. +To check that the methods are compatible, a hybrid environment is constructed with the predicates of the `impl` plus the -predicates of the trait method, and we attempt to prove the predicates of the -impl method. We do the same for `const_conditions`: +predicates of the trait method, and we attempt to prove the predicates of the impl method. +We do the same for `const_conditions`: ```rust const trait Foo { @@ -95,10 +97,10 @@ impl Foo for Vec { } ``` -These checks are done in [`compare_method_predicate_entailment`]. A similar -function that does the same check for associated types is called -[`compare_type_predicate_entailment`]. Both of these need to consider -`const_conditions` when in const contexts. +These checks are done in [`compare_method_predicate_entailment`]. +A similar function that does the same check for associated types is called +[`compare_type_predicate_entailment`]. +Both of these need to consider `const_conditions` when in const contexts. In MIR, as part of const checking, `const_conditions` of items that are called are revalidated again in [`Checker::revalidate_conditional_constness`]. @@ -111,7 +113,9 @@ are revalidated again in [`Checker::revalidate_conditional_constness`]. ## `explicit_implied_const_bounds` on associated types and traits -Bounds on associated types, opaque types, and supertraits such as +Bounds on associated types, opaque types, and supertraits such as the following +have their bounds represented differently: + ```rust trait Foo: ~const PartialEq { type X: ~const PartialEq; @@ -122,11 +126,11 @@ fn foo() -> impl ~const PartialEq { } ``` -Have their bounds represented differently. Unlike `const_conditions` which need -to be proved for callers, and can be assumed inside the definition (e.g. trait +Unlike `const_conditions`, which need to be proved for callers, +and can be assumed inside the definition (e.g. trait bounds on functions), these bounds need to be proved at definition (at the impl, -or when returning the opaque) but can be assumed for callers. The non-const -equivalent of these bounds are called [`explicit_item_bounds`]. +or when returning the opaque) but can be assumed for callers. +The non-const equivalent of these bounds are called [`explicit_item_bounds`]. These bounds are checked in [`compare_impl_item::check_type_bounds`] for HIR typeck, [`evaluate_host_effect_from_item_bounds`] in the old solver and @@ -139,18 +143,16 @@ typeck, [`evaluate_host_effect_from_item_bounds`] in the old solver and ## Proving `HostEffectPredicate`s -`HostEffectPredicate`s are implemented both in the [old solver] and the [new -trait solver]. In general, we can prove a `HostEffect` predicate when either of -these conditions are met: +`HostEffectPredicate`s are implemented both in the [old solver] and the [new trait solver]. +In general, we can prove a `HostEffect` predicate when either of these conditions are met: * The predicate can be assumed from caller bounds; * The type has a `const` `impl` for the trait, *and* that const conditions on -the impl holds, *and* that the `explicit_implied_const_bounds` on the trait -holds; or -* The type has a built-in implementation for the trait in const contexts. For -example, `Fn` may be implemented by function items if their const conditions -are satisfied, or `Destruct` is implemented in const contexts if the type can -be dropped at compile time. + the impl holds, *and* that the `explicit_implied_const_bounds` on the trait holds; or +* The type has a built-in implementation for the trait in const contexts. + For example, `Fn` may be implemented by function items if their const conditions + are satisfied, or `Destruct` is implemented in const contexts if the type can + be dropped at compile time. [old solver]: https://doc.rust-lang.org/nightly/nightly-rustc/src/rustc_trait_selection/traits/effects.rs.html [new trait solver]: https://doc.rust-lang.org/nightly/nightly-rustc/src/rustc_next_trait_solver/solve/effect_goals.rs.html @@ -161,10 +163,11 @@ To be expanded later. ### The `#[rustc_non_const_trait_method]` attribute -This is intended for internal (standard library) usage only. With this attribute -applied to a trait method, the compiler will not check the default body of this -method for ability to run in compile time. Users of the trait will also not be -allowed to use this trait method in const contexts. This attribute is primarily +This is intended for internal (standard library) usage only. +With this attribute applied to a trait method, the compiler will not check the default body of this +method for ability to run in compile time. +Users of the trait will also not be allowed to use this trait method in const contexts. +This attribute is primarily used for constifying large traits such as `Iterator` without having to make all its methods `const` at the same time. diff --git a/src/doc/rustc-dev-guide/src/external-repos.md b/src/doc/rustc-dev-guide/src/external-repos.md index 2e32fcfe78c1d..7ae1c881be8f7 100644 --- a/src/doc/rustc-dev-guide/src/external-repos.md +++ b/src/doc/rustc-dev-guide/src/external-repos.md @@ -1,4 +1,4 @@ -# Using External Repositories +# Using external repositories The `rust-lang/rust` git repository depends on several other repos in the `rust-lang` organization. There are three main ways we use dependencies: @@ -12,7 +12,7 @@ As a general rule: changes - Use submodules for tools that are independent of the compiler -## External Dependencies (subtrees) +## External dependencies (subtrees) The following external projects are managed using some form of a `subtree`: @@ -153,7 +153,7 @@ Now you're done, the `src/tools/clippy` directory behaves as if Clippy were part of the rustc monorepo, so no one but you (or others that synchronize subtrees) actually needs to use `git subtree`. -## External Dependencies (submodules) +## External dependencies (submodules) Building Rust will also use external git repositories tracked using [git submodules]. The complete list may be found in the [`.gitmodules`] file. diff --git a/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md b/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md index d71e51d5f61bf..8e94928c8a1a0 100644 --- a/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md +++ b/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md @@ -7,13 +7,13 @@ libraries and binaries with additional instructions and data, at compile time. The coverage instrumentation injects calls to the LLVM intrinsic instruction [`llvm.instrprof.increment`][llvm-instrprof-increment] at code branches (based on a MIR-based control flow analysis), and LLVM converts these to -instructions that increment static counters, when executed. The LLVM coverage -instrumentation also requires a [Coverage Map] that encodes source metadata, +instructions that increment static counters, when executed. +The LLVM coverage instrumentation also requires a [Coverage Map] that encodes source metadata, mapping counter IDs--directly and indirectly--to the file locations (with start and end line and column). -Rust libraries, with or without coverage instrumentation, can be linked into -instrumented binaries. When the program is executed and cleanly terminates, +Rust libraries, with or without coverage instrumentation, can be linked into instrumented binaries. +When the program is executed and cleanly terminates, LLVM libraries write the final counter values to a file (`default.profraw` or a custom file set through environment variable `LLVM_PROFILE_FILE`). @@ -21,9 +21,7 @@ Developers use existing LLVM coverage analysis tools to decode `.profraw` files, with corresponding Coverage Maps (from matching binaries that produced them), and generate various reports for analysis, for example: -Screenshot of sample `llvm-cov show` result, for function add_quoted_string -
+![Screenshot of sample `llvm-cov show` result, for function add_quoted_string](img/llvm-cov-show-01.png) Detailed instructions and examples are documented in the [rustc book][rustc-book-instrument-coverage]. @@ -39,31 +37,28 @@ When working on the coverage instrumentation code, it is usually necessary to This allows the compiler to produce instrumented binaries, and makes it possible to run the full coverage test suite. -Enabling debug assertions in the compiler and in LLVM is recommended, but not -mandatory. +Enabling debug assertions in the compiler and in LLVM is recommended, but not mandatory. ```toml # Similar to the "compiler" profile, but also enables debug assertions in LLVM. # These assertions can detect malformed coverage mappings in some cases. profile = "codegen" -[build] # IMPORTANT: This tells the build system to build the LLVM profiler runtime. # Without it, the compiler can't produce coverage-instrumented binaries, # and many of the coverage tests will be skipped. -profiler = true +build.profiler = true -[rust] # Enable debug assertions in the compiler. -debug-assertions = true +rust.debug-assertions = true ``` ## Rust symbol mangling `-C instrument-coverage` automatically enables Rust symbol mangling `v0` (as if the user specified `-C symbol-mangling-version=v0` option when invoking -`rustc`) to ensure consistent and reversible name mangling. This has two -important benefits: +`rustc`) to ensure consistent and reversible name mangling. +This has two important benefits: 1. LLVM coverage tools can analyze coverage over multiple runs, including some changes to source code; so mangled names must be consistent across compilations. @@ -73,8 +68,8 @@ important benefits: ## The LLVM profiler runtime -Coverage data is only generated by running the executable Rust program. `rustc` -statically links coverage-instrumented binaries with LLVM runtime code +Coverage data is only generated by running the executable Rust program. +`rustc` statically links coverage-instrumented binaries with LLVM runtime code ([compiler-rt][compiler-rt-profile]) that implements program hooks (such as an `exit` hook) to write the counter values to the `.profraw` file. diff --git a/src/doc/rustc-dev-guide/src/offload/internals.md b/src/doc/rustc-dev-guide/src/offload/internals.md index 77a4cadbcb986..520c48d958962 100644 --- a/src/doc/rustc-dev-guide/src/offload/internals.md +++ b/src/doc/rustc-dev-guide/src/offload/internals.md @@ -13,4 +13,4 @@ We use a single-source, two-pass compilation approach. First we compile all functions that should be offloaded for the device (e.g nvptx64, amdgcn-amd-amdhsa, intel in the future). Currently we require cumbersome `#cfg(target_os="")` annotations, but we intend to recognize those in the future based on our offload intrinsic. -We then compile the code for the host (e.g. x86-64), where most of the offloading logic happens. On the host side, we generate calls to the openmp offload runtime, to inform it about the layout of the types (a simplified version of the autodiff TypeTrees). We also use the type system to figure out whether kernel arguments have to be moved only to the device (e.g. `&[f32;1024]`), from the device, or both (e.g. `&mut [f64]`). We then launched the kernel, after which we inform the runtime to end this environment and move data back (as far as needed). +We then compile the code for the host (e.g. x86-64), where most of the offloading logic happens. On the host side, we generate calls to the openmp offload runtime, to inform it about the layout of the types (a simplified version of the autodiff TypeTrees). We also use the type system to figure out whether kernel arguments have to be moved only to the device (e.g. `&[f32;1024]`), from the device, or both (e.g. `&mut [f64]`). We then launch the kernel, after which we inform the runtime to end this environment and move data back (as far as needed). diff --git a/src/doc/rustc-dev-guide/src/profiling.md b/src/doc/rustc-dev-guide/src/profiling.md index 519d9b5488cbd..66eabe7d8c930 100644 --- a/src/doc/rustc-dev-guide/src/profiling.md +++ b/src/doc/rustc-dev-guide/src/profiling.md @@ -33,10 +33,11 @@ Since most of the time compiling rustc is spent in LLVM, the idea is that by reducing the amount of code passed to LLVM, compiling rustc gets faster. To use `cargo-llvm-lines` together with somewhat custom rustc build process, you can use -`-C save-temps` to obtain required LLVM IR. The option preserves temporary work products -created during compilation. Among those is LLVM IR that represents an input to the -optimization pipeline; ideal for our purposes. It is stored in files with `*.no-opt.bc` -extension in LLVM bitcode format. +`-C save-temps` to obtain required LLVM IR. +The option preserves temporary work products created during compilation. +Among those is LLVM IR that represents an input to the +optimization pipeline; ideal for our purposes. +It is stored in files with `*.no-opt.bc` extension in LLVM bitcode format. Example usage: ``` @@ -89,24 +90,24 @@ Since this doesn't seem to work with incremental compilation or `./x check`, you will be compiling rustc _a lot_. I recommend changing a few settings in `bootstrap.toml` to make it bearable: ``` -[rust] # A debug build takes _a third_ as long on my machine, # but compiling more than stage0 rustc becomes unbearably slow. -optimize = false +rust.optimize = false # We can't use incremental anyway, so we disable it for a little speed boost. -incremental = false +rust.incremental = false # We won't be running it, so no point in compiling debug checks. -debug = false +rust.debug = false # Using a single codegen unit gives less output, but is slower to compile. -codegen-units = 0 # num_cpus +rust.codegen-units = 0 # num_cpus ``` The llvm-lines output is affected by several options. -`optimize = false` increases it from 2.1GB to 3.5GB and `codegen-units = 0` to 4.1GB. +`rust.optimize = false` increases it from 2.1GB to 3.5GB and `codegen-units = 0` to 4.1GB. -MIR optimizations have little impact. Compared to the default `RUSTFLAGS="-Z +MIR optimizations have little impact. +Compared to the default `RUSTFLAGS="-Z mir-opt-level=1"`, level 0 adds 0.3GB and level 2 removes 0.2GB. As of July 2022, inlining happens in LLVM and GCC codegen backends, diff --git a/src/doc/rustc-dev-guide/src/profiling/wpa-profiling.md b/src/doc/rustc-dev-guide/src/profiling/wpa-profiling.md index d2680d40853f7..a0a5bee63e9e6 100644 --- a/src/doc/rustc-dev-guide/src/profiling/wpa-profiling.md +++ b/src/doc/rustc-dev-guide/src/profiling/wpa-profiling.md @@ -3,13 +3,13 @@ ## Introducing WPR and WPA High-level performance analysis (including memory usage) can be performed with the Windows -Performance Recorder (WPR) and Windows Performance Analyzer (WPA). As the names suggest, WPR is for -recording system statistics (in the form of event trace log a.k.a. ETL files), while WPA is for -analyzing these ETL files. +Performance Recorder (WPR) and Windows Performance Analyzer (WPA). +As the names suggest, WPR is for recording system statistics (in the form of event trace log a.k.a. +ETL files), while WPA is for analyzing these ETL files. WPR collects system wide statistics, so it won't just record things relevant to rustc but also -everything else that's running on the machine. During analysis, we can filter to just the things we -find interesting. +everything else that's running on the machine. +During analysis, we can filter to just the things we find interesting. These tools are quite powerful but also require a bit of learning before we can successfully profile the Rust compiler. @@ -21,36 +21,43 @@ specifically designed to make analyzing rustc easier. ### Installing WPR and WPA You can install WPR and WPA as part of the Windows Performance Toolkit which itself is an option as -part of downloading the Windows Assessment and Deployment Kit (ADK). You can download the ADK -installer [here](https://go.microsoft.com/fwlink/?linkid=2086042). Make sure to select the Windows -Performance Toolkit (you don't need to select anything else). +part of downloading the Windows Assessment and Deployment Kit (ADK). +You can download the ADK +installer [here](https://learn.microsoft.com/en-us/windows-hardware/get-started/adk-install). +Make sure to select the Windows Performance Toolkit (you don't need to select anything else). ## Recording -In order to perform system analysis, you'll first need to record your system with WPR. Open WPR and -at the bottom of the window select the "profiles" of the things you want to record. For looking +In order to perform system analysis, you'll first need to record your system with WPR. +Open WPR and at the bottom of the window select the "profiles" of the things you want to record. +For looking into memory usage of the rustc bootstrap process, we'll want to select the following items: * CPU usage * VirtualAlloc usage You might be tempted to record "Heap usage" as well, but this records every single heap allocation -and can be very, very expensive. For high-level analysis, it might be best to leave that turned -off. +and can be very, very expensive. +For high-level analysis, it might be best to leave that turned off. -Now we need to get our setup ready to record. For memory usage analysis, it is best to record the -stage 2 compiler build with a stage 1 compiler build with debug symbols. Having symbols in the +Now we need to get our setup ready to record. +For memory usage analysis, it is best to record the +stage 2 compiler build with a stage 1 compiler build with debug symbols. +Having symbols in the compiler we're using to build rustc will aid our analysis greatly by allowing WPA to resolve Rust -symbols correctly. Unfortunately, the stage 0 compiler does not have symbols turned on which is why -we'll need to build a stage 1 compiler and then a stage 2 compiler ourselves. +symbols correctly. +Unfortunately, the stage 0 compiler does not have symbols turned on, +which is why we'll need to build a stage 1 compiler, +and then a stage 2 compiler ourselves. -To do this, make sure you have set `debuginfo-level = 1` in your `bootstrap.toml` file. This tells -rustc to generate debug information which includes stack frames when bootstrapping. +To do this, make sure you have set `rust.debuginfo-level = 1` in your `bootstrap.toml` file. +This tells rustc to generate debug information which includes stack frames when bootstrapping. Now you can build the stage 1 compiler: `x build --stage 1 -i library` or however else you want to build the stage 1 compiler. -Now that the stage 1 compiler is built, we can record the stage 2 build. Go back to WPR, click the +Now that the stage 1 compiler is built, we can record the stage 2 build. +Go back to WPR, click the "start" button and build the stage 2 compiler (e.g., `x build --stage=2 -i library`). When this process finishes, stop the recording. @@ -61,8 +68,10 @@ appears. ## Analysis -Now that our ETL file is open in WPA, we can analyze the results. First, we'll want to apply the -pre-made "profile" which will put WPA into a state conducive to analyzing rustc bootstrap. Download +Now that our ETL file is open in WPA, we can analyze the results. +First, we'll want to apply the +pre-made "profile" which will put WPA into a state conducive to analyzing rustc bootstrap. +Download the profile [here](https://github.com/wesleywiser/rustc-bootstrap-wpa-analysis/releases/download/1/rustc.generic.wpaProfile). Select the "Profiles" menu at the top, then "apply" and then choose the downloaded profile. @@ -71,8 +80,9 @@ You should see something resembling the following: ![WPA with profile applied](../img/wpa-initial-memory.png) Next, we will need to tell WPA to load and process debug symbols so that it can properly demangle -the Rust stack traces. To do this, click "Trace" and then choose "Load Symbols". This step can take -a while. +the Rust stack traces. +To do this, click "Trace" and then choose "Load Symbols". +This step can take a while. Once WPA has loaded symbols for rustc, we can expand the rustc.exe node and begin drilling down into the stack with the largest allocations. @@ -81,8 +91,8 @@ To do that, we'll expand the `[Root]` node in the "Commit Stack" column and cont until we find interesting stack frames. > Tip: After selecting the node you want to expand, press the right arrow key. This will expand the -node and put the selection on the next largest node in the expanded set. You can continue pressing -the right arrow key until you reach an interesting frame. +node and put the selection on the next largest node in the expanded set. +You can continue pressing the right arrow key until you reach an interesting frame. ![WPA with expanded stack](../img/wpa-stack.png) diff --git a/src/doc/rustc-dev-guide/src/rustc-driver/external-rustc-drivers.md b/src/doc/rustc-dev-guide/src/rustc-driver/external-rustc-drivers.md index 1049d7a82dddb..2d409ad201b13 100644 --- a/src/doc/rustc-dev-guide/src/rustc-driver/external-rustc-drivers.md +++ b/src/doc/rustc-dev-guide/src/rustc-driver/external-rustc-drivers.md @@ -42,29 +42,28 @@ For custom-built toolchains or environments not using rustup, additional configu #### Troubleshooting Steps -1. **Check LLVM installation**: Verify LLVM is installed and accessible -2. **Configure library paths**: You may need to set environment variables: - ```text +1. Verify LLVM is installed and accessible +2. Ensure that library paths are set: + ```sh export LD_LIBRARY_PATH=/path/to/llvm/lib:$LD_LIBRARY_PATH ``` -3. **Check version compatibility**: Ensure your LLVM version is compatible with your Rust toolchain +3. Ensure your LLVM version is compatible with your Rust toolchain -### Configuring `rust-analyzer` for Out-of-Tree Projects +### Configuring `rust-analyzer` for out-of-tree projects When developing out-of-tree projects that use `rustc_private` crates, you can configure `rust-analyzer` to recognize these crates. #### Configuration Steps -1. **Set rust-analyzer configuration** - Configure `rust-analyzer.rustc.source` to `"discover"` in your editor settings. +1. Configure `rust-analyzer.rustc.source` to `"discover"` in your editor settings. For VS Code, add to `rust_analyzer_settings.json`: ```json { "rust-analyzer.rustc.source": "discover" } ``` -2. **Add metadata to Cargo.toml** - Add the following to the `Cargo.toml` of every crate that uses `rustc_private`: + +2. Add the following to the `Cargo.toml` of every crate that uses `rustc_private`: ```toml [package.metadata.rust-analyzer] rustc_private = true @@ -74,4 +73,6 @@ This configuration allows `rust-analyzer` to properly recognize and provide IDE ### Additional Resources -- [GitHub Issue #137421](https://github.com/rust-lang/rust/issues/137421): Explains that `rustc_private` linker failures often occur because `llvm-tools` is not installed +- [GitHub Issue #137421] explains that `rustc_private` linker failures often occur because `llvm-tools` is not installed + +[GitHub Issue #137421]: https://github.com/rust-lang/rust/issues/137421 diff --git a/src/doc/rustc-dev-guide/src/sanitizers.md b/src/doc/rustc-dev-guide/src/sanitizers.md index 673d650e6050b..65e1c0c705057 100644 --- a/src/doc/rustc-dev-guide/src/sanitizers.md +++ b/src/doc/rustc-dev-guide/src/sanitizers.md @@ -36,8 +36,7 @@ Highlight of the most important aspects of the implementation: when enabled in `bootstrap.toml`: ```toml - [build] - sanitizers = true + build.sanitizers = true ``` The runtimes are [placed into target libdir][sanitizer-copy]. @@ -84,7 +83,7 @@ Sanitizers are validated by code generation tests in [`tests/ui/sanitizer/`][test-ui] directory. Testing sanitizer functionality requires the sanitizer runtimes (built when -`sanitizer = true` in `bootstrap.toml`) and target providing support for particular a sanitizer. +`build.sanitizer = true` in `bootstrap.toml`) and target providing support for particular a sanitizer. When a sanitizer is unsupported on a given target, sanitizer tests will be ignored. This behaviour is controlled by compiletest `needs-sanitizer-*` directives. diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index 5c4dfb6e0dd19..959a73a5a9ad9 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -277,8 +277,7 @@ the debugger currently being used: gdb is in a range (inclusive) - `min-lldb-version: 310` — ignores the test if the version of lldb is below the given version - `rust-lldb` — ignores the test if lldb is not contain the Rust plugin. - NOTE: The "Rust" version of LLDB doesn't exist anymore, so this will always be - ignored. + NOTE: The "Rust" version of LLDB doesn't exist anymore, so this will always be ignored. This should probably be removed. By passing the `--debugger` option to compiletest, you can specify a single debugger to run tests with. @@ -570,9 +569,7 @@ Instrumented binaries need to be linked against the LLVM profiler runtime, so is enabled in `bootstrap.toml`: ```toml -# bootstrap.toml -[build] -profiler = true +build.profiler = true ``` This also means that they typically don't run in PR CI jobs, though they do run diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md index 08371a779e117..ac76a2e15d9ad 100644 --- a/src/doc/rustc-dev-guide/src/tests/directives.md +++ b/src/doc/rustc-dev-guide/src/tests/directives.md @@ -164,9 +164,9 @@ The following directives will check rustc build settings and target settings: via `--target`, use `needs-llvm-components` instead to ensure the appropriate backend is available. - `needs-profiler-runtime` — ignores the test if the profiler runtime was not - enabled for the target (`build.profiler = true` in rustc's `bootstrap.toml`) + enabled for the target (`build.profiler = true` in `bootstrap.toml`) - `needs-sanitizer-support` — ignores if the sanitizer support was not enabled - for the target (`sanitizers = true` in rustc's `bootstrap.toml`) + for the target (`build.sanitizers = true` in `bootstrap.toml`) - `needs-sanitizer-{address,hwaddress,leak,memory,thread}` — ignores if the corresponding sanitizer is not enabled for the target (AddressSanitizer, hardware-assisted AddressSanitizer, LeakSanitizer, MemorySanitizer or diff --git a/src/doc/rustc-dev-guide/src/tests/docker.md b/src/doc/rustc-dev-guide/src/tests/docker.md index af8e0c36d0500..51beee8a866c4 100644 --- a/src/doc/rustc-dev-guide/src/tests/docker.md +++ b/src/doc/rustc-dev-guide/src/tests/docker.md @@ -1,12 +1,14 @@ # Testing with Docker -The [`src/ci/docker`] directory includes [Docker] image definitions for Linux-based jobs executed on GitHub Actions (non-Linux jobs run outside Docker). You can run these jobs on your local development machine, which can be -helpful to test environments different from your local system. You will -need to install Docker on a Linux, Windows, or macOS system (typically Linux +The [`src/ci/docker`] directory includes [Docker] image definitions for Linux-based jobs executed on GitHub Actions (non-Linux jobs run outside Docker). +You can run these jobs on your local development machine, which can be +helpful to test environments different from your local system. +You will need to install Docker on a Linux, Windows, or macOS system (typically Linux will be much faster than Windows or macOS because the latter use virtual machines to emulate a Linux environment). -Jobs running in CI are configured through a set of bash scripts, and it is not always trivial to reproduce their behavior locally. If you want to run a CI job locally in the simplest way possible, you can use a provided helper `citool` that tries to replicate what happens on CI as closely as possible: +Jobs running in CI are configured through a set of bash scripts, and it is not always trivial to reproduce their behavior locally. +If you want to run a CI job locally in the simplest way possible, you can use a provided helper `citool` that tries to replicate what happens on CI as closely as possible: ```bash cargo run --manifest-path src/ci/citool/Cargo.toml run-local @@ -18,39 +20,53 @@ If the above script does not work for you, you would like to have more control o ## The `run.sh` script The [`src/ci/docker/run.sh`] script is used to build a specific Docker image, run it, -build Rust within the image, and either run tests or prepare a set of archives designed for distribution. The script will mount your local Rust source tree in read-only mode, and an `obj` directory in read-write mode. All the compiler artifacts will be stored in the `obj` directory. The shell will start out in the `obj`directory. From there, it will execute `../src/ci/run.sh` which starts the build as defined by the Docker image. +build Rust within the image, and either run tests or prepare a set of archives designed for distribution. +The script will mount your local Rust source tree in read-only mode, and an `obj` directory in read-write mode. +All the compiler artifacts will be stored in the `obj` directory. +The shell will start out in the `obj`directory. +From there, it will execute `../src/ci/run.sh` which starts the build as defined by the Docker image. -You can run `src/ci/docker/run.sh ` directly. A few important notes regarding the `run.sh` script: -- When executed on CI, the script expects that all submodules are checked out. If some submodule that is accessed by the job is not available, the build will result in an error. You should thus make sure that you have all required submodules checked out locally. You can either do that manually through git, or set `submodules = true` in your `bootstrap.toml` and run a command such as `x build` to let bootstrap download the most important submodules (this might not be enough for the given CI job that you are trying to execute though). -- `` corresponds to a single directory located in one of the `src/ci/docker/host-*` directories. Note that image name does not necessarily correspond to a job name, as some jobs execute the same image, but with different environment variables or Docker build arguments (this is a part of the complexity that makes it difficult to run CI jobs locally). +You can run `src/ci/docker/run.sh ` directly. +A few important notes regarding the `run.sh` script: +- When executed on CI, the script expects that all submodules are checked out. + If some submodule that is accessed by the job is not available, the build will result in an error. + You should thus make sure that you have all required submodules checked out locally. + You can either do that manually through git, or set `build.submodules = true` in your `bootstrap.toml` and run a command such as `x build` to let bootstrap download the most important submodules + Note that this might not be enough for the given CI job that you are trying to execute though. +- `` corresponds to a single directory located in one of the `src/ci/docker/host-*` directories. + Note that image name does not necessarily correspond to a job name, as some jobs execute the same image, but with different environment variables or Docker build arguments + This is a part of the complexity that makes it difficult to run CI jobs locally. - If you are executing a "dist" job (job beginning with `dist-`), you should set the `DEPLOY=1` environment variable. - If you are executing an "alternative dist" job (job beginning with `dist-` and ending with `-alt`), you should set the `DEPLOY_ALT=1` environment variable. -- Some of the std tests require IPv6 support. Docker on Linux seems to have it - disabled by default. Run the commands in [`enable-docker-ipv6.sh`] to enable - IPv6 before creating the container. This only needs to be done once. +- Some of the std tests require IPv6 support. + Docker on Linux seems to have it disabled by default. + Run the commands in [`enable-docker-ipv6.sh`] to enable IPv6 before creating the container. + This only needs to be done once. ### Interactive mode -Sometimes, it can be useful to build a specific Docker image, and then run custom commands inside it, so that you can experiment with how the given system behaves. You can do that using an interactive mode, which will +Sometimes, it can be useful to build a specific Docker image, and then run custom commands inside it, so that you can experiment with how the given system behaves. +You can do that using an interactive mode, which will start a bash shell in the container, using `src/ci/docker/run.sh --dev `. -When inside the Docker container, you can run individual commands to do specific tasks. For -example, you can run `../x test tests/ui` to just run UI tests. +When inside the Docker container, you can run individual commands to do specific tasks. +For example, you can run `../x test tests/ui` to just run UI tests. Some additional notes about using the interactive mode: - The container will be deleted automatically when you exit the shell, however - the build artifacts persist in the `obj` directory. If you are switching - between different Docker images, the artifacts from previous environments - stored in the `obj` directory may confuse the build system. Sometimes you - will need to delete parts or all of the `obj` directory before building + the build artifacts persist in the `obj` directory. + If you are switching between different Docker images, the artifacts from previous environments + stored in the `obj` directory may confuse the build system. + Sometimes you will need to delete parts or all of the `obj` directory before building inside the container. -- The container is bare-bones, with only a minimal set of packages. You may - want to install some things like `apt install less vim`. -- You can open multiple shells in the container. First you need the container +- The container is bare-bones, with only a minimal set of packages. + You may want to install some things like `apt install less vim`. +- You can open multiple shells in the container. + First you need the container name (a short hash), which is displayed in the shell prompt, or you can run - `docker container ls` outside of the container to list the available - containers. With the container name, run `docker exec -it + `docker container ls` outside of the container to list the available containers. + With the container name, run `docker exec -it /bin/bash` where `` is the container name like `4ba195e95cef`. [Docker]: https://www.docker.com/ diff --git a/src/doc/rustc-dev-guide/src/tracing.md b/src/doc/rustc-dev-guide/src/tracing.md index 28c0bcc737caf..2ad035bbafbcf 100644 --- a/src/doc/rustc-dev-guide/src/tracing.md +++ b/src/doc/rustc-dev-guide/src/tracing.md @@ -74,8 +74,7 @@ RUSTC_LOG=[typeck] The query arguments are included as a tracing field which means that you can filter on the debug display of the arguments. For example, the `typeck` query has an argument `key: LocalDefId` of what is being checked. -You can use a regex to match on that `LocalDefId` to log type checking for a specific -function: +You can use a regex to match on that `LocalDefId` to log type checking for a specific function: ``` RUSTC_LOG=[typeck{key=.*name_of_item.*}] @@ -194,7 +193,7 @@ calls to `debug!` and `trace!` are only included in the program if `rust.debug-logging=true` is turned on in bootstrap.toml (it is turned off by default), so if you don't see `DEBUG` logs, especially if you run the compiler with `RUSTC_LOG=rustc rustc some.rs` and only see -`INFO` logs, make sure that `debug-logging=true` is turned on in your bootstrap.toml. +`INFO` logs, make sure that `rust.debug-logging=true` is turned on in your bootstrap.toml. ## Logging etiquette and conventions diff --git a/src/tools/clippy/clippy_lints/src/time_subtraction.rs b/src/tools/clippy/clippy_lints/src/time_subtraction.rs index 3ba59aefea068..ca8378ba7c6a2 100644 --- a/src/tools/clippy/clippy_lints/src/time_subtraction.rs +++ b/src/tools/clippy/clippy_lints/src/time_subtraction.rs @@ -85,7 +85,7 @@ impl LateLintPass<'_> for UncheckedTimeSubtraction { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) { let (lhs, rhs) = match expr.kind { ExprKind::Binary(op, lhs, rhs) if matches!(op.node, BinOpKind::Sub,) => (lhs, rhs), - ExprKind::MethodCall(fn_name, lhs, [rhs], _) if cx.ty_based_def(expr).is_diag_item(cx, sym::sub) => { + ExprKind::MethodCall(_, lhs, [rhs], _) if cx.ty_based_def(expr).is_diag_item(cx, sym::sub) => { (lhs, rhs) }, _ => return, diff --git a/src/tools/miri/tests/fail/data_race/mixed_size_read_write_read.rs b/src/tools/miri/tests/fail/data_race/mixed_size_read_write_read.rs index c84895799b695..2d3d36c0e64ab 100644 --- a/src/tools/miri/tests/fail/data_race/mixed_size_read_write_read.rs +++ b/src/tools/miri/tests/fail/data_race/mixed_size_read_write_read.rs @@ -1,6 +1,5 @@ //@compile-flags: -Zmiri-deterministic-concurrency // A case that is not covered by `mixed_size_read_write`. -#![feature(ptr_as_ref_unchecked)] use std::sync::atomic::*; use std::thread; diff --git a/tests/assembly-llvm/x86_64-bigint-helpers.rs b/tests/assembly-llvm/x86_64-bigint-helpers.rs index 9d998a31cf306..d5d1eba99f390 100644 --- a/tests/assembly-llvm/x86_64-bigint-helpers.rs +++ b/tests/assembly-llvm/x86_64-bigint-helpers.rs @@ -4,7 +4,6 @@ //@ compile-flags: -C llvm-args=-x86-asm-syntax=intel #![no_std] -#![feature(bigint_helper_methods)] // This checks that the `carrying_add` and `borrowing_sub` implementation successfully chain, // to catch issues like diff --git a/tests/codegen-llvm/bigint-helpers.rs b/tests/codegen-llvm/bigint-helpers.rs index ec70a3eabedb6..404dc901de8cb 100644 --- a/tests/codegen-llvm/bigint-helpers.rs +++ b/tests/codegen-llvm/bigint-helpers.rs @@ -1,7 +1,6 @@ //@ compile-flags: -C opt-level=3 #![crate_type = "lib"] -#![feature(bigint_helper_methods)] // Note that there's also an assembly test for this, which is what checks for // the `ADC` (Add with Carry) instruction on x86 now that the IR we emit uses diff --git a/tests/codegen-llvm/slp-vectorization-mul3.rs b/tests/codegen-llvm/slp-vectorization-mul3.rs new file mode 100644 index 0000000000000..38c0949b82713 --- /dev/null +++ b/tests/codegen-llvm/slp-vectorization-mul3.rs @@ -0,0 +1,26 @@ +//! Regression test for #142519 +//@ only-x86_64 +//@ compile-flags: -O +//@ min-llvm-version: 22 + +#![crate_type = "lib"] + +// CHECK-LABEL: @mul3 +// CHECK: phi <4 x i8> +// CHECK: load <4 x i8> +// CHECK: add <4 x i8> +// CHECK: store <4 x i8> + +#[no_mangle] +pub fn mul3(previous: &[[u8; 4]], current: &mut [[u8; 4]]) { + let mut c_bpp = [0u8; 4]; + + for i in 0..previous.len() { + current[i][0] = current[i][0].wrapping_add(c_bpp[0]); + current[i][1] = current[i][1].wrapping_add(c_bpp[1]); + current[i][2] = current[i][2].wrapping_add(c_bpp[2]); + current[i][3] = current[i][3].wrapping_add(c_bpp[3]); + + c_bpp = previous[i]; + } +} diff --git a/tests/ui/asm/aarch64v8r.rs b/tests/ui/asm/aarch64v8r.rs index 6b582bb730f07..abc254ad5f8ee 100644 --- a/tests/ui/asm/aarch64v8r.rs +++ b/tests/ui/asm/aarch64v8r.rs @@ -1,11 +1,15 @@ // Codegen test of mandatory Armv8-R AArch64 extensions +// The Cortex-R82 CPU is an implementation of the Arm v8-R AArch64 ISA so +// it also implements the ISA-level mandatory extensions. We check that with a revision //@ add-minicore -//@ revisions: hf sf +//@ revisions: hf sf r82 //@ [hf] compile-flags: --target aarch64v8r-unknown-none //@ [hf] needs-llvm-components: aarch64 //@ [sf] compile-flags: --target aarch64v8r-unknown-none-softfloat //@ [sf] needs-llvm-components: aarch64 +//@ [r82] compile-flags: --target aarch64v8r-unknown-none -C target-cpu=cortex-r82 +//@ [r82] needs-llvm-components: aarch64 //@ build-pass //@ ignore-backends: gcc diff --git a/tests/ui/asm/cortex-r82.rs b/tests/ui/asm/cortex-r82.rs new file mode 100644 index 0000000000000..74313e5cb48c1 --- /dev/null +++ b/tests/ui/asm/cortex-r82.rs @@ -0,0 +1,180 @@ +// Codegen test of mandatory Cortex-R82 extensions + +//@ add-minicore +//@ compile-flags: --target aarch64v8r-unknown-none -C target-cpu=cortex-r82 +//@ needs-llvm-components: aarch64 +//@ build-pass +//@ ignore-backends: gcc + +#![deny(dead_code)] +#![feature(no_core)] +#![no_core] +#![no_main] +#![crate_type = "rlib"] + +extern crate minicore; +use minicore::*; + +/* # Mandatory extensions + * + * A `//` comment indicates that the extension has no associated assembly instruction and cannot + * be codegen tested + * A `/* */` comment indicates that the extension is being tested in the ISA level codegen test + * (`tests/ui/asm/aarch64v8r.rs`) + * + * Note that as we use the hard-float `aarch64v8r-unknown-none` target as the base, the neon + * extension is present (`NEON_FPm=1`). This affects which R82-specific extensions are enabled + * (see "when `NEON_FPm == 1`" note in Cortex-R82 Processor Technical Reference Manual) + * + * ## References: + * + * - Arm Cortex-R82 Processor Technical Reference Manual Revision r3p1 (102670_0301_06_en Issue 6) + * section 3.2.1 has the list of mandatory extensions + * - Arm Architecture Reference Manual for A-profile architecture (ARM DDI 0487) -- has the + * mapping from features to instructions + * - Feature names in A-profile architecture (109697_0100_02_en Version 1.0) -- overview of what + * each extension mean + * */ +pub fn mandatory_extensions() { + // FEAT_GICv3 + // FEAT_GICv3p1 + // FEAT_GICv3_TDIR + feat_pmuv3(); + // FEAT_ETMv4 + // FEAT_ETMv4p1 + // FEAT_ETMv4p2 + // FEAT_ETMv4p3 + // FEAT_ETMv4p4 + // FEAT_ETMv4p5 + /* FEAT_RAS */ + // FEAT_PCSRv8 + feat_ssbs(); + feat_ssbs2(); + // FEAT_CSV2 + // FEAT_CSV2_1p1 + // FEAT_CSV3 + feat_sb(); + feat_specres(); + feat_dgh(); + // FEAT_nTLBPA + /* FEAT_CRC32 */ + /* FEAT_LSE */ + feat_rdm(); // mandatory given that NEON_FPm=1 + /* FEAT_HPDS */ + /* FEAT_PAN */ + // FEAT_HAFDBS + // FEAT_PMUv3p1 + // FEAT_TTCNP + // FEAT_XNX + /* FEAT_UAO */ + feat_pan2(); + feat_dpb(); + /* FEAT_Debugv8p2 */ + /* FEAT_ASMv8p2 */ + // FEAT_IESB + feat_fp16(); // mandatory given that NEON_FPm=1 + // FEAT_PCSRv8p2 + feat_dotprod(); // mandatory given that NEON_FPm=1 + feat_fhm(); // mandatory given that NEON_FPm=1 + feat_dpb2(); + /* FEAT_PAuth */ + // FEAT_PACQARMA3 + // FEAT_PAuth2 + // FEAT_FPAC + // FEAT_FPACCOMBINE + // FEAT_CONSTPACFIELD + feat_jscvt(); // mandatory given that NEON_FPm=1 + /* FEAT_LRCPC */ + feat_fcma(); // mandatory given that NEON_FPm=1 + // FEAT_DoPD + // FEAT_SEL2 + /* FEAT_S2FWB */ + /* FEAT_DIT */ + /* FEAT_IDST */ + /* FEAT_FlagM */ + /* FEAT_LSE2 */ + /* FEAT_LRCPC2 */ + /* FEAT_TLBIOS */ + /* FEAT_TLBIRANGE */ + /* FEAT_TTL */ + // FEAT_BBM + // FEAT_CNTSC + feat_rasv1p1(); + // FEAT_Debugv8p4 + feat_pmuv3p4(); + feat_trf(); + // FEAT_TTST + // FEAT_E0PD +} + +fn feat_pmuv3() { + unsafe { asm!("mrs x0, PMCCFILTR_EL0") } +} + +fn feat_ssbs() { + unsafe { asm!("msr SSBS, 1") } +} + +fn feat_ssbs2() { + unsafe { asm!("mrs x0, SSBS") } +} + +fn feat_sb() { + unsafe { asm!("sb") } +} + +fn feat_specres() { + unsafe { asm!("cfp rctx, x0") } +} + +fn feat_dgh() { + unsafe { asm!("dgh") } +} + +fn feat_rdm() { + unsafe { asm!("sqrdmlah v0.4h, v1.4h, v2.4h") } +} + +fn feat_pan2() { + unsafe { asm!("AT S1E1RP, x0") } +} + +fn feat_dpb() { + unsafe { asm!("DC CVAP, x0") } +} + +fn feat_fp16() { + unsafe { asm!("fmulx h0, h1, h2") } +} + +fn feat_dotprod() { + unsafe { asm!("sdot V0.4S, V1.16B, V2.16B") } +} + +fn feat_fhm() { + unsafe { asm!("fmlal v0.2s, v1.2h, v2.2h") } +} + +fn feat_dpb2() { + unsafe { asm!("DC CVADP, x0") } +} + +fn feat_jscvt() { + unsafe { asm!("fjcvtzs w0, d1") } +} + +fn feat_fcma() { + unsafe { asm!("fcadd v0.4h, v1.4h, v2.4h, #90") } +} + +fn feat_rasv1p1() { + unsafe { asm!("mrs x0, ERXMISC2_EL1") } +} + +fn feat_pmuv3p4() { + unsafe { asm!("mrs x0, PMMIR_EL1") } +} + +fn feat_trf() { + unsafe { asm!("tsb csync") } +} diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.current.stderr index 43205bd395fcd..075e4bf0384d0 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.current.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.current.stderr @@ -1,8 +1,8 @@ warning: `#[diagnostic::do_not_recommend]` does not expect any arguments --> $DIR/does_not_acccept_args.rs:12:1 | -LL | #[diagnostic::do_not_recommend(not_accepted)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[diagnostic::do_not_recommend(if, crate, do yeet, false, dyn, abstract, gen, not_accepted)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(malformed_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.next.stderr index 43205bd395fcd..075e4bf0384d0 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.next.stderr @@ -1,8 +1,8 @@ warning: `#[diagnostic::do_not_recommend]` does not expect any arguments --> $DIR/does_not_acccept_args.rs:12:1 | -LL | #[diagnostic::do_not_recommend(not_accepted)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[diagnostic::do_not_recommend(if, crate, do yeet, false, dyn, abstract, gen, not_accepted)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(malformed_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.rs b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.rs index 918bf5a0113ea..943b5a37f9385 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.rs +++ b/tests/ui/diagnostic_namespace/do_not_recommend/does_not_acccept_args.rs @@ -9,7 +9,7 @@ trait Bar {} trait Baz {} trait Boo {} -#[diagnostic::do_not_recommend(not_accepted)] +#[diagnostic::do_not_recommend(if, crate, do yeet, false, dyn, abstract, gen, not_accepted)] //~^ WARNING `#[diagnostic::do_not_recommend]` does not expect any arguments impl Foo for T where T: Send {} diff --git a/tests/ui/lint/unused/match_with_guard.rs b/tests/ui/lint/unused/match_with_guard.rs new file mode 100644 index 0000000000000..61e4321f67352 --- /dev/null +++ b/tests/ui/lint/unused/match_with_guard.rs @@ -0,0 +1,10 @@ +//! The mere presence of a match guard should not deem bound variables "used". +//! Regression test for https://github.com/rust-lang/rust/issues/151983 +//@ check-pass +#![warn(unused)] +fn main() { + match Some(42) { + Some(unused) if true => (), //~WARN unused variable: `unused` + _ => (), + } +} diff --git a/tests/ui/lint/unused/match_with_guard.stderr b/tests/ui/lint/unused/match_with_guard.stderr new file mode 100644 index 0000000000000..6a509e568b686 --- /dev/null +++ b/tests/ui/lint/unused/match_with_guard.stderr @@ -0,0 +1,15 @@ +warning: unused variable: `unused` + --> $DIR/match_with_guard.rs:7:14 + | +LL | Some(unused) if true => (), + | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_unused` + | +note: the lint level is defined here + --> $DIR/match_with_guard.rs:4:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` + +warning: 1 warning emitted +