diff options
424 files changed, 7969 insertions, 5851 deletions
diff --git a/.editorconfig b/.editorconfig index ef8ed24c52a..1b137cf4ebe 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,9 +7,18 @@ root = true [*] end_of_line = lf charset = utf-8 -trim_trailing_whitespace = true insert_final_newline = true +# some tests need trailing whitespace in output snapshots +[!tests/] +trim_trailing_whitespace = true +# for actual source code files of test, we still don't want trailing whitespace +[tests/**.{rs,js}] +trim_trailing_whitespace = true +# these specific source files need to have trailing whitespace. +[tests/ui/{frontmatter/frontmatter-whitespace-3.rs,parser/shebang/shebang-space.rs}] +trim_trailing_whitespace = false + [!src/llvm-project] indent_style = space indent_size = 4 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6ce543071d8..df5dda76eb7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -52,7 +52,7 @@ jobs: run_type: ${{ steps.jobs.outputs.run_type }} steps: - name: Checkout the source code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Test citool # Only test citool on the auto branch, to reduce latency of the calculate matrix job # on PR/try builds. @@ -113,7 +113,7 @@ jobs: run: git config --global core.autocrlf false - name: checkout the source code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 2 @@ -313,7 +313,7 @@ jobs: if: ${{ !cancelled() && contains(fromJSON('["auto", "try"]'), needs.calculate_matrix.outputs.run_type) }} steps: - name: checkout the source code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 2 # Calculate the exit status of the whole CI workflow. diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml index 9d4b6192d6e..80ffd67e04e 100644 --- a/.github/workflows/dependencies.yml +++ b/.github/workflows/dependencies.yml @@ -51,7 +51,7 @@ jobs: runs-on: ubuntu-24.04 steps: - name: checkout the source code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: submodules: recursive - name: install the bootstrap toolchain @@ -101,7 +101,7 @@ jobs: pull-requests: write steps: - name: checkout the source code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: download Cargo.lock from update job uses: actions/download-artifact@v4 diff --git a/.github/workflows/ghcr.yml b/.github/workflows/ghcr.yml index 6d050d98cb2..a89867efe66 100644 --- a/.github/workflows/ghcr.yml +++ b/.github/workflows/ghcr.yml @@ -29,7 +29,7 @@ jobs: # Needed to write to the ghcr.io registry packages: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: persist-credentials: false diff --git a/.github/workflows/post-merge.yml b/.github/workflows/post-merge.yml index ca088ba31fd..12ff4be4f1e 100644 --- a/.github/workflows/post-merge.yml +++ b/.github/workflows/post-merge.yml @@ -15,7 +15,7 @@ jobs: permissions: pull-requests: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: # Make sure that we have enough commits to find the parent merge commit. # Since all merges should be through merge commits, fetching two commits diff --git a/Cargo.lock b/Cargo.lock index 4eb246995b1..8c980616e83 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3480,6 +3480,7 @@ dependencies = [ name = "rustc_attr_parsing" version = "0.0.0" dependencies = [ + "itertools", "rustc_abi", "rustc_ast", "rustc_ast_pretty", @@ -3889,6 +3890,7 @@ dependencies = [ name = "rustc_hir" version = "0.0.0" dependencies = [ + "bitflags", "odht", "rustc_abi", "rustc_arena", diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index 2cc07694afb..f1e810a8b9e 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -1,5 +1,6 @@ use rustc_ast::{Block, BlockCheckMode, Local, LocalKind, Stmt, StmtKind}; use rustc_hir as hir; +use rustc_hir::Target; use rustc_span::sym; use smallvec::SmallVec; @@ -109,7 +110,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; let span = self.lower_span(l.span); let source = hir::LocalSource::Normal; - self.lower_attrs(hir_id, &l.attrs, l.span); + self.lower_attrs(hir_id, &l.attrs, l.span, Target::Statement); self.arena.alloc(hir::LetStmt { hir_id, super_, ty, pat, init, els, span, source }) } diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 2ddbf083a09..cbd17d66b75 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -7,7 +7,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir as hir; use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{HirId, find_attr}; +use rustc_hir::{HirId, Target, find_attr}; use rustc_middle::span_bug; use rustc_middle::ty::TyCtxt; use rustc_session::errors::report_lit_error; @@ -74,7 +74,7 @@ impl<'hir> LoweringContext<'_, 'hir> { if !e.attrs.is_empty() { let old_attrs = self.attrs.get(&ex.hir_id.local_id).copied().unwrap_or(&[]); let new_attrs = self - .lower_attrs_vec(&e.attrs, e.span, ex.hir_id) + .lower_attrs_vec(&e.attrs, e.span, ex.hir_id, Target::from_expr(e)) .into_iter() .chain(old_attrs.iter().cloned()); let new_attrs = &*self.arena.alloc_from_iter(new_attrs); @@ -97,7 +97,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } let expr_hir_id = self.lower_node_id(e.id); - let attrs = self.lower_attrs(expr_hir_id, &e.attrs, e.span); + let attrs = self.lower_attrs(expr_hir_id, &e.attrs, e.span, Target::from_expr(e)); let kind = match &e.kind { ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)), @@ -639,7 +639,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let guard = arm.guard.as_ref().map(|cond| self.lower_expr(cond)); let hir_id = self.next_id(); let span = self.lower_span(arm.span); - self.lower_attrs(hir_id, &arm.attrs, arm.span); + self.lower_attrs(hir_id, &arm.attrs, arm.span, Target::Arm); let is_never_pattern = pat.is_never_pattern(); // We need to lower the body even if it's unneeded for never pattern in match, // ensure that we can get HirId for DefId if need (issue #137708). @@ -820,6 +820,7 @@ impl<'hir> LoweringContext<'_, 'hir> { span: unstable_span, }], span, + Target::Fn, ); } } @@ -1654,7 +1655,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_expr_field(&mut self, f: &ExprField) -> hir::ExprField<'hir> { let hir_id = self.lower_node_id(f.id); - self.lower_attrs(hir_id, &f.attrs, f.span); + self.lower_attrs(hir_id, &f.attrs, f.span, Target::ExprField); hir::ExprField { hir_id, ident: self.lower_ident(f.ident), @@ -1910,7 +1911,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // // Also, add the attributes to the outer returned expr node. let expr = self.expr_drop_temps_mut(for_span, match_expr); - self.lower_attrs(expr.hir_id, &e.attrs, e.span); + self.lower_attrs(expr.hir_id, &e.attrs, e.span, Target::from_expr(e)); expr } @@ -1967,7 +1968,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let val_ident = Ident::with_dummy_span(sym::val); let (val_pat, val_pat_nid) = self.pat_ident(span, val_ident); let val_expr = self.expr_ident(span, val_ident, val_pat_nid); - self.lower_attrs(val_expr.hir_id, &attrs, span); + self.lower_attrs(val_expr.hir_id, &attrs, span, Target::Expression); let continue_pat = self.pat_cf_continue(unstable_span, val_pat); self.arm(continue_pat, val_expr) }; @@ -1998,7 +1999,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let ret_expr = self.checked_return(Some(from_residual_expr)); self.arena.alloc(self.expr(try_span, ret_expr)) }; - self.lower_attrs(ret_expr.hir_id, &attrs, span); + self.lower_attrs(ret_expr.hir_id, &attrs, span, Target::Expression); let break_pat = self.pat_cf_break(try_span, residual_local); self.arm(break_pat, ret_expr) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 235573c96e4..72817a0a9a0 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -5,7 +5,7 @@ use rustc_errors::{E0570, ErrorGuaranteed, struct_span_code_err}; use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{DefKind, PerNS, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId}; -use rustc_hir::{self as hir, HirId, LifetimeSource, PredicateOrigin, find_attr}; +use rustc_hir::{self as hir, HirId, LifetimeSource, PredicateOrigin, Target, find_attr}; use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::span_bug; use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; @@ -80,7 +80,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { self.with_lctx(CRATE_NODE_ID, |lctx| { let module = lctx.lower_mod(&c.items, &c.spans); // FIXME(jdonszelman): is dummy span ever a problem here? - lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs, DUMMY_SP); + lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs, DUMMY_SP, Target::Crate); hir::OwnerNode::Crate(module) }) } @@ -136,7 +136,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_item(&mut self, i: &Item) -> &'hir hir::Item<'hir> { let vis_span = self.lower_span(i.vis.span); let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id); - let attrs = self.lower_attrs(hir_id, &i.attrs, i.span); + let attrs = self.lower_attrs(hir_id, &i.attrs, i.span, Target::from_ast_item(i)); let kind = self.lower_item_kind(i.span, i.id, hir_id, attrs, vis_span, &i.kind); let item = hir::Item { owner_id: hir_id.expect_owner(), @@ -436,14 +436,14 @@ impl<'hir> LoweringContext<'_, 'hir> { let body = Box::new(self.lower_delim_args(body)); let def_id = self.local_def_id(id); let def_kind = self.tcx.def_kind(def_id); - let DefKind::Macro(macro_kind) = def_kind else { + let DefKind::Macro(macro_kinds) = def_kind else { unreachable!( "expected DefKind::Macro for macro item, found {}", def_kind.descr(def_id.to_def_id()) ); }; let macro_def = self.arena.alloc(ast::MacroDef { body, macro_rules: *macro_rules }); - hir::ItemKind::Macro(ident, macro_def, macro_kind) + hir::ItemKind::Macro(ident, macro_def, macro_kinds) } ItemKind::Delegation(box delegation) => { let delegation_results = self.lower_delegation(delegation, id, false); @@ -621,7 +621,8 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> { let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id); let owner_id = hir_id.expect_owner(); - let attrs = self.lower_attrs(hir_id, &i.attrs, i.span); + let attrs = + self.lower_attrs(hir_id, &i.attrs, i.span, Target::from_foreign_item_kind(&i.kind)); let (ident, kind) = match &i.kind { ForeignItemKind::Fn(box Fn { sig, ident, generics, define_opaque, .. }) => { let fdec = &sig.decl; @@ -690,7 +691,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_variant(&mut self, item_kind: &ItemKind, v: &Variant) -> hir::Variant<'hir> { let hir_id = self.lower_node_id(v.id); - self.lower_attrs(hir_id, &v.attrs, v.span); + self.lower_attrs(hir_id, &v.attrs, v.span, Target::Variant); hir::Variant { hir_id, def_id: self.local_def_id(v.id), @@ -773,7 +774,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> hir::FieldDef<'hir> { let ty = self.lower_ty(&f.ty, ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy)); let hir_id = self.lower_node_id(f.id); - self.lower_attrs(hir_id, &f.attrs, f.span); + self.lower_attrs(hir_id, &f.attrs, f.span, Target::Field); hir::FieldDef { span: self.lower_span(f.span), hir_id, @@ -792,7 +793,12 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> { let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id); - let attrs = self.lower_attrs(hir_id, &i.attrs, i.span); + let attrs = self.lower_attrs( + hir_id, + &i.attrs, + i.span, + Target::from_assoc_item_kind(&i.kind, AssocCtxt::Trait), + ); let trait_item_def_id = hir_id.expect_owner(); let (ident, generics, kind, has_default) = match &i.kind { @@ -1001,7 +1007,12 @@ impl<'hir> LoweringContext<'_, 'hir> { let has_value = true; let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value); let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id); - let attrs = self.lower_attrs(hir_id, &i.attrs, i.span); + let attrs = self.lower_attrs( + hir_id, + &i.attrs, + i.span, + Target::from_assoc_item_kind(&i.kind, AssocCtxt::Impl { of_trait: is_in_trait_impl }), + ); let (ident, (generics, kind)) = match &i.kind { AssocItemKind::Const(box ConstItem { @@ -1171,7 +1182,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_param(&mut self, param: &Param) -> hir::Param<'hir> { let hir_id = self.lower_node_id(param.id); - self.lower_attrs(hir_id, ¶m.attrs, param.span); + self.lower_attrs(hir_id, ¶m.attrs, param.span, Target::Param); hir::Param { hir_id, pat: self.lower_pat(¶m.pat), @@ -1851,7 +1862,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> hir::WherePredicate<'hir> { let hir_id = self.lower_node_id(pred.id); let span = self.lower_span(pred.span); - self.lower_attrs(hir_id, &pred.attrs, span); + self.lower_attrs(hir_id, &pred.attrs, span, Target::WherePredicate); let kind = self.arena.alloc(match &pred.kind { WherePredicateKind::BoundPredicate(WhereBoundPredicate { bound_generic_params, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 465d9dc82bc..70595391b85 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -54,7 +54,7 @@ use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId}; use rustc_hir::lints::DelayedLint; use rustc_hir::{ self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LifetimeSource, - LifetimeSyntax, ParamName, TraitCandidate, + LifetimeSyntax, ParamName, Target, TraitCandidate, }; use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_macros::extension; @@ -943,11 +943,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { id: HirId, attrs: &[Attribute], target_span: Span, + target: Target, ) -> &'hir [hir::Attribute] { if attrs.is_empty() { &[] } else { - let lowered_attrs = self.lower_attrs_vec(attrs, self.lower_span(target_span), id); + let lowered_attrs = + self.lower_attrs_vec(attrs, self.lower_span(target_span), id, target); assert_eq!(id.owner, self.current_hir_id_owner); let ret = self.arena.alloc_from_iter(lowered_attrs); @@ -972,12 +974,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { attrs: &[Attribute], target_span: Span, target_hir_id: HirId, + target: Target, ) -> Vec<hir::Attribute> { let l = self.span_lowerer(); self.attribute_parser.parse_attribute_list( attrs, target_span, target_hir_id, + target, OmitDoc::Lower, |s| l.lower(s), |l| { @@ -1942,7 +1946,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let (name, kind) = self.lower_generic_param_kind(param, source); let hir_id = self.lower_node_id(param.id); - self.lower_attrs(hir_id, ¶m.attrs, param.span()); + self.lower_attrs(hir_id, ¶m.attrs, param.span(), Target::Param); hir::GenericParam { hir_id, def_id: self.local_def_id(param.id), diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index b6533060a76..b8f86247875 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use rustc_ast::*; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{self as hir, LangItem}; +use rustc_hir::{self as hir, LangItem, Target}; use rustc_middle::span_bug; use rustc_span::source_map::{Spanned, respan}; use rustc_span::{DesugaringKind, Ident, Span}; @@ -93,7 +93,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let fs = self.arena.alloc_from_iter(fields.iter().map(|f| { let hir_id = self.lower_node_id(f.id); - self.lower_attrs(hir_id, &f.attrs, f.span); + self.lower_attrs(hir_id, &f.attrs, f.span, Target::PatField); hir::PatField { hir_id, diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index dc2eb17589c..f62b8d1d576 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1741,7 +1741,7 @@ fn deny_equality_constraints( .map(|segment| segment.ident.name) .zip(poly.trait_ref.path.segments.iter().map(|segment| segment.ident.name)) .all(|(a, b)| a == b) - && let Some(potential_assoc) = full_path.segments.iter().last() + && let Some(potential_assoc) = full_path.segments.last() { suggest(poly, potential_assoc, predicate); } diff --git a/compiler/rustc_attr_parsing/Cargo.toml b/compiler/rustc_attr_parsing/Cargo.toml index cec9d62e656..bac89373b67 100644 --- a/compiler/rustc_attr_parsing/Cargo.toml +++ b/compiler/rustc_attr_parsing/Cargo.toml @@ -5,6 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start +itertools = "0.12" rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl index de22ea322c7..4fb66a81652 100644 --- a/compiler/rustc_attr_parsing/messages.ftl +++ b/compiler/rustc_attr_parsing/messages.ftl @@ -10,6 +10,12 @@ attr_parsing_empty_attribute = unused attribute .suggestion = remove this attribute +attr_parsing_invalid_target = `#[{$name}]` attribute cannot be used on {$target} + .help = `#[{$name}]` can {$only}be applied to {$applied} +attr_parsing_invalid_target_lint = `#[{$name}]` attribute cannot be used on {$target} + .warn = {-attr_parsing_previously_accepted} + .help = `#[{$name}]` can {$only}be applied to {$applied} + attr_parsing_empty_confusables = expected at least one confusable name attr_parsing_expected_one_cfg_pattern = diff --git a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs index b3393e93de8..4d995027814 100644 --- a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs +++ b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs @@ -2,10 +2,12 @@ use std::iter; use rustc_feature::{AttributeTemplate, template}; use rustc_hir::attrs::AttributeKind; +use rustc_hir::{MethodKind, Target}; use rustc_span::{Span, Symbol, sym}; use super::{CombineAttributeParser, ConvertFn}; -use crate::context::{AcceptContext, Stage}; +use crate::context::MaybeWarn::{Allow, Warn}; +use crate::context::{AcceptContext, AllowedTargets, Stage}; use crate::parser::ArgParser; use crate::session_diagnostics; @@ -15,6 +17,12 @@ impl<S: Stage> CombineAttributeParser<S> for AllowInternalUnstableParser { type Item = (Symbol, Span); const CONVERT: ConvertFn<Self::Item> = |items, span| AttributeKind::AllowInternalUnstable(items, span); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::MacroDef), + Allow(Target::Fn), + Warn(Target::Field), + Warn(Target::Arm), + ]); const TEMPLATE: AttributeTemplate = template!(Word, List: &["feat1, feat2, ..."]); fn extend<'c>( @@ -32,6 +40,11 @@ impl<S: Stage> CombineAttributeParser<S> for UnstableFeatureBoundParser { const PATH: &'static [rustc_span::Symbol] = &[sym::unstable_feature_bound]; type Item = (Symbol, Span); const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::UnstableFeatureBound(items); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Impl { of_trait: true }), + Allow(Target::Trait), + ]); const TEMPLATE: AttributeTemplate = template!(Word, List: &["feat1, feat2, ..."]); fn extend<'c>( @@ -53,6 +66,13 @@ impl<S: Stage> CombineAttributeParser<S> for AllowConstFnUnstableParser { type Item = Symbol; const CONVERT: ConvertFn<Self::Item> = |items, first_span| AttributeKind::AllowConstFnUnstable(items, first_span); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + ]); const TEMPLATE: AttributeTemplate = template!(Word, List: &["feat1, feat2, ..."]); fn extend<'c>( diff --git a/compiler/rustc_attr_parsing/src/attributes/body.rs b/compiler/rustc_attr_parsing/src/attributes/body.rs index ab9330216f6..88540384621 100644 --- a/compiler/rustc_attr_parsing/src/attributes/body.rs +++ b/compiler/rustc_attr_parsing/src/attributes/body.rs @@ -1,15 +1,18 @@ //! Attributes that can be found in function body. +use rustc_hir::Target; use rustc_hir::attrs::AttributeKind; use rustc_span::{Symbol, sym}; use super::{NoArgsAttributeParser, OnDuplicate}; -use crate::context::Stage; +use crate::context::MaybeWarn::Allow; +use crate::context::{AllowedTargets, Stage}; pub(crate) struct CoroutineParser; impl<S: Stage> NoArgsAttributeParser<S> for CoroutineParser { const PATH: &[Symbol] = &[sym::coroutine]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Closure)]); const CREATE: fn(rustc_span::Span) -> AttributeKind = |span| AttributeKind::Coroutine(span); } diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index a9f77195d1b..6ea073896c2 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -1,5 +1,6 @@ use rustc_feature::{AttributeTemplate, template}; use rustc_hir::attrs::{AttributeKind, CoverageAttrKind, OptimizeAttr, UsedBy}; +use rustc_hir::{MethodKind, Target}; use rustc_session::parse::feature_err; use rustc_span::{Span, Symbol, sym}; @@ -7,7 +8,8 @@ use super::{ AcceptMapping, AttributeOrder, AttributeParser, CombineAttributeParser, ConvertFn, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser, }; -use crate::context::{AcceptContext, FinalizeContext, Stage}; +use crate::context::MaybeWarn::{Allow, Warn}; +use crate::context::{AcceptContext, AllowedTargets, FinalizeContext, Stage}; use crate::parser::ArgParser; use crate::session_diagnostics::{NakedFunctionIncompatibleAttribute, NullOnExport}; @@ -17,6 +19,13 @@ impl<S: Stage> SingleAttributeParser<S> for OptimizeParser { const PATH: &[Symbol] = &[sym::optimize]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Closure), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::Method(MethodKind::Inherent)), + ]); const TEMPLATE: AttributeTemplate = template!(List: &["size", "speed", "none"]); fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { @@ -49,6 +58,15 @@ pub(crate) struct ColdParser; impl<S: Stage> NoArgsAttributeParser<S> for ColdParser { const PATH: &[Symbol] = &[sym::cold]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::ForeignFn), + Allow(Target::Closure), + ]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::Cold; } @@ -58,6 +76,17 @@ impl<S: Stage> SingleAttributeParser<S> for CoverageParser { const PATH: &[Symbol] = &[sym::coverage]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Closure), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Impl { of_trait: true }), + Allow(Target::Impl { of_trait: false }), + Allow(Target::Mod), + Allow(Target::Crate), + ]); const TEMPLATE: AttributeTemplate = template!(OneOf: &[sym::off, sym::on]); fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { @@ -97,6 +126,16 @@ impl<S: Stage> SingleAttributeParser<S> for ExportNameParser { const PATH: &[rustc_span::Symbol] = &[sym::export_name]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Static), + Allow(Target::Fn), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + Warn(Target::Field), + Warn(Target::Arm), + Warn(Target::MacroDef), + ]); const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name"); fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { @@ -138,6 +177,12 @@ impl<S: Stage> AttributeParser<S> for NakedParser { this.span = Some(cx.attr_span); } })]; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + ]); fn finalize(self, cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> { // FIXME(jdonszelmann): upgrade this list to *parsed* attributes @@ -230,6 +275,18 @@ pub(crate) struct TrackCallerParser; impl<S: Stage> NoArgsAttributeParser<S> for TrackCallerParser { const PATH: &[Symbol] = &[sym::track_caller]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::ForeignFn), + Allow(Target::Closure), + Warn(Target::MacroDef), + Warn(Target::Arm), + Warn(Target::Field), + ]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::TrackCaller; } @@ -237,6 +294,12 @@ pub(crate) struct NoMangleParser; impl<S: Stage> NoArgsAttributeParser<S> for NoMangleParser { const PATH: &[Symbol] = &[sym::no_mangle]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ + Allow(Target::Fn), + Allow(Target::Static), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::TraitImpl)), + ]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoMangle; } @@ -310,6 +373,7 @@ impl<S: Stage> AttributeParser<S> for UsedParser { } }, )]; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Static)]); fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> { // Ratcheting behaviour, if both `linker` and `compiler` are specified, use `linker` @@ -373,4 +437,15 @@ impl<S: Stage> CombineAttributeParser<S> for TargetFeatureParser { } features } + + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + Warn(Target::Statement), + Warn(Target::Field), + Warn(Target::Arm), + Warn(Target::MacroDef), + ]); } diff --git a/compiler/rustc_attr_parsing/src/attributes/confusables.rs b/compiler/rustc_attr_parsing/src/attributes/confusables.rs index edd22172ca2..00f949c82c5 100644 --- a/compiler/rustc_attr_parsing/src/attributes/confusables.rs +++ b/compiler/rustc_attr_parsing/src/attributes/confusables.rs @@ -1,12 +1,13 @@ use rustc_feature::template; use rustc_hir::attrs::AttributeKind; +use rustc_hir::{MethodKind, Target}; use rustc_span::{Span, Symbol, sym}; use thin_vec::ThinVec; use super::{AcceptMapping, AttributeParser}; -use crate::context::{FinalizeContext, Stage}; +use crate::context::MaybeWarn::Allow; +use crate::context::{AllowedTargets, FinalizeContext, Stage}; use crate::session_diagnostics; - #[derive(Default)] pub(crate) struct ConfusablesParser { confusables: ThinVec<Symbol>, @@ -41,6 +42,8 @@ impl<S: Stage> AttributeParser<S> for ConfusablesParser { this.first_span.get_or_insert(cx.attr_span); }, )]; + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowList(&[Allow(Target::Method(MethodKind::Inherent))]); fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> { if self.confusables.is_empty() { diff --git a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs index e57ea8bbb5c..8101c91460f 100644 --- a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs +++ b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs @@ -1,13 +1,14 @@ use rustc_feature::{AttributeTemplate, template}; use rustc_hir::attrs::{AttributeKind, DeprecatedSince, Deprecation}; +use rustc_hir::{MethodKind, Target}; use rustc_span::{Span, Symbol, sym}; use super::util::parse_version; use super::{AttributeOrder, OnDuplicate, SingleAttributeParser}; -use crate::context::{AcceptContext, Stage}; +use crate::context::MaybeWarn::{Allow, Error}; +use crate::context::{AcceptContext, AllowedTargets, Stage}; use crate::parser::ArgParser; use crate::session_diagnostics; - pub(crate) struct DeprecationParser; fn get<S: Stage>( @@ -38,6 +39,30 @@ impl<S: Stage> SingleAttributeParser<S> for DeprecationParser { const PATH: &[Symbol] = &[sym::deprecated]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ + Allow(Target::Fn), + Allow(Target::Mod), + Allow(Target::Struct), + Allow(Target::Enum), + Allow(Target::Union), + Allow(Target::Const), + Allow(Target::Static), + Allow(Target::MacroDef), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::TyAlias), + Allow(Target::Use), + Allow(Target::ForeignFn), + Allow(Target::Field), + Allow(Target::Trait), + Allow(Target::AssocTy), + Allow(Target::AssocConst), + Allow(Target::Variant), + Allow(Target::Impl { of_trait: false }), //FIXME This does not make sense + Allow(Target::Crate), + Error(Target::WherePredicate), + ]); const TEMPLATE: AttributeTemplate = template!( Word, List: &[r#"since = "version""#, r#"note = "reason""#, r#"since = "version", note = "reason""#], diff --git a/compiler/rustc_attr_parsing/src/attributes/dummy.rs b/compiler/rustc_attr_parsing/src/attributes/dummy.rs index bbcd9ab530c..85842b1b5c5 100644 --- a/compiler/rustc_attr_parsing/src/attributes/dummy.rs +++ b/compiler/rustc_attr_parsing/src/attributes/dummy.rs @@ -3,14 +3,14 @@ use rustc_hir::attrs::AttributeKind; use rustc_span::{Symbol, sym}; use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser}; -use crate::context::{AcceptContext, Stage}; +use crate::context::{ALL_TARGETS, AcceptContext, AllowedTargets, Stage}; use crate::parser::ArgParser; - pub(crate) struct DummyParser; impl<S: Stage> SingleAttributeParser<S> for DummyParser { const PATH: &[Symbol] = &[sym::rustc_dummy]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Ignore; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); const TEMPLATE: AttributeTemplate = template!(Word); // Anything, really fn convert(_: &mut AcceptContext<'_, '_, S>, _: &ArgParser<'_>) -> Option<AttributeKind> { diff --git a/compiler/rustc_attr_parsing/src/attributes/inline.rs b/compiler/rustc_attr_parsing/src/attributes/inline.rs index e9a45f20bff..6a659a95b85 100644 --- a/compiler/rustc_attr_parsing/src/attributes/inline.rs +++ b/compiler/rustc_attr_parsing/src/attributes/inline.rs @@ -5,19 +5,34 @@ use rustc_feature::{AttributeTemplate, template}; use rustc_hir::attrs::{AttributeKind, InlineAttr}; use rustc_hir::lints::AttributeLintKind; +use rustc_hir::{MethodKind, Target}; use rustc_span::{Symbol, sym}; use super::{AcceptContext, AttributeOrder, OnDuplicate}; use crate::attributes::SingleAttributeParser; -use crate::context::Stage; +use crate::context::MaybeWarn::{Allow, Warn}; +use crate::context::{AllowedTargets, Stage}; use crate::parser::ArgParser; - pub(crate) struct InlineParser; impl<S: Stage> SingleAttributeParser<S> for InlineParser { const PATH: &'static [Symbol] = &[sym::inline]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::Closure), + Allow(Target::Delegation { mac: false }), + Warn(Target::Method(MethodKind::Trait { body: false })), + Warn(Target::ForeignFn), + Warn(Target::Field), + Warn(Target::MacroDef), + Warn(Target::Arm), + Warn(Target::AssocConst), + ]); const TEMPLATE: AttributeTemplate = template!( Word, List: &["always", "never"], @@ -63,6 +78,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcForceInlineParser { const PATH: &'static [Symbol] = &[sym::rustc_force_inline]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); const TEMPLATE: AttributeTemplate = template!(Word, List: &["reason"], NameValueStr: "reason"); fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index d406c30b83e..552b9dfabc2 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -1,21 +1,26 @@ use rustc_feature::{AttributeTemplate, template}; -use rustc_hir::attrs::AttributeKind; use rustc_hir::attrs::AttributeKind::{LinkName, LinkOrdinal, LinkSection}; +use rustc_hir::attrs::{AttributeKind, Linkage}; +use rustc_hir::{MethodKind, Target}; use rustc_span::{Span, Symbol, sym}; use crate::attributes::{ AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser, }; -use crate::context::{AcceptContext, Stage, parse_single_integer}; +use crate::context::MaybeWarn::Allow; +use crate::context::{ALL_TARGETS, AcceptContext, AllowedTargets, Stage, parse_single_integer}; use crate::parser::ArgParser; use crate::session_diagnostics::{LinkOrdinalOutOfRange, NullOnLinkSection}; - pub(crate) struct LinkNameParser; impl<S: Stage> SingleAttributeParser<S> for LinkNameParser { const PATH: &[Symbol] = &[sym::link_name]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ + Allow(Target::ForeignFn), + Allow(Target::ForeignStatic), + ]); const TEMPLATE: AttributeTemplate = template!( NameValueStr: "name", "https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_name-attribute" @@ -41,6 +46,8 @@ impl<S: Stage> SingleAttributeParser<S> for LinkSectionParser { const PATH: &[Symbol] = &[sym::link_section]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError; + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Static), Allow(Target::Fn)]); const TEMPLATE: AttributeTemplate = template!( NameValueStr: "name", "https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute" @@ -70,6 +77,7 @@ pub(crate) struct ExportStableParser; impl<S: Stage> NoArgsAttributeParser<S> for ExportStableParser { const PATH: &[Symbol] = &[sym::export_stable]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); //FIXME Still checked fully in `check_attr.rs` const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ExportStable; } @@ -77,6 +85,7 @@ pub(crate) struct FfiConstParser; impl<S: Stage> NoArgsAttributeParser<S> for FfiConstParser { const PATH: &[Symbol] = &[sym::ffi_const]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::ForeignFn)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::FfiConst; } @@ -84,6 +93,7 @@ pub(crate) struct FfiPureParser; impl<S: Stage> NoArgsAttributeParser<S> for FfiPureParser { const PATH: &[Symbol] = &[sym::ffi_pure]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::ForeignFn)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::FfiPure; } @@ -91,6 +101,12 @@ pub(crate) struct StdInternalSymbolParser; impl<S: Stage> NoArgsAttributeParser<S> for StdInternalSymbolParser { const PATH: &[Symbol] = &[sym::rustc_std_internal_symbol]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::ForeignFn), + Allow(Target::Static), + Allow(Target::ForeignStatic), + ]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::StdInternalSymbol; } @@ -100,6 +116,8 @@ impl<S: Stage> SingleAttributeParser<S> for LinkOrdinalParser { const PATH: &[Symbol] = &[sym::link_ordinal]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowList(&[Allow(Target::ForeignFn), Allow(Target::ForeignStatic)]); const TEMPLATE: AttributeTemplate = template!( List: &["ordinal"], "https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_ordinal-attribute" @@ -129,3 +147,87 @@ impl<S: Stage> SingleAttributeParser<S> for LinkOrdinalParser { Some(LinkOrdinal { ordinal, span: cx.attr_span }) } } + +pub(crate) struct LinkageParser; + +impl<S: Stage> SingleAttributeParser<S> for LinkageParser { + const PATH: &[Symbol] = &[sym::linkage]; + + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; + + const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::Static), + Allow(Target::ForeignStatic), + Allow(Target::ForeignFn), + ]); + + const TEMPLATE: AttributeTemplate = template!(NameValueStr: [ + "available_externally", + "common", + "extern_weak", + "external", + "internal", + "linkonce", + "linkonce_odr", + "weak", + "weak_odr", + ]); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { + let Some(name_value) = args.name_value() else { + cx.expected_name_value(cx.attr_span, Some(sym::linkage)); + return None; + }; + + let Some(value) = name_value.value_as_str() else { + cx.expected_string_literal(name_value.value_span, Some(name_value.value_as_lit())); + return None; + }; + + // Use the names from src/llvm/docs/LangRef.rst here. Most types are only + // applicable to variable declarations and may not really make sense for + // Rust code in the first place but allow them anyway and trust that the + // user knows what they're doing. Who knows, unanticipated use cases may pop + // up in the future. + // + // ghost, dllimport, dllexport and linkonce_odr_autohide are not supported + // and don't have to be, LLVM treats them as no-ops. + let linkage = match value { + sym::available_externally => Linkage::AvailableExternally, + sym::common => Linkage::Common, + sym::extern_weak => Linkage::ExternalWeak, + sym::external => Linkage::External, + sym::internal => Linkage::Internal, + sym::linkonce => Linkage::LinkOnceAny, + sym::linkonce_odr => Linkage::LinkOnceODR, + sym::weak => Linkage::WeakAny, + sym::weak_odr => Linkage::WeakODR, + + _ => { + cx.expected_specific_argument( + name_value.value_span, + vec![ + "available_externally", + "common", + "extern_weak", + "external", + "internal", + "linkonce", + "linkonce_odr", + "weak", + "weak_odr", + ], + ); + return None; + } + }; + + Some(AttributeKind::Linkage(linkage, cx.attr_span)) + } +} diff --git a/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs index 9530fec07d6..2b586d4003c 100644 --- a/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs +++ b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs @@ -1,13 +1,21 @@ use rustc_hir::attrs::AttributeKind; +use rustc_hir::{MethodKind, Target}; use rustc_span::{Span, Symbol, sym}; use crate::attributes::{NoArgsAttributeParser, OnDuplicate}; -use crate::context::Stage; - +use crate::context::MaybeWarn::{Allow, Error}; +use crate::context::{AllowedTargets, Stage}; pub(crate) struct AsPtrParser; impl<S: Stage> NoArgsAttributeParser<S> for AsPtrParser { const PATH: &[Symbol] = &[sym::rustc_as_ptr]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + ]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::AsPtr; } @@ -15,6 +23,11 @@ pub(crate) struct PubTransparentParser; impl<S: Stage> NoArgsAttributeParser<S> for PubTransparentParser { const PATH: &[Symbol] = &[sym::rustc_pub_transparent]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Struct), + Allow(Target::Enum), + Allow(Target::Union), + ]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::PubTransparent; } @@ -22,6 +35,11 @@ pub(crate) struct PassByValueParser; impl<S: Stage> NoArgsAttributeParser<S> for PassByValueParser { const PATH: &[Symbol] = &[sym::rustc_pass_by_value]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Struct), + Allow(Target::Enum), + Allow(Target::TyAlias), + ]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::PassByValue; } @@ -29,5 +47,10 @@ pub(crate) struct AutomaticallyDerivedParser; impl<S: Stage> NoArgsAttributeParser<S> for AutomaticallyDerivedParser { const PATH: &[Symbol] = &[sym::automatically_derived]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ + Allow(Target::Impl { of_trait: true }), + Error(Target::Crate), + Error(Target::WherePredicate), + ]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::AutomaticallyDerived; } diff --git a/compiler/rustc_attr_parsing/src/attributes/loop_match.rs b/compiler/rustc_attr_parsing/src/attributes/loop_match.rs index 868c113a6d1..242e2f2c1bc 100644 --- a/compiler/rustc_attr_parsing/src/attributes/loop_match.rs +++ b/compiler/rustc_attr_parsing/src/attributes/loop_match.rs @@ -1,13 +1,15 @@ +use rustc_hir::Target; use rustc_hir::attrs::AttributeKind; use rustc_span::{Span, Symbol, sym}; use crate::attributes::{NoArgsAttributeParser, OnDuplicate}; -use crate::context::Stage; - +use crate::context::MaybeWarn::Allow; +use crate::context::{AllowedTargets, Stage}; pub(crate) struct LoopMatchParser; impl<S: Stage> NoArgsAttributeParser<S> for LoopMatchParser { const PATH: &[Symbol] = &[sym::loop_match]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Expression)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::LoopMatch; } @@ -15,5 +17,6 @@ pub(crate) struct ConstContinueParser; impl<S: Stage> NoArgsAttributeParser<S> for ConstContinueParser { const PATH: &[Symbol] = &[sym::const_continue]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Expression)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::ConstContinue; } diff --git a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs index a1166bf9ac5..c9b5dd35fa1 100644 --- a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs @@ -1,18 +1,20 @@ use rustc_errors::DiagArgValue; use rustc_feature::{AttributeTemplate, template}; +use rustc_hir::Target; use rustc_hir::attrs::{AttributeKind, MacroUseArgs}; use rustc_span::{Span, Symbol, sym}; use thin_vec::ThinVec; use crate::attributes::{AcceptMapping, AttributeParser, NoArgsAttributeParser, OnDuplicate}; -use crate::context::{AcceptContext, FinalizeContext, Stage}; +use crate::context::MaybeWarn::{Allow, Error, Warn}; +use crate::context::{AcceptContext, AllowedTargets, FinalizeContext, Stage}; use crate::parser::ArgParser; use crate::session_diagnostics; - pub(crate) struct MacroEscapeParser; impl<S: Stage> NoArgsAttributeParser<S> for MacroEscapeParser { const PATH: &[Symbol] = &[sym::macro_escape]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = MACRO_USE_ALLOWED_TARGETS; const CREATE: fn(Span) -> AttributeKind = AttributeKind::MacroEscape; } @@ -35,6 +37,12 @@ const MACRO_USE_TEMPLATE: AttributeTemplate = template!( Word, List: &["name1, name2, ..."], "https://doc.rust-lang.org/reference/macros-by-example.html#the-macro_use-attribute" ); +const MACRO_USE_ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[ + Allow(Target::Mod), + Allow(Target::ExternCrate), + Allow(Target::Crate), + Error(Target::WherePredicate), +]); impl<S: Stage> AttributeParser<S> for MacroUseParser { const ATTRIBUTES: AcceptMapping<Self, S> = &[( @@ -111,6 +119,7 @@ impl<S: Stage> AttributeParser<S> for MacroUseParser { } }, )]; + const ALLOWED_TARGETS: AllowedTargets = MACRO_USE_ALLOWED_TARGETS; fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> { Some(AttributeKind::MacroUse { span: self.first_span?, arguments: self.state }) @@ -122,5 +131,11 @@ pub(crate) struct AllowInternalUnsafeParser; impl<S: Stage> NoArgsAttributeParser<S> for AllowInternalUnsafeParser { const PATH: &[Symbol] = &[sym::allow_internal_unsafe]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Ignore; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::MacroDef), + Warn(Target::Field), + Warn(Target::Arm), + ]); const CREATE: fn(Span) -> AttributeKind = |span| AttributeKind::AllowInternalUnsafe(span); } diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index f7946ade6d2..ed5d1d92b8c 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -21,7 +21,7 @@ use rustc_hir::attrs::AttributeKind; use rustc_span::{Span, Symbol}; use thin_vec::ThinVec; -use crate::context::{AcceptContext, FinalizeContext, Stage}; +use crate::context::{AcceptContext, AllowedTargets, FinalizeContext, Stage}; use crate::parser::ArgParser; use crate::session_diagnostics::UnusedMultiple; @@ -80,6 +80,8 @@ pub(crate) trait AttributeParser<S: Stage>: Default + 'static { /// If an attribute has this symbol, the `accept` function will be called on it. const ATTRIBUTES: AcceptMapping<Self, S>; + const ALLOWED_TARGETS: AllowedTargets; + /// The parser has gotten a chance to accept the attributes on an item, /// here it can produce an attribute. /// @@ -116,6 +118,8 @@ pub(crate) trait SingleAttributeParser<S: Stage>: 'static { /// and this specified whether to, for example, warn or error on the other one. const ON_DUPLICATE: OnDuplicate<S>; + const ALLOWED_TARGETS: AllowedTargets; + /// The template this attribute parser should implement. Used for diagnostics. const TEMPLATE: AttributeTemplate; @@ -163,6 +167,7 @@ impl<T: SingleAttributeParser<S>, S: Stage> AttributeParser<S> for Single<T, S> } }, )]; + const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS; fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> { Some(self.1?.0) @@ -247,6 +252,7 @@ pub(crate) enum AttributeOrder { pub(crate) trait NoArgsAttributeParser<S: Stage>: 'static { const PATH: &[Symbol]; const ON_DUPLICATE: OnDuplicate<S>; + const ALLOWED_TARGETS: AllowedTargets; /// Create the [`AttributeKind`] given attribute's [`Span`]. const CREATE: fn(Span) -> AttributeKind; @@ -264,6 +270,7 @@ impl<T: NoArgsAttributeParser<S>, S: Stage> SingleAttributeParser<S> for Without const PATH: &[Symbol] = T::PATH; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; const ON_DUPLICATE: OnDuplicate<S> = T::ON_DUPLICATE; + const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS; const TEMPLATE: AttributeTemplate = template!(Word); fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { @@ -293,6 +300,8 @@ pub(crate) trait CombineAttributeParser<S: Stage>: 'static { /// where `x` is a vec of these individual reprs. const CONVERT: ConvertFn<Self::Item>; + const ALLOWED_TARGETS: AllowedTargets; + /// The template this attribute parser should implement. Used for diagnostics. const TEMPLATE: AttributeTemplate; @@ -324,15 +333,13 @@ impl<T: CombineAttributeParser<S>, S: Stage> Default for Combine<T, S> { } impl<T: CombineAttributeParser<S>, S: Stage> AttributeParser<S> for Combine<T, S> { - const ATTRIBUTES: AcceptMapping<Self, S> = &[( - T::PATH, - <T as CombineAttributeParser<S>>::TEMPLATE, - |group: &mut Combine<T, S>, cx, args| { + const ATTRIBUTES: AcceptMapping<Self, S> = + &[(T::PATH, T::TEMPLATE, |group: &mut Combine<T, S>, cx, args| { // Keep track of the span of the first attribute, for diagnostics group.first_span.get_or_insert(cx.attr_span); group.items.extend(T::extend(cx, args)) - }, - )]; + })]; + const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS; fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> { if let Some(first_span) = self.first_span { diff --git a/compiler/rustc_attr_parsing/src/attributes/must_use.rs b/compiler/rustc_attr_parsing/src/attributes/must_use.rs index c88bb5a69e5..b6cfc780590 100644 --- a/compiler/rustc_attr_parsing/src/attributes/must_use.rs +++ b/compiler/rustc_attr_parsing/src/attributes/must_use.rs @@ -4,16 +4,16 @@ use rustc_hir::attrs::AttributeKind; use rustc_span::{Symbol, sym}; use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser}; -use crate::context::{AcceptContext, Stage}; +use crate::context::{ALL_TARGETS, AcceptContext, AllowedTargets, Stage}; use crate::parser::ArgParser; use crate::session_diagnostics; - pub(crate) struct MustUseParser; impl<S: Stage> SingleAttributeParser<S> for MustUseParser { const PATH: &[Symbol] = &[sym::must_use]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); //FIXME Still checked fully in `check_attr.rs` const TEMPLATE: AttributeTemplate = template!( Word, NameValueStr: "reason", "https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute" diff --git a/compiler/rustc_attr_parsing/src/attributes/no_implicit_prelude.rs b/compiler/rustc_attr_parsing/src/attributes/no_implicit_prelude.rs index 40f8d00685e..589faf38f73 100644 --- a/compiler/rustc_attr_parsing/src/attributes/no_implicit_prelude.rs +++ b/compiler/rustc_attr_parsing/src/attributes/no_implicit_prelude.rs @@ -1,13 +1,16 @@ +use rustc_hir::Target; use rustc_hir::attrs::AttributeKind; use rustc_span::{Span, sym}; use crate::attributes::{NoArgsAttributeParser, OnDuplicate}; -use crate::context::Stage; - +use crate::context::MaybeWarn::Allow; +use crate::context::{AllowedTargets, Stage}; pub(crate) struct NoImplicitPreludeParser; impl<S: Stage> NoArgsAttributeParser<S> for NoImplicitPreludeParser { const PATH: &[rustc_span::Symbol] = &[sym::no_implicit_prelude]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Mod), Allow(Target::Crate)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoImplicitPrelude; } diff --git a/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs b/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs index 361ac8e959d..41e9ca4de41 100644 --- a/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs +++ b/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs @@ -1,13 +1,22 @@ +use rustc_hir::Target; use rustc_hir::attrs::AttributeKind; use rustc_span::{Span, Symbol, sym}; use crate::attributes::{NoArgsAttributeParser, OnDuplicate}; -use crate::context::Stage; - +use crate::context::MaybeWarn::{Allow, Warn}; +use crate::context::{AllowedTargets, Stage}; pub(crate) struct NonExhaustiveParser; impl<S: Stage> NoArgsAttributeParser<S> for NonExhaustiveParser { const PATH: &[Symbol] = &[sym::non_exhaustive]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Enum), + Allow(Target::Struct), + Allow(Target::Variant), + Warn(Target::Field), + Warn(Target::Arm), + Warn(Target::MacroDef), + ]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::NonExhaustive; } diff --git a/compiler/rustc_attr_parsing/src/attributes/path.rs b/compiler/rustc_attr_parsing/src/attributes/path.rs index c1c3de8cbfc..f9191d1abed 100644 --- a/compiler/rustc_attr_parsing/src/attributes/path.rs +++ b/compiler/rustc_attr_parsing/src/attributes/path.rs @@ -1,17 +1,20 @@ use rustc_feature::{AttributeTemplate, template}; +use rustc_hir::Target; use rustc_hir::attrs::AttributeKind; use rustc_span::{Symbol, sym}; use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser}; -use crate::context::{AcceptContext, Stage}; +use crate::context::MaybeWarn::{Allow, Error}; +use crate::context::{AcceptContext, AllowedTargets, Stage}; use crate::parser::ArgParser; - pub(crate) struct PathParser; impl<S: Stage> SingleAttributeParser<S> for PathParser { const PATH: &[Symbol] = &[sym::path]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError; + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Mod), Error(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!( NameValueStr: "file", "https://doc.rust-lang.org/reference/items/modules.html#the-path-attribute" diff --git a/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs index b267980914c..4624fa36287 100644 --- a/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs @@ -1,4 +1,5 @@ use rustc_feature::{AttributeTemplate, template}; +use rustc_hir::Target; use rustc_hir::attrs::AttributeKind; use rustc_span::{Span, Symbol, sym}; use thin_vec::ThinVec; @@ -6,13 +7,15 @@ use thin_vec::ThinVec; use crate::attributes::{ AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser, }; -use crate::context::{AcceptContext, Stage}; +use crate::context::MaybeWarn::{Allow, Warn}; +use crate::context::{AcceptContext, AllowedTargets, Stage}; use crate::parser::ArgParser; - pub(crate) struct ProcMacroParser; impl<S: Stage> NoArgsAttributeParser<S> for ProcMacroParser { const PATH: &[Symbol] = &[sym::proc_macro]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowList(&[Allow(Target::Fn), Warn(Target::Crate)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::ProcMacro; } @@ -20,6 +23,8 @@ pub(crate) struct ProcMacroAttributeParser; impl<S: Stage> NoArgsAttributeParser<S> for ProcMacroAttributeParser { const PATH: &[Symbol] = &[sym::proc_macro_attribute]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowList(&[Allow(Target::Fn), Warn(Target::Crate)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::ProcMacroAttribute; } @@ -28,6 +33,8 @@ impl<S: Stage> SingleAttributeParser<S> for ProcMacroDeriveParser { const PATH: &[Symbol] = &[sym::proc_macro_derive]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowList(&[Allow(Target::Fn), Warn(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!( List: &["TraitName", "TraitName, attributes(name1, name2, ...)"], "https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros" @@ -48,6 +55,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcBuiltinMacroParser { const PATH: &[Symbol] = &[sym::rustc_builtin_macro]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::MacroDef)]); const TEMPLATE: AttributeTemplate = template!(List: &["TraitName", "TraitName, attributes(name1, name2, ...)"]); diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs index 996d2af5f37..7ab58ed9347 100644 --- a/compiler/rustc_attr_parsing/src/attributes/repr.rs +++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs @@ -2,14 +2,15 @@ use rustc_abi::Align; use rustc_ast::{IntTy, LitIntType, LitKind, UintTy}; use rustc_feature::{AttributeTemplate, template}; use rustc_hir::attrs::{AttributeKind, IntType, ReprAttr}; +use rustc_hir::{MethodKind, Target}; use rustc_span::{DUMMY_SP, Span, Symbol, sym}; use super::{AcceptMapping, AttributeParser, CombineAttributeParser, ConvertFn, FinalizeContext}; -use crate::context::{AcceptContext, Stage}; +use crate::context::MaybeWarn::Allow; +use crate::context::{ALL_TARGETS, AcceptContext, AllowedTargets, Stage}; use crate::parser::{ArgParser, MetaItemListParser, MetaItemParser}; use crate::session_diagnostics; use crate::session_diagnostics::IncorrectReprFormatGenericCause; - /// Parse #[repr(...)] forms. /// /// Valid repr contents: any of the primitive integral type names (see @@ -60,6 +61,10 @@ impl<S: Stage> CombineAttributeParser<S> for ReprParser { reprs } + + //FIXME Still checked fully in `check_attr.rs` + //This one is slightly more complicated because the allowed targets depend on the arguments + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); } macro_rules! int_pat { @@ -318,6 +323,14 @@ impl AlignParser { impl<S: Stage> AttributeParser<S> for AlignParser { const ATTRIBUTES: AcceptMapping<Self, S> = &[(Self::PATH, Self::TEMPLATE, Self::parse)]; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::ForeignFn), + ]); fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> { let (align, span) = self.0?; diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 1a668b4416f..efd7b650e44 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -1,17 +1,19 @@ use rustc_feature::{AttributeTemplate, template}; +use rustc_hir::Target; use rustc_hir::attrs::AttributeKind; use rustc_span::{Symbol, sym}; use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser}; -use crate::context::{AcceptContext, Stage, parse_single_integer}; +use crate::context::MaybeWarn::Allow; +use crate::context::{AcceptContext, AllowedTargets, Stage, parse_single_integer}; use crate::parser::ArgParser; - pub(crate) struct RustcLayoutScalarValidRangeStart; impl<S: Stage> SingleAttributeParser<S> for RustcLayoutScalarValidRangeStart { const PATH: &'static [Symbol] = &[sym::rustc_layout_scalar_valid_range_start]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); const TEMPLATE: AttributeTemplate = template!(List: &["start"]); fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { @@ -26,6 +28,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcLayoutScalarValidRangeEnd { const PATH: &'static [Symbol] = &[sym::rustc_layout_scalar_valid_range_end]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); const TEMPLATE: AttributeTemplate = template!(List: &["end"]); fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { @@ -40,6 +43,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcObjectLifetimeDefaultParser { const PATH: &[rustc_span::Symbol] = &[sym::rustc_object_lifetime_default]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); const TEMPLATE: AttributeTemplate = template!(Word); fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { diff --git a/compiler/rustc_attr_parsing/src/attributes/semantics.rs b/compiler/rustc_attr_parsing/src/attributes/semantics.rs index 70a8a002099..d4ad861a3a2 100644 --- a/compiler/rustc_attr_parsing/src/attributes/semantics.rs +++ b/compiler/rustc_attr_parsing/src/attributes/semantics.rs @@ -2,11 +2,11 @@ use rustc_hir::attrs::AttributeKind; use rustc_span::{Span, Symbol, sym}; use crate::attributes::{NoArgsAttributeParser, OnDuplicate}; -use crate::context::Stage; - +use crate::context::{ALL_TARGETS, AllowedTargets, Stage}; pub(crate) struct MayDangleParser; impl<S: Stage> NoArgsAttributeParser<S> for MayDangleParser { const PATH: &[Symbol] = &[sym::may_dangle]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); //FIXME Still checked fully in `check_attr.rs` const CREATE: fn(span: Span) -> AttributeKind = AttributeKind::MayDangle; } diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index c6707f5048b..5a26178f84b 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -4,15 +4,16 @@ use rustc_errors::ErrorGuaranteed; use rustc_feature::template; use rustc_hir::attrs::AttributeKind; use rustc_hir::{ - DefaultBodyStability, PartialConstStability, Stability, StabilityLevel, StableSince, - UnstableReason, VERSION_PLACEHOLDER, + DefaultBodyStability, MethodKind, PartialConstStability, Stability, StabilityLevel, + StableSince, Target, UnstableReason, VERSION_PLACEHOLDER, }; use rustc_span::{Ident, Span, Symbol, sym}; use super::util::parse_version; use super::{AcceptMapping, AttributeParser, OnDuplicate}; use crate::attributes::NoArgsAttributeParser; -use crate::context::{AcceptContext, FinalizeContext, Stage}; +use crate::context::MaybeWarn::Allow; +use crate::context::{AcceptContext, AllowedTargets, FinalizeContext, Stage}; use crate::parser::{ArgParser, MetaItemParser}; use crate::session_diagnostics::{self, UnsupportedLiteralReason}; @@ -26,6 +27,35 @@ macro_rules! reject_outside_std { }; } +const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Struct), + Allow(Target::Enum), + Allow(Target::Union), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::Impl { of_trait: false }), + Allow(Target::Impl { of_trait: true }), + Allow(Target::MacroDef), + Allow(Target::Crate), + Allow(Target::Mod), + Allow(Target::Use), // FIXME I don't think this does anything? + Allow(Target::Const), + Allow(Target::AssocConst), + Allow(Target::AssocTy), + Allow(Target::Trait), + Allow(Target::TraitAlias), + Allow(Target::TyAlias), + Allow(Target::Variant), + Allow(Target::Field), + Allow(Target::Param), + Allow(Target::Static), + Allow(Target::ForeignFn), + Allow(Target::ForeignStatic), +]); + #[derive(Default)] pub(crate) struct StabilityParser { allowed_through_unstable_modules: Option<Symbol>, @@ -87,6 +117,7 @@ impl<S: Stage> AttributeParser<S> for StabilityParser { }, ), ]; + const ALLOWED_TARGETS: AllowedTargets = ALLOWED_TARGETS; fn finalize(mut self, cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> { if let Some(atum) = self.allowed_through_unstable_modules { @@ -142,6 +173,7 @@ impl<S: Stage> AttributeParser<S> for BodyStabilityParser { } }, )]; + const ALLOWED_TARGETS: AllowedTargets = ALLOWED_TARGETS; fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> { let (stability, span) = self.stability?; @@ -154,6 +186,10 @@ pub(crate) struct ConstStabilityIndirectParser; impl<S: Stage> NoArgsAttributeParser<S> for ConstStabilityIndirectParser { const PATH: &[Symbol] = &[sym::rustc_const_stable_indirect]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Ignore; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Method(MethodKind::Inherent)), + ]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ConstStabilityIndirect; } @@ -213,6 +249,7 @@ impl<S: Stage> AttributeParser<S> for ConstStabilityParser { this.promotable = true; }), ]; + const ALLOWED_TARGETS: AllowedTargets = ALLOWED_TARGETS; fn finalize(mut self, cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> { if self.promotable { diff --git a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs index 3267855fb0d..8b666c3868b 100644 --- a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs @@ -1,18 +1,21 @@ use rustc_feature::{AttributeTemplate, template}; +use rustc_hir::Target; use rustc_hir::attrs::AttributeKind; use rustc_hir::lints::AttributeLintKind; use rustc_span::{Symbol, sym}; use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser}; -use crate::context::{AcceptContext, Stage}; +use crate::context::MaybeWarn::{Allow, Error}; +use crate::context::{AcceptContext, AllowedTargets, Stage}; use crate::parser::ArgParser; - pub(crate) struct IgnoreParser; impl<S: Stage> SingleAttributeParser<S> for IgnoreParser { const PATH: &[Symbol] = &[sym::ignore]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Fn), Error(Target::WherePredicate)]); const TEMPLATE: AttributeTemplate = template!( Word, NameValueStr: "reason", "https://doc.rust-lang.org/reference/attributes/testing.html#the-ignore-attribute" @@ -54,6 +57,8 @@ impl<S: Stage> SingleAttributeParser<S> for ShouldPanicParser { const PATH: &[Symbol] = &[sym::should_panic]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError; + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Fn), Error(Target::WherePredicate)]); const TEMPLATE: AttributeTemplate = template!( Word, List: &[r#"expected = "reason""#], NameValueStr: "reason", "https://doc.rust-lang.org/reference/attributes/testing.html#the-should_panic-attribute" diff --git a/compiler/rustc_attr_parsing/src/attributes/traits.rs b/compiler/rustc_attr_parsing/src/attributes/traits.rs index 8514d799aa4..ee9d7ba99cd 100644 --- a/compiler/rustc_attr_parsing/src/attributes/traits.rs +++ b/compiler/rustc_attr_parsing/src/attributes/traits.rs @@ -2,19 +2,21 @@ use core::mem; use rustc_feature::{AttributeTemplate, template}; use rustc_hir::attrs::AttributeKind; +use rustc_hir::{MethodKind, Target}; use rustc_span::{Span, Symbol, sym}; use crate::attributes::{ AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser, }; -use crate::context::{AcceptContext, Stage}; +use crate::context::MaybeWarn::{Allow, Warn}; +use crate::context::{ALL_TARGETS, AcceptContext, AllowedTargets, Stage}; use crate::parser::ArgParser; - pub(crate) struct SkipDuringMethodDispatchParser; impl<S: Stage> SingleAttributeParser<S> for SkipDuringMethodDispatchParser { const PATH: &[Symbol] = &[sym::rustc_skip_during_method_dispatch]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); const TEMPLATE: AttributeTemplate = template!(List: &["array, boxed_slice"]); @@ -58,6 +60,7 @@ pub(crate) struct ParenSugarParser; impl<S: Stage> NoArgsAttributeParser<S> for ParenSugarParser { const PATH: &[Symbol] = &[sym::rustc_paren_sugar]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::ParenSugar; } @@ -65,6 +68,7 @@ pub(crate) struct TypeConstParser; impl<S: Stage> NoArgsAttributeParser<S> for TypeConstParser { const PATH: &[Symbol] = &[sym::type_const]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::AssocConst)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::TypeConst; } @@ -74,6 +78,12 @@ pub(crate) struct MarkerParser; impl<S: Stage> NoArgsAttributeParser<S> for MarkerParser { const PATH: &[Symbol] = &[sym::marker]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Trait), + Warn(Target::Field), + Warn(Target::Arm), + Warn(Target::MacroDef), + ]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::Marker; } @@ -81,6 +91,7 @@ pub(crate) struct DenyExplicitImplParser; impl<S: Stage> NoArgsAttributeParser<S> for DenyExplicitImplParser { const PATH: &[Symbol] = &[sym::rustc_deny_explicit_impl]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::DenyExplicitImpl; } @@ -88,6 +99,7 @@ pub(crate) struct DoNotImplementViaObjectParser; impl<S: Stage> NoArgsAttributeParser<S> for DoNotImplementViaObjectParser { const PATH: &[Symbol] = &[sym::rustc_do_not_implement_via_object]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::DoNotImplementViaObject; } @@ -98,6 +110,7 @@ pub(crate) struct ConstTraitParser; impl<S: Stage> NoArgsAttributeParser<S> for ConstTraitParser { const PATH: &[Symbol] = &[sym::const_trait]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::ConstTrait; } @@ -107,6 +120,7 @@ pub(crate) struct SpecializationTraitParser; impl<S: Stage> NoArgsAttributeParser<S> for SpecializationTraitParser { const PATH: &[Symbol] = &[sym::rustc_specialization_trait]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::SpecializationTrait; } @@ -114,6 +128,7 @@ pub(crate) struct UnsafeSpecializationMarkerParser; impl<S: Stage> NoArgsAttributeParser<S> for UnsafeSpecializationMarkerParser { const PATH: &[Symbol] = &[sym::rustc_unsafe_specialization_marker]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::UnsafeSpecializationMarker; } @@ -123,6 +138,7 @@ pub(crate) struct CoinductiveParser; impl<S: Stage> NoArgsAttributeParser<S> for CoinductiveParser { const PATH: &[Symbol] = &[sym::rustc_coinductive]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::Coinductive; } @@ -130,6 +146,8 @@ pub(crate) struct AllowIncoherentImplParser; impl<S: Stage> NoArgsAttributeParser<S> for AllowIncoherentImplParser { const PATH: &[Symbol] = &[sym::rustc_allow_incoherent_impl]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowList(&[Allow(Target::Method(MethodKind::Inherent))]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::AllowIncoherentImpl; } @@ -137,6 +155,7 @@ pub(crate) struct CoherenceIsCoreParser; impl<S: Stage> NoArgsAttributeParser<S> for CoherenceIsCoreParser { const PATH: &[Symbol] = &[sym::rustc_coherence_is_core]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::CoherenceIsCore; } @@ -144,6 +163,8 @@ pub(crate) struct FundamentalParser; impl<S: Stage> NoArgsAttributeParser<S> for FundamentalParser { const PATH: &[Symbol] = &[sym::fundamental]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowList(&[Allow(Target::Struct), Allow(Target::Trait)]); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::Fundamental; } @@ -151,5 +172,6 @@ pub(crate) struct PointeeParser; impl<S: Stage> NoArgsAttributeParser<S> for PointeeParser { const PATH: &[Symbol] = &[sym::pointee]; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); //FIXME Still checked fully in `check_attr.rs` const CREATE: fn(Span) -> AttributeKind = AttributeKind::Pointee; } diff --git a/compiler/rustc_attr_parsing/src/attributes/transparency.rs b/compiler/rustc_attr_parsing/src/attributes/transparency.rs index d4d68eb8b27..0ffcf434b52 100644 --- a/compiler/rustc_attr_parsing/src/attributes/transparency.rs +++ b/compiler/rustc_attr_parsing/src/attributes/transparency.rs @@ -1,12 +1,13 @@ use rustc_feature::{AttributeTemplate, template}; +use rustc_hir::Target; use rustc_hir::attrs::AttributeKind; use rustc_span::hygiene::Transparency; use rustc_span::{Symbol, sym}; use super::{AttributeOrder, OnDuplicate, SingleAttributeParser}; -use crate::context::{AcceptContext, Stage}; +use crate::context::MaybeWarn::Allow; +use crate::context::{AcceptContext, AllowedTargets, Stage}; use crate::parser::ArgParser; - pub(crate) struct TransparencyParser; // FIXME(jdonszelmann): make these proper diagnostics @@ -18,6 +19,7 @@ impl<S: Stage> SingleAttributeParser<S> for TransparencyParser { const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Custom(|cx, used, unused| { cx.dcx().span_err(vec![used, unused], "multiple macro transparency attributes"); }); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::MacroDef)]); const TEMPLATE: AttributeTemplate = template!(NameValueStr: ["transparent", "semitransparent", "opaque"]); diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 1420753a44e..bebe3350c4e 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -3,13 +3,16 @@ use std::collections::BTreeMap; use std::ops::{Deref, DerefMut}; use std::sync::LazyLock; +use itertools::Itertools; use private::Sealed; use rustc_ast::{self as ast, LitKind, MetaItemLit, NodeId}; use rustc_errors::{DiagCtxtHandle, Diagnostic}; use rustc_feature::{AttributeTemplate, Features}; use rustc_hir::attrs::AttributeKind; use rustc_hir::lints::{AttributeLint, AttributeLintKind}; -use rustc_hir::{AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId, HirId}; +use rustc_hir::{ + AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId, HirId, MethodKind, Target, +}; use rustc_session::Session; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym}; @@ -27,7 +30,7 @@ use crate::attributes::dummy::DummyParser; use crate::attributes::inline::{InlineParser, RustcForceInlineParser}; use crate::attributes::link_attrs::{ ExportStableParser, FfiConstParser, FfiPureParser, LinkNameParser, LinkOrdinalParser, - LinkSectionParser, StdInternalSymbolParser, + LinkSectionParser, LinkageParser, StdInternalSymbolParser, }; use crate::attributes::lint_helpers::{ AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser, @@ -61,8 +64,11 @@ use crate::attributes::traits::{ }; use crate::attributes::transparency::TransparencyParser; use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs}; +use crate::context::MaybeWarn::{Allow, Error, Warn}; use crate::parser::{ArgParser, MetaItemParser, PathParser}; -use crate::session_diagnostics::{AttributeParseError, AttributeParseErrorReason, UnknownMetaItem}; +use crate::session_diagnostics::{ + AttributeParseError, AttributeParseErrorReason, InvalidTarget, UnknownMetaItem, +}; type GroupType<S> = LazyLock<GroupTypeInner<S>>; @@ -74,6 +80,7 @@ struct GroupTypeInner<S: Stage> { struct GroupTypeInnerAccept<S: Stage> { template: AttributeTemplate, accept_fn: AcceptFn<S>, + allowed_targets: AllowedTargets, } type AcceptFn<S> = @@ -121,7 +128,8 @@ macro_rules! attribute_parsers { STATE_OBJECT.with_borrow_mut(|s| { accept_fn(s, cx, args) }) - }) + }), + allowed_targets: <$names as crate::attributes::AttributeParser<$stage>>::ALLOWED_TARGETS, }); } @@ -167,6 +175,7 @@ attribute_parsers!( Single<LinkNameParser>, Single<LinkOrdinalParser>, Single<LinkSectionParser>, + Single<LinkageParser>, Single<MustUseParser>, Single<OptimizeParser>, Single<PathAttributeParser>, @@ -642,6 +651,64 @@ impl ShouldEmit { } } +#[derive(Debug)] +pub(crate) enum AllowedTargets { + AllowList(&'static [MaybeWarn]), + AllowListWarnRest(&'static [MaybeWarn]), +} + +pub(crate) enum AllowedResult { + Allowed, + Warn, + Error, +} + +impl AllowedTargets { + pub(crate) fn is_allowed(&self, target: Target) -> AllowedResult { + match self { + AllowedTargets::AllowList(list) => { + if list.contains(&Allow(target)) { + AllowedResult::Allowed + } else if list.contains(&Warn(target)) { + AllowedResult::Warn + } else { + AllowedResult::Error + } + } + AllowedTargets::AllowListWarnRest(list) => { + if list.contains(&Allow(target)) { + AllowedResult::Allowed + } else if list.contains(&Error(target)) { + AllowedResult::Error + } else { + AllowedResult::Warn + } + } + } + } + + pub(crate) fn allowed_targets(&self) -> Vec<Target> { + match self { + AllowedTargets::AllowList(list) => list, + AllowedTargets::AllowListWarnRest(list) => list, + } + .iter() + .filter_map(|target| match target { + Allow(target) => Some(*target), + Warn(_) => None, + Error(_) => None, + }) + .collect() + } +} + +#[derive(Debug, Eq, PartialEq)] +pub(crate) enum MaybeWarn { + Allow(Target), + Warn(Target), + Error(Target), +} + /// Context created once, for example as part of the ast lowering /// context, through which all attributes can be lowered. pub struct AttributeParser<'sess, S: Stage = Late> { @@ -690,6 +757,7 @@ impl<'sess> AttributeParser<'sess, Early> { attrs, target_span, target_node_id, + Target::Crate, // Does not matter, we're not going to emit errors anyways OmitDoc::Skip, std::convert::identity, |_lint| { @@ -776,6 +844,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { attrs: &[ast::Attribute], target_span: Span, target_id: S::Id, + target: Target, omit_doc: OmitDoc, lower_span: impl Copy + Fn(Span) -> Span, @@ -847,7 +916,48 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { attr_path: path.get_attribute_path(), }; - (accept.accept_fn)(&mut cx, args) + (accept.accept_fn)(&mut cx, args); + + if self.stage.should_emit().should_emit() { + match accept.allowed_targets.is_allowed(target) { + AllowedResult::Allowed => {} + AllowedResult::Warn => { + let allowed_targets = + accept.allowed_targets.allowed_targets(); + let (applied, only) = allowed_targets_applied( + allowed_targets, + target, + self.features, + ); + emit_lint(AttributeLint { + id: target_id, + span: attr.span, + kind: AttributeLintKind::InvalidTarget { + name: parts[0], + target, + only: if only { "only " } else { "" }, + applied, + }, + }); + } + AllowedResult::Error => { + let allowed_targets = + accept.allowed_targets.allowed_targets(); + let (applied, only) = allowed_targets_applied( + allowed_targets, + target, + self.features, + ); + self.dcx().emit_err(InvalidTarget { + span: attr.span, + name: parts[0], + target: target.plural_name(), + only: if only { "only " } else { "" }, + applied, + }); + } + } + } } } else { // If we're here, we must be compiling a tool attribute... Or someone @@ -935,6 +1045,132 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { } } +/// Takes a list of `allowed_targets` for an attribute, and the `target` the attribute was applied to. +/// Does some heuristic-based filtering to remove uninteresting targets, and formats the targets into a string +pub(crate) fn allowed_targets_applied( + mut allowed_targets: Vec<Target>, + target: Target, + features: Option<&Features>, +) -> (String, bool) { + // Remove unstable targets from `allowed_targets` if their features are not enabled + if let Some(features) = features { + if !features.fn_delegation() { + allowed_targets.retain(|t| !matches!(t, Target::Delegation { .. })); + } + if !features.stmt_expr_attributes() { + allowed_targets.retain(|t| !matches!(t, Target::Expression | Target::Statement)); + } + } + + // We define groups of "similar" targets. + // If at least two of the targets are allowed, and the `target` is not in the group, + // we collapse the entire group to a single entry to simplify the target list + const FUNCTION_LIKE: &[Target] = &[ + Target::Fn, + Target::Closure, + Target::ForeignFn, + Target::Method(MethodKind::Inherent), + Target::Method(MethodKind::Trait { body: false }), + Target::Method(MethodKind::Trait { body: true }), + Target::Method(MethodKind::TraitImpl), + ]; + const METHOD_LIKE: &[Target] = &[ + Target::Method(MethodKind::Inherent), + Target::Method(MethodKind::Trait { body: false }), + Target::Method(MethodKind::Trait { body: true }), + Target::Method(MethodKind::TraitImpl), + ]; + const IMPL_LIKE: &[Target] = + &[Target::Impl { of_trait: false }, Target::Impl { of_trait: true }]; + const ADT_LIKE: &[Target] = &[Target::Struct, Target::Enum]; + + let mut added_fake_targets = Vec::new(); + filter_targets( + &mut allowed_targets, + FUNCTION_LIKE, + "functions", + target, + &mut added_fake_targets, + ); + filter_targets(&mut allowed_targets, METHOD_LIKE, "methods", target, &mut added_fake_targets); + filter_targets(&mut allowed_targets, IMPL_LIKE, "impl blocks", target, &mut added_fake_targets); + filter_targets(&mut allowed_targets, ADT_LIKE, "data types", target, &mut added_fake_targets); + + // If there is now only 1 target left, show that as the only possible target + ( + added_fake_targets + .iter() + .copied() + .chain(allowed_targets.iter().map(|t| t.plural_name())) + .join(", "), + allowed_targets.len() + added_fake_targets.len() == 1, + ) +} + +fn filter_targets( + allowed_targets: &mut Vec<Target>, + target_group: &'static [Target], + target_group_name: &'static str, + target: Target, + added_fake_targets: &mut Vec<&'static str>, +) { + if target_group.contains(&target) { + return; + } + if allowed_targets.iter().filter(|at| target_group.contains(at)).count() < 2 { + return; + } + allowed_targets.retain(|t| !target_group.contains(t)); + added_fake_targets.push(target_group_name); +} + +/// This is the list of all targets to which a attribute can be applied +/// This is used for: +/// - `rustc_dummy`, which can be applied to all targets +/// - Attributes that are not parted to the new target system yet can use this list as a placeholder +pub(crate) const ALL_TARGETS: &'static [MaybeWarn] = &[ + Allow(Target::ExternCrate), + Allow(Target::Use), + Allow(Target::Static), + Allow(Target::Const), + Allow(Target::Fn), + Allow(Target::Closure), + Allow(Target::Mod), + Allow(Target::ForeignMod), + Allow(Target::GlobalAsm), + Allow(Target::TyAlias), + Allow(Target::Enum), + Allow(Target::Variant), + Allow(Target::Struct), + Allow(Target::Field), + Allow(Target::Union), + Allow(Target::Trait), + Allow(Target::TraitAlias), + Allow(Target::Impl { of_trait: false }), + Allow(Target::Impl { of_trait: true }), + Allow(Target::Expression), + Allow(Target::Statement), + Allow(Target::Arm), + Allow(Target::AssocConst), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::AssocTy), + Allow(Target::ForeignFn), + Allow(Target::ForeignStatic), + Allow(Target::ForeignTy), + Allow(Target::MacroDef), + Allow(Target::Param), + Allow(Target::PatField), + Allow(Target::ExprField), + Allow(Target::WherePredicate), + Allow(Target::MacroCall), + Allow(Target::Crate), + Allow(Target::Delegation { mac: false }), + Allow(Target::Delegation { mac: true }), +]; + /// Parse a single integer. /// /// Used by attributes that take a single integer as argument, such as diff --git a/compiler/rustc_attr_parsing/src/lints.rs b/compiler/rustc_attr_parsing/src/lints.rs index 22f5531bc80..733225bab59 100644 --- a/compiler/rustc_attr_parsing/src/lints.rs +++ b/compiler/rustc_attr_parsing/src/lints.rs @@ -1,6 +1,7 @@ use rustc_errors::{DiagArgValue, LintEmitter}; -use rustc_hir::HirId; use rustc_hir::lints::{AttributeLint, AttributeLintKind}; +use rustc_hir::{HirId, Target}; +use rustc_span::sym; use crate::session_diagnostics; @@ -34,5 +35,25 @@ pub fn emit_attribute_lint<L: LintEmitter>(lint: &AttributeLint<HirId>, lint_emi *first_span, session_diagnostics::EmptyAttributeList { attr_span: *first_span }, ), + &AttributeLintKind::InvalidTarget { name, target, ref applied, only } => lint_emitter + .emit_node_span_lint( + // This check is here because `deprecated` had its own lint group and removing this would be a breaking change + if name == sym::deprecated + && ![Target::Closure, Target::Expression, Target::Statement, Target::Arm] + .contains(&target) + { + rustc_session::lint::builtin::USELESS_DEPRECATED + } else { + rustc_session::lint::builtin::UNUSED_ATTRIBUTES + }, + *id, + *span, + session_diagnostics::InvalidTargetLint { + name, + target: target.plural_name(), + applied: applied.clone(), + only, + }, + ), } } diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 41179844152..95e85667cd6 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -480,6 +480,29 @@ pub(crate) struct EmptyAttributeList { pub attr_span: Span, } +#[derive(LintDiagnostic)] +#[diag(attr_parsing_invalid_target_lint)] +#[warning] +#[help] +pub(crate) struct InvalidTargetLint { + pub name: Symbol, + pub target: &'static str, + pub applied: String, + pub only: &'static str, +} + +#[derive(Diagnostic)] +#[help] +#[diag(attr_parsing_invalid_target)] +pub(crate) struct InvalidTarget { + #[primary_span] + pub span: Span, + pub name: Symbol, + pub target: &'static str, + pub applied: String, + pub only: &'static str, +} + #[derive(Diagnostic)] #[diag(attr_parsing_invalid_alignment_value, code = E0589)] pub(crate) struct InvalidAlignmentValue { diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index af71db69483..0b3151fd8b8 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -518,7 +518,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { .with_span_help( self.get_closure_bound_clause_span(*def_id), "`Fn` and `FnMut` closures require captured values to be able to be \ - consumed multiple times, but an `FnOnce` consume them only once", + consumed multiple times, but `FnOnce` closures may consume them only once", ) } _ => { diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 5d9416b59fc..c0ca35f9ff8 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -677,12 +677,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { /// - is the trait from the local crate? If not, we can't suggest changing signatures /// - `Span` of the argument in the trait definition fn is_error_in_trait(&self, local: Local) -> (bool, bool, Option<Span>) { + let tcx = self.infcx.tcx; if self.body.local_kind(local) != LocalKind::Arg { return (false, false, None); } let my_def = self.body.source.def_id(); let Some(td) = - self.infcx.tcx.impl_of_assoc(my_def).and_then(|x| self.infcx.tcx.trait_id_of_impl(x)) + tcx.trait_impl_of_assoc(my_def).and_then(|id| self.infcx.tcx.trait_id_of_impl(id)) else { return (false, false, None); }; diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index c3aa205d5aa..a960b96b91c 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1773,10 +1773,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { locations, ); - assert!(!matches!( - tcx.impl_of_assoc(def_id).map(|imp| tcx.def_kind(imp)), - Some(DefKind::Impl { of_trait: true }) - )); + assert_eq!(tcx.trait_impl_of_assoc(def_id), None); self.prove_predicates( args.types().map(|ty| ty::ClauseKind::WellFormed(ty.into())), locations, diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl index ae186d744c4..eb3c40cc593 100644 --- a/compiler/rustc_builtin_macros/messages.ftl +++ b/compiler/rustc_builtin_macros/messages.ftl @@ -259,8 +259,6 @@ builtin_macros_only_one_argument = {$name} takes 1 argument builtin_macros_proc_macro = `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]` -builtin_macros_proc_macro_attribute_only_be_used_on_bare_functions = the `#[{$path}]` attribute may only be used on bare functions - builtin_macros_proc_macro_attribute_only_usable_with_crate_type = the `#[{$path}]` attribute is only usable with crates of the `proc-macro` crate type builtin_macros_requires_cfg_pattern = diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 6bcf4d3e0a2..bb520db75b9 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -906,14 +906,6 @@ pub(crate) struct TakesNoArguments<'a> { } #[derive(Diagnostic)] -#[diag(builtin_macros_proc_macro_attribute_only_be_used_on_bare_functions)] -pub(crate) struct AttributeOnlyBeUsedOnBareFunctions<'a> { - #[primary_span] - pub span: Span, - pub path: &'a str, -} - -#[derive(Diagnostic)] #[diag(builtin_macros_proc_macro_attribute_only_usable_with_crate_type)] pub(crate) struct AttributeOnlyUsableWithCrateType<'a> { #[primary_span] diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs index f440adf6cf0..6ac3e17503d 100644 --- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs +++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs @@ -231,12 +231,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { let fn_ident = if let ast::ItemKind::Fn(fn_) = &item.kind { fn_.ident } else { - self.dcx - .create_err(errors::AttributeOnlyBeUsedOnBareFunctions { - span: attr.span, - path: &pprust::path_to_string(&attr.get_normal_item().path), - }) - .emit(); + // Error handled by general target checking logic return; }; diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index bec546badc9..a56466750e7 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -281,8 +281,8 @@ fn data_id_for_static( .abi .bytes(); - let linkage = if import_linkage == rustc_middle::mir::mono::Linkage::ExternalWeak - || import_linkage == rustc_middle::mir::mono::Linkage::WeakAny + let linkage = if import_linkage == rustc_hir::attrs::Linkage::ExternalWeak + || import_linkage == rustc_hir::attrs::Linkage::WeakAny { Linkage::Preemptible } else { @@ -332,8 +332,8 @@ fn data_id_for_static( let linkage = if definition { crate::linkage::get_static_linkage(tcx, def_id) - } else if attrs.linkage == Some(rustc_middle::mir::mono::Linkage::ExternalWeak) - || attrs.linkage == Some(rustc_middle::mir::mono::Linkage::WeakAny) + } else if attrs.linkage == Some(rustc_hir::attrs::Linkage::ExternalWeak) + || attrs.linkage == Some(rustc_hir::attrs::Linkage::WeakAny) { Linkage::Preemptible } else { diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index 8ec3599b63d..7e77781dc2f 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -18,12 +18,11 @@ use rustc_codegen_ssa::{ use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{IntoDynSyncSend, par_map}; +use rustc_hir::attrs::Linkage as RLinkage; use rustc_metadata::fs::copy_to_stdout; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use rustc_middle::mir::mono::{ - CodegenUnit, Linkage as RLinkage, MonoItem, MonoItemData, Visibility, -}; +use rustc_middle::mir::mono::{CodegenUnit, MonoItem, MonoItemData, Visibility}; use rustc_session::Session; use rustc_session::config::{DebugInfo, OutFileName, OutputFilenames, OutputType}; diff --git a/compiler/rustc_codegen_cranelift/src/linkage.rs b/compiler/rustc_codegen_cranelift/src/linkage.rs index ca853aac158..d76ab9d0109 100644 --- a/compiler/rustc_codegen_cranelift/src/linkage.rs +++ b/compiler/rustc_codegen_cranelift/src/linkage.rs @@ -1,4 +1,5 @@ -use rustc_middle::mir::mono::{Linkage as RLinkage, MonoItem, Visibility}; +use rustc_hir::attrs::Linkage as RLinkage; +use rustc_middle::mir::mono::{MonoItem, Visibility}; use crate::prelude::*; diff --git a/compiler/rustc_codegen_gcc/src/base.rs b/compiler/rustc_codegen_gcc/src/base.rs index c105916bbb2..e9d72e457a0 100644 --- a/compiler/rustc_codegen_gcc/src/base.rs +++ b/compiler/rustc_codegen_gcc/src/base.rs @@ -8,8 +8,8 @@ use rustc_codegen_ssa::ModuleCodegen; use rustc_codegen_ssa::base::maybe_create_entry_wrapper; use rustc_codegen_ssa::mono_item::MonoItemExt; use rustc_codegen_ssa::traits::DebugInfoCodegenMethods; +use rustc_hir::attrs::Linkage; use rustc_middle::dep_graph; -use rustc_middle::mir::mono::Linkage; #[cfg(feature = "master")] use rustc_middle::mir::mono::Visibility; use rustc_middle::ty::TyCtxt; diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs index 873f1f1951c..619277eba8b 100644 --- a/compiler/rustc_codegen_gcc/src/consts.rs +++ b/compiler/rustc_codegen_gcc/src/consts.rs @@ -5,13 +5,13 @@ use rustc_abi::{self as abi, Align, HasDataLayout, Primitive, Size, WrappingRang use rustc_codegen_ssa::traits::{ BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods, }; +use rustc_hir::attrs::Linkage; use rustc_hir::def::DefKind; use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::mir::interpret::{ self, ConstAllocation, ErrorHandled, Scalar as InterpScalar, read_target_uint, }; -use rustc_middle::mir::mono::Linkage; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Instance}; use rustc_middle::{bug, span_bug}; diff --git a/compiler/rustc_codegen_gcc/src/mono_item.rs b/compiler/rustc_codegen_gcc/src/mono_item.rs index ff188c437da..35d44d21bcb 100644 --- a/compiler/rustc_codegen_gcc/src/mono_item.rs +++ b/compiler/rustc_codegen_gcc/src/mono_item.rs @@ -1,11 +1,12 @@ #[cfg(feature = "master")] use gccjit::{FnAttribute, VarAttribute}; use rustc_codegen_ssa::traits::PreDefineCodegenMethods; +use rustc_hir::attrs::Linkage; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use rustc_middle::mir::mono::{Linkage, Visibility}; +use rustc_middle::mir::mono::Visibility; use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv, LayoutOf}; use rustc_middle::ty::{self, Instance, TypeVisitableExt}; diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index 009e7e2487b..043123fcab2 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -24,6 +24,7 @@ use crate::attributes::{self, llfn_attrs_from_instance}; use crate::builder::Builder; use crate::context::CodegenCx; use crate::llvm::{self, Attribute, AttributePlace}; +use crate::llvm_util; use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::value::Value; @@ -500,7 +501,16 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { } } PassMode::Indirect { attrs, meta_attrs: None, on_stack: false } => { - apply(attrs); + let i = apply(attrs); + if cx.sess().opts.optimize != config::OptLevel::No + && llvm_util::get_version() >= (21, 0, 0) + { + attributes::apply_to_llfn( + llfn, + llvm::AttributePlace::Argument(i), + &[llvm::AttributeKind::DeadOnReturn.create_attr(cx.llcx)], + ); + } } PassMode::Indirect { attrs, meta_attrs: Some(meta_attrs), on_stack } => { assert!(!on_stack); diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs index 5dda836988c..9cc5d8dbc21 100644 --- a/compiler/rustc_codegen_llvm/src/base.rs +++ b/compiler/rustc_codegen_llvm/src/base.rs @@ -18,9 +18,10 @@ use rustc_codegen_ssa::base::maybe_create_entry_wrapper; use rustc_codegen_ssa::mono_item::MonoItemExt; use rustc_codegen_ssa::traits::*; use rustc_data_structures::small_c_str::SmallCStr; +use rustc_hir::attrs::Linkage; use rustc_middle::dep_graph; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; -use rustc_middle::mir::mono::{Linkage, Visibility}; +use rustc_middle::mir::mono::Visibility; use rustc_middle::ty::TyCtxt; use rustc_session::config::DebugInfo; use rustc_span::Symbol; diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 6b06daf3477..9ec7b0f80ae 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -4,6 +4,7 @@ use rustc_abi::{Align, HasDataLayout, Primitive, Scalar, Size, WrappingRange}; use rustc_codegen_ssa::common; use rustc_codegen_ssa::traits::*; use rustc_hir::LangItem; +use rustc_hir::attrs::Linkage; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; @@ -11,7 +12,7 @@ use rustc_middle::mir::interpret::{ Allocation, ConstAllocation, ErrorHandled, InitChunk, Pointer, Scalar as InterpScalar, read_target_uint, }; -use rustc_middle::mir::mono::{Linkage, MonoItem}; +use rustc_middle::mir::mono::MonoItem; use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf}; use rustc_middle::ty::{self, Instance}; use rustc_middle::{bug, span_bug}; diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index ee77774c688..27ae729a531 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -213,6 +213,12 @@ pub(crate) unsafe fn create_module<'ll>( target_data_layout = target_data_layout.replace("p8:128:128:128:48", "p8:128:128") } } + if llvm_version < (22, 0, 0) { + if sess.target.arch == "avr" { + // LLVM 22.0 updated the default layout on avr: https://github.com/llvm/llvm-project/pull/153010 + target_data_layout = target_data_layout.replace("n8:16", "n8") + } + } // Ensure the data-layout values hardcoded remain the defaults. { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 6cbf2dbf7d3..2c3a84499ac 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -533,31 +533,26 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { // First, let's see if this is a method within an inherent impl. Because // if yes, we want to make the result subroutine DIE a child of the // subroutine's self-type. - if let Some(impl_def_id) = cx.tcx.impl_of_assoc(instance.def_id()) { - // If the method does *not* belong to a trait, proceed - if cx.tcx.trait_id_of_impl(impl_def_id).is_none() { - let impl_self_ty = cx.tcx.instantiate_and_normalize_erasing_regions( - instance.args, - cx.typing_env(), - cx.tcx.type_of(impl_def_id), - ); - - // Only "class" methods are generally understood by LLVM, - // so avoid methods on other types (e.g., `<*mut T>::null`). - if let ty::Adt(def, ..) = impl_self_ty.kind() - && !def.is_box() - { - // Again, only create type information if full debuginfo is enabled - if cx.sess().opts.debuginfo == DebugInfo::Full && !impl_self_ty.has_param() - { - return (type_di_node(cx, impl_self_ty), true); - } else { - return (namespace::item_namespace(cx, def.did()), false); - } + // For trait method impls we still use the "parallel namespace" + // strategy + if let Some(imp_def_id) = cx.tcx.inherent_impl_of_assoc(instance.def_id()) { + let impl_self_ty = cx.tcx.instantiate_and_normalize_erasing_regions( + instance.args, + cx.typing_env(), + cx.tcx.type_of(imp_def_id), + ); + + // Only "class" methods are generally understood by LLVM, + // so avoid methods on other types (e.g., `<*mut T>::null`). + if let ty::Adt(def, ..) = impl_self_ty.kind() + && !def.is_box() + { + // Again, only create type information if full debuginfo is enabled + if cx.sess().opts.debuginfo == DebugInfo::Full && !impl_self_ty.has_param() { + return (type_di_node(cx, impl_self_ty), true); + } else { + return (namespace::item_namespace(cx, def.did()), false); } - } else { - // For trait method impls we still use the "parallel namespace" - // strategy } } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 75d3d27f74e..ad3c3d5932e 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -249,6 +249,7 @@ pub(crate) enum AttributeKind { FnRetThunkExtern = 41, Writable = 42, DeadOnUnwind = 43, + DeadOnReturn = 44, } /// LLVMIntPredicate diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index f9edaded60d..5075befae8a 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -1,8 +1,9 @@ use rustc_codegen_ssa::traits::*; +use rustc_hir::attrs::Linkage; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_middle::bug; -use rustc_middle::mir::mono::{Linkage, Visibility}; +use rustc_middle::mir::mono::Visibility; use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv, LayoutOf}; use rustc_middle::ty::{self, Instance, TypeVisitableExt}; use rustc_session::config::CrateType; diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 0494666bda9..77096822fdc 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -306,7 +306,8 @@ fn exported_generic_symbols_provider_local<'tcx>( let mut symbols: Vec<_> = vec![]; if tcx.local_crate_exports_generics() { - use rustc_middle::mir::mono::{Linkage, MonoItem, Visibility}; + use rustc_hir::attrs::Linkage; + use rustc_middle::mir::mono::{MonoItem, Visibility}; use rustc_middle::ty::InstanceKind; // Normally, we require that shared monomorphizations are not hidden, diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 287787eb3d1..7fa37198387 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -6,12 +6,10 @@ use rustc_ast::{LitKind, MetaItem, MetaItemInner, attr}; use rustc_hir::attrs::{AttributeKind, InlineAttr, InstructionSetAttr, UsedBy}; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; -use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS; use rustc_hir::{self as hir, Attribute, LangItem, find_attr, lang_items}; use rustc_middle::middle::codegen_fn_attrs::{ CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, }; -use rustc_middle::mir::mono::Linkage; use rustc_middle::query::Providers; use rustc_middle::span_bug; use rustc_middle::ty::{self as ty, TyCtxt}; @@ -26,31 +24,6 @@ use crate::target_features::{ check_target_feature_trait_unsafe, check_tied_features, from_target_feature_attr, }; -fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage { - use rustc_middle::mir::mono::Linkage::*; - - // Use the names from src/llvm/docs/LangRef.rst here. Most types are only - // applicable to variable declarations and may not really make sense for - // Rust code in the first place but allow them anyway and trust that the - // user knows what they're doing. Who knows, unanticipated use cases may pop - // up in the future. - // - // ghost, dllimport, dllexport and linkonce_odr_autohide are not supported - // and don't have to be, LLVM treats them as no-ops. - match name { - "available_externally" => AvailableExternally, - "common" => Common, - "extern_weak" => ExternalWeak, - "external" => External, - "internal" => Internal, - "linkonce" => LinkOnceAny, - "linkonce_odr" => LinkOnceODR, - "weak" => WeakAny, - "weak_odr" => WeakODR, - _ => tcx.dcx().span_fatal(tcx.def_span(def_id), "invalid linkage specified"), - } -} - /// In some cases, attributes are only valid on functions, but it's the `check_attr` /// pass that checks that they aren't used anywhere else, rather than this module. /// In these cases, we bail from performing further checks that are only meaningful for @@ -103,13 +76,6 @@ fn parse_instruction_set_attr(tcx: TyCtxt<'_>, attr: &Attribute) -> Option<Instr } } -// FIXME(jdonszelmann): remove when linkage becomes a parsed attr -fn parse_linkage_attr(tcx: TyCtxt<'_>, did: LocalDefId, attr: &Attribute) -> Option<Linkage> { - let val = attr.value_str()?; - let linkage = linkage_by_name(tcx, did, val.as_str()); - Some(linkage) -} - // FIXME(jdonszelmann): remove when no_sanitize becomes a parsed attr fn parse_no_sanitize_attr(tcx: TyCtxt<'_>, attr: &Attribute) -> Option<SanitizerSet> { let list = attr.meta_item_list()?; @@ -332,6 +298,28 @@ fn process_builtin_attrs( AttributeKind::StdInternalSymbol(_) => { codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL } + AttributeKind::Linkage(linkage, _) => { + let linkage = Some(*linkage); + + if tcx.is_foreign_item(did) { + codegen_fn_attrs.import_linkage = linkage; + + if tcx.is_mutable_static(did.into()) { + let mut diag = tcx.dcx().struct_span_err( + attr.span(), + "extern mutable statics are not allowed with `#[linkage]`", + ); + diag.note( + "marking the extern static mutable would allow changing which \ + symbol the static references rather than make the target of the \ + symbol mutable", + ); + diag.emit(); + } + } else { + codegen_fn_attrs.linkage = linkage; + } + } _ => {} } } @@ -349,28 +337,6 @@ fn process_builtin_attrs( codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED } sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL, - sym::linkage => { - let linkage = parse_linkage_attr(tcx, did, attr); - - if tcx.is_foreign_item(did) { - codegen_fn_attrs.import_linkage = linkage; - - if tcx.is_mutable_static(did.into()) { - let mut diag = tcx.dcx().struct_span_err( - attr.span(), - "extern mutable statics are not allowed with `#[linkage]`", - ); - diag.note( - "marking the extern static mutable would allow changing which \ - symbol the static references rather than make the target of the \ - symbol mutable", - ); - diag.emit(); - } - } else { - codegen_fn_attrs.linkage = linkage; - } - } sym::no_sanitize => { interesting_spans.no_sanitize = Some(attr.span()); codegen_fn_attrs.no_sanitize |= @@ -553,14 +519,12 @@ fn handle_lang_items( // strippable by the linker. // // Additionally weak lang items have predetermined symbol names. - if let Some(lang_item) = lang_item { - if WEAK_LANG_ITEMS.contains(&lang_item) { - codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL; - } - if let Some(link_name) = lang_item.link_name() { - codegen_fn_attrs.export_name = Some(link_name); - codegen_fn_attrs.link_name = Some(link_name); - } + if let Some(lang_item) = lang_item + && let Some(link_name) = lang_item.link_name() + { + codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL; + codegen_fn_attrs.export_name = Some(link_name); + codegen_fn_attrs.link_name = Some(link_name); } // error when using no_mangle on a lang item item diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs index 2a9b5c9019b..31784cabf4a 100644 --- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs +++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs @@ -1,6 +1,6 @@ use rustc_abi::{BackendRepr, Float, Integer, Primitive, RegKind}; -use rustc_hir::attrs::InstructionSetAttr; -use rustc_middle::mir::mono::{Linkage, MonoItemData, Visibility}; +use rustc_hir::attrs::{InstructionSetAttr, Linkage}; +use rustc_middle::mir::mono::{MonoItemData, Visibility}; use rustc_middle::mir::{InlineAsmOperand, START_BLOCK}; use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout}; use rustc_middle::ty::{Instance, Ty, TyCtxt, TypeVisitableExt}; diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs index b9040c330fb..8f03dc1e6b5 100644 --- a/compiler/rustc_codegen_ssa/src/mono_item.rs +++ b/compiler/rustc_codegen_ssa/src/mono_item.rs @@ -1,5 +1,6 @@ +use rustc_hir::attrs::Linkage; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use rustc_middle::mir::mono::{Linkage, MonoItem, MonoItemData, Visibility}; +use rustc_middle::mir::mono::{MonoItem, MonoItemData, Visibility}; use rustc_middle::ty::layout::HasTyCtxt; use tracing::debug; diff --git a/compiler/rustc_codegen_ssa/src/traits/declare.rs b/compiler/rustc_codegen_ssa/src/traits/declare.rs index 9f735546558..8d5f0a5b939 100644 --- a/compiler/rustc_codegen_ssa/src/traits/declare.rs +++ b/compiler/rustc_codegen_ssa/src/traits/declare.rs @@ -1,5 +1,6 @@ +use rustc_hir::attrs::Linkage; use rustc_hir::def_id::DefId; -use rustc_middle::mir::mono::{Linkage, Visibility}; +use rustc_middle::mir::mono::Visibility; use rustc_middle::ty::Instance; pub trait PreDefineCodegenMethods<'tcx> { diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index b1cc0cc2878..64cb934ac8d 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -731,18 +731,21 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ) { let tcx = *self.tcx; - let trait_def_id = tcx.trait_of_assoc(def_id).unwrap(); + let trait_def_id = tcx.parent(def_id); let virtual_trait_ref = ty::TraitRef::from_assoc(tcx, trait_def_id, virtual_instance.args); let existential_trait_ref = ty::ExistentialTraitRef::erase_self_ty(tcx, virtual_trait_ref); let concrete_trait_ref = existential_trait_ref.with_self_ty(tcx, dyn_ty); - let concrete_method = Instance::expect_resolve_for_vtable( - tcx, - self.typing_env, - def_id, - virtual_instance.args.rebase_onto(tcx, trait_def_id, concrete_trait_ref.args), - self.cur_span(), - ); + let concrete_method = { + let _trace = enter_trace_span!(M, resolve::expect_resolve_for_vtable, ?def_id); + Instance::expect_resolve_for_vtable( + tcx, + self.typing_env, + def_id, + virtual_instance.args.rebase_onto(tcx, trait_def_id, concrete_trait_ref.args), + self.cur_span(), + ) + }; assert_eq!(concrete_instance, concrete_method); } @@ -825,7 +828,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { place } }; - let instance = ty::Instance::resolve_drop_in_place(*self.tcx, place.layout.ty); + let instance = { + let _trace = + enter_trace_span!(M, resolve::resolve_drop_in_place, ty = ?place.layout.ty); + ty::Instance::resolve_drop_in_place(*self.tcx, place.layout.ty) + }; let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty())?; let arg = self.mplace_to_ref(&place)?; diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index de4fbc7b475..e3afeda5b7c 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -16,8 +16,8 @@ use super::{ FnVal, ImmTy, Immediate, InterpCx, Machine, OpTy, PlaceTy, err_inval, interp_ok, throw_ub, throw_ub_custom, }; -use crate::fluent_generated as fluent; use crate::interpret::Writeable; +use crate::{enter_trace_span, fluent_generated as fluent}; impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { pub fn cast( @@ -81,13 +81,16 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // The src operand does not matter, just its type match *src.layout.ty.kind() { ty::FnDef(def_id, args) => { - let instance = ty::Instance::resolve_for_fn_ptr( - *self.tcx, - self.typing_env, - def_id, - args, - ) - .ok_or_else(|| err_inval!(TooGeneric))?; + let instance = { + let _trace = enter_trace_span!(M, resolve::resolve_for_fn_ptr, ?def_id); + ty::Instance::resolve_for_fn_ptr( + *self.tcx, + self.typing_env, + def_id, + args, + ) + .ok_or_else(|| err_inval!(TooGeneric))? + }; let fn_ptr = self.fn_ptr(FnVal::Instance(instance)); self.write_pointer(fn_ptr, dest)?; @@ -114,12 +117,15 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // The src operand does not matter, just its type match *src.layout.ty.kind() { ty::Closure(def_id, args) => { - let instance = ty::Instance::resolve_closure( - *self.tcx, - def_id, - args, - ty::ClosureKind::FnOnce, - ); + let instance = { + let _trace = enter_trace_span!(M, resolve::resolve_closure, ?def_id); + ty::Instance::resolve_closure( + *self.tcx, + def_id, + args, + ty::ClosureKind::FnOnce, + ) + }; let fn_ptr = self.fn_ptr(FnVal::Instance(instance)); self.write_pointer(fn_ptr, dest)?; } diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index d4f2bb8257d..a8a1ac1c980 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -344,6 +344,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { def: DefId, args: GenericArgsRef<'tcx>, ) -> InterpResult<'tcx, ty::Instance<'tcx>> { + let _trace = enter_trace_span!(M, resolve::try_resolve, def = ?def); trace!("resolve: {:?}, {:#?}", def, args); trace!("typing_env: {:#?}", self.typing_env); trace!("args: {:#?}", args); diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 76e470b69dc..f1995b3f132 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -560,7 +560,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { "Async Drop must be expanded or reset to sync in runtime MIR" ); let place = self.eval_place(place)?; - let instance = Instance::resolve_drop_in_place(*self.tcx, place.layout.ty); + let instance = { + let _trace = + enter_trace_span!(M, resolve::resolve_drop_in_place, ty = ?place.layout.ty); + Instance::resolve_drop_in_place(*self.tcx, place.layout.ty) + }; if let ty::InstanceKind::DropGlue(_, None) = instance.def { // This is the branch we enter if and only if the dropped type has no drop glue // whatsoever. This can happen as a result of monomorphizing a drop of a diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs index 2dc746754f8..9d6674873b1 100644 --- a/compiler/rustc_const_eval/src/util/type_name.rs +++ b/compiler/rustc_const_eval/src/util/type_name.rs @@ -7,12 +7,12 @@ use rustc_middle::bug; use rustc_middle::ty::print::{PrettyPrinter, PrintError, Printer}; use rustc_middle::ty::{self, GenericArg, GenericArgKind, Ty, TyCtxt}; -struct AbsolutePathPrinter<'tcx> { +struct TypeNamePrinter<'tcx> { tcx: TyCtxt<'tcx>, path: String, } -impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { +impl<'tcx> Printer<'tcx> for TypeNamePrinter<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -75,26 +75,26 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { self.pretty_print_dyn_existential(predicates) } - fn path_crate(&mut self, cnum: CrateNum) -> Result<(), PrintError> { + fn print_crate_name(&mut self, cnum: CrateNum) -> Result<(), PrintError> { self.path.push_str(self.tcx.crate_name(cnum).as_str()); Ok(()) } - fn path_qualified( + fn print_path_with_qualified( &mut self, self_ty: Ty<'tcx>, trait_ref: Option<ty::TraitRef<'tcx>>, ) -> Result<(), PrintError> { - self.pretty_path_qualified(self_ty, trait_ref) + self.pretty_print_path_with_qualified(self_ty, trait_ref) } - fn path_append_impl( + fn print_path_with_impl( &mut self, print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, self_ty: Ty<'tcx>, trait_ref: Option<ty::TraitRef<'tcx>>, ) -> Result<(), PrintError> { - self.pretty_path_append_impl( + self.pretty_print_path_with_impl( |cx| { print_prefix(cx)?; @@ -107,7 +107,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { ) } - fn path_append( + fn print_path_with_simple( &mut self, print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, disambiguated_data: &DisambiguatedDefPathData, @@ -119,7 +119,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { Ok(()) } - fn path_generic_args( + fn print_path_with_generic_args( &mut self, print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, args: &[GenericArg<'tcx>], @@ -135,7 +135,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { } } -impl<'tcx> PrettyPrinter<'tcx> for AbsolutePathPrinter<'tcx> { +impl<'tcx> PrettyPrinter<'tcx> for TypeNamePrinter<'tcx> { fn should_print_region(&self, _region: ty::Region<'_>) -> bool { false } @@ -159,7 +159,7 @@ impl<'tcx> PrettyPrinter<'tcx> for AbsolutePathPrinter<'tcx> { } } -impl Write for AbsolutePathPrinter<'_> { +impl Write for TypeNamePrinter<'_> { fn write_str(&mut self, s: &str) -> std::fmt::Result { self.path.push_str(s); Ok(()) @@ -167,7 +167,7 @@ impl Write for AbsolutePathPrinter<'_> { } pub fn type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> String { - let mut p = AbsolutePathPrinter { tcx, path: String::new() }; + let mut p = TypeNamePrinter { tcx, path: String::new() }; p.print_type(ty).unwrap(); p.path } diff --git a/compiler/rustc_error_codes/src/error_codes/E0518.md b/compiler/rustc_error_codes/src/error_codes/E0518.md index f04329bc4e6..87dc231578a 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0518.md +++ b/compiler/rustc_error_codes/src/error_codes/E0518.md @@ -1,9 +1,11 @@ +#### Note: this error code is no longer emitted by the compiler. + An `#[inline(..)]` attribute was incorrectly placed on something other than a function or method. Example of erroneous code: -```compile_fail,E0518 +```ignore (no longer emitted) #[inline(always)] struct Foo; diff --git a/compiler/rustc_error_codes/src/error_codes/E0578.md b/compiler/rustc_error_codes/src/error_codes/E0578.md index fca89757287..78fabe855bb 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0578.md +++ b/compiler/rustc_error_codes/src/error_codes/E0578.md @@ -1,8 +1,10 @@ +#### Note: this error code is no longer emitted by the compiler. + A module cannot be found and therefore, the visibility cannot be determined. Erroneous code example: -```compile_fail,E0578,edition2018 +```ignore (no longer emitted) foo!(); pub (in ::Sea) struct Shark; // error! diff --git a/compiler/rustc_error_codes/src/error_codes/E0701.md b/compiler/rustc_error_codes/src/error_codes/E0701.md index 4965e643105..e1be0e915f4 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0701.md +++ b/compiler/rustc_error_codes/src/error_codes/E0701.md @@ -1,9 +1,11 @@ +#### Note: this error code is no longer emitted by the compiler. + This error indicates that a `#[non_exhaustive]` attribute was incorrectly placed on something other than a struct or enum. Erroneous code example: -```compile_fail,E0701 +```ignore (no longer emitted) #[non_exhaustive] trait Foo { } ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0739.md b/compiler/rustc_error_codes/src/error_codes/E0739.md index 406d3d52779..5403405ca9d 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0739.md +++ b/compiler/rustc_error_codes/src/error_codes/E0739.md @@ -1,8 +1,10 @@ +#### Note: this error code is no longer emitted by the compiler. + `#[track_caller]` must be applied to a function Erroneous code example: -```compile_fail,E0739 +```ignore (no longer emitted) #[track_caller] struct Bar { a: u8, diff --git a/compiler/rustc_error_codes/src/error_codes/E0755.md b/compiler/rustc_error_codes/src/error_codes/E0755.md index b67f078c78e..bd93626a8db 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0755.md +++ b/compiler/rustc_error_codes/src/error_codes/E0755.md @@ -1,8 +1,10 @@ +#### Note: this error code is no longer emitted by the compiler. + The `ffi_pure` attribute was used on a non-foreign function. Erroneous code example: -```compile_fail,E0755 +```ignore (no longer emitted) #![feature(ffi_pure)] #[unsafe(ffi_pure)] // error! diff --git a/compiler/rustc_error_codes/src/error_codes/E0756.md b/compiler/rustc_error_codes/src/error_codes/E0756.md index aadde038d12..daafc2a5ac0 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0756.md +++ b/compiler/rustc_error_codes/src/error_codes/E0756.md @@ -1,9 +1,11 @@ +#### Note: this error code is no longer emitted by the compiler. + The `ffi_const` attribute was used on something other than a foreign function declaration. Erroneous code example: -```compile_fail,E0756 +```ignore (no longer emitted) #![feature(ffi_const)] #[unsafe(ffi_const)] // error! diff --git a/compiler/rustc_error_codes/src/error_codes/E0788.md b/compiler/rustc_error_codes/src/error_codes/E0788.md index ba138aed2d1..1afa961f9b7 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0788.md +++ b/compiler/rustc_error_codes/src/error_codes/E0788.md @@ -1,3 +1,5 @@ +#### Note: this error code is no longer emitted by the compiler. + A `#[coverage(off|on)]` attribute was found in a position where it is not allowed. @@ -10,7 +12,7 @@ Coverage attributes can be applied to: Example of erroneous code: -```compile_fail,E0788 +```ignore (no longer emitted) unsafe extern "C" { #[coverage(off)] fn foreign_fn(); diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 98be37fd84b..e579370ce4e 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -1113,7 +1113,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { .map(|snippet| { debug_assert!( !(sp.is_empty() && snippet.is_empty()), - "Span must not be empty and have no suggestion" + "Span `{sp:?}` must not be empty and have no suggestion" ); Substitution { parts: vec![SubstitutionPart { snippet, span: sp }] } }) diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 7da3bf27eb5..f2c15071532 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -17,6 +17,7 @@ use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, PResult}; use rustc_feature::Features; use rustc_hir as hir; use rustc_hir::attrs::{AttributeKind, CfgEntry, Deprecation}; +use rustc_hir::def::MacroKinds; use rustc_hir::{Stability, find_attr}; use rustc_lint_defs::{BufferedEarlyLint, RegisteredTools}; use rustc_parse::MACRO_ARGUMENTS; @@ -718,6 +719,9 @@ impl MacResult for DummyResult { /// A syntax extension kind. #[derive(Clone)] pub enum SyntaxExtensionKind { + /// A `macro_rules!` macro that can work as any `MacroKind` + MacroRules(Arc<crate::MacroRulesMacroExpander>), + /// A token-based function-like macro. Bang( /// An expander with signature TokenStream -> TokenStream. @@ -772,9 +776,39 @@ pub enum SyntaxExtensionKind { ), /// A glob delegation. + /// + /// This is for delegated function implementations, and has nothing to do with glob imports. GlobDelegation(Arc<dyn GlobDelegationExpander + sync::DynSync + sync::DynSend>), } +impl SyntaxExtensionKind { + /// Returns `Some(expander)` for a macro usable as a `LegacyBang`; otherwise returns `None` + /// + /// This includes a `MacroRules` with function-like rules. + pub fn as_legacy_bang(&self) -> Option<&(dyn TTMacroExpander + sync::DynSync + sync::DynSend)> { + match self { + SyntaxExtensionKind::LegacyBang(exp) => Some(exp.as_ref()), + SyntaxExtensionKind::MacroRules(exp) if exp.kinds().contains(MacroKinds::BANG) => { + Some(exp.as_ref()) + } + _ => None, + } + } + + /// Returns `Some(expander)` for a macro usable as an `Attr`; otherwise returns `None` + /// + /// This includes a `MacroRules` with `attr` rules. + pub fn as_attr(&self) -> Option<&(dyn AttrProcMacro + sync::DynSync + sync::DynSend)> { + match self { + SyntaxExtensionKind::Attr(exp) => Some(exp.as_ref()), + SyntaxExtensionKind::MacroRules(exp) if exp.kinds().contains(MacroKinds::ATTR) => { + Some(exp.as_ref()) + } + _ => None, + } + } +} + /// A struct representing a macro definition in "lowered" form ready for expansion. pub struct SyntaxExtension { /// A syntax extension kind. @@ -804,18 +838,19 @@ pub struct SyntaxExtension { } impl SyntaxExtension { - /// Returns which kind of macro calls this syntax extension. - pub fn macro_kind(&self) -> MacroKind { + /// Returns which kinds of macro call this syntax extension. + pub fn macro_kinds(&self) -> MacroKinds { match self.kind { SyntaxExtensionKind::Bang(..) | SyntaxExtensionKind::LegacyBang(..) - | SyntaxExtensionKind::GlobDelegation(..) => MacroKind::Bang, + | SyntaxExtensionKind::GlobDelegation(..) => MacroKinds::BANG, SyntaxExtensionKind::Attr(..) | SyntaxExtensionKind::LegacyAttr(..) - | SyntaxExtensionKind::NonMacroAttr => MacroKind::Attr, + | SyntaxExtensionKind::NonMacroAttr => MacroKinds::ATTR, SyntaxExtensionKind::Derive(..) | SyntaxExtensionKind::LegacyDerive(..) => { - MacroKind::Derive + MacroKinds::DERIVE } + SyntaxExtensionKind::MacroRules(ref m) => m.kinds(), } } @@ -1024,11 +1059,12 @@ impl SyntaxExtension { parent: LocalExpnId, call_site: Span, descr: Symbol, + kind: MacroKind, macro_def_id: Option<DefId>, parent_module: Option<DefId>, ) -> ExpnData { ExpnData::new( - ExpnKind::Macro(self.macro_kind(), descr), + ExpnKind::Macro(kind, descr), parent.to_expn_id(), call_site, self.span, diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index e7ae4416968..670f5c91bb9 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -736,8 +736,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let (fragment_kind, span) = (invoc.fragment_kind, invoc.span()); ExpandResult::Ready(match invoc.kind { - InvocationKind::Bang { mac, span } => match ext { - SyntaxExtensionKind::Bang(expander) => { + InvocationKind::Bang { mac, span } => { + if let SyntaxExtensionKind::Bang(expander) = ext { match expander.expand(self.cx, span, mac.args.tokens.clone()) { Ok(tok_result) => { let fragment = @@ -755,8 +755,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } Err(guar) => return ExpandResult::Ready(fragment_kind.dummy(span, guar)), } - } - SyntaxExtensionKind::LegacyBang(expander) => { + } else if let Some(expander) = ext.as_legacy_bang() { let tok_result = match expander.expand(self.cx, span, mac.args.tokens.clone()) { ExpandResult::Ready(tok_result) => tok_result, ExpandResult::Retry(_) => { @@ -776,11 +775,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let guar = self.error_wrong_fragment_kind(fragment_kind, &mac, span); fragment_kind.dummy(span, guar) } + } else { + unreachable!(); } - _ => unreachable!(), - }, - InvocationKind::Attr { attr, pos, mut item, derives } => match ext { - SyntaxExtensionKind::Attr(expander) => { + } + InvocationKind::Attr { attr, pos, mut item, derives } => { + if let Some(expander) = ext.as_attr() { self.gate_proc_macro_input(&item); self.gate_proc_macro_attr_item(span, &item); let tokens = match &item { @@ -835,8 +835,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } Err(guar) => return ExpandResult::Ready(fragment_kind.dummy(span, guar)), } - } - SyntaxExtensionKind::LegacyAttr(expander) => { + } else if let SyntaxExtensionKind::LegacyAttr(expander) = ext { match validate_attr::parse_meta(&self.cx.sess.psess, &attr) { Ok(meta) => { let item_clone = macro_stats.then(|| item.clone()); @@ -878,15 +877,15 @@ impl<'a, 'b> MacroExpander<'a, 'b> { fragment_kind.expect_from_annotatables(iter::once(item)) } } - } - SyntaxExtensionKind::NonMacroAttr => { + } else if let SyntaxExtensionKind::NonMacroAttr = ext { // `-Zmacro-stats` ignores these because they don't do any real expansion. self.cx.expanded_inert_attrs.mark(&attr); item.visit_attrs(|attrs| attrs.insert(pos, attr)); fragment_kind.expect_from_annotatables(iter::once(item)) + } else { + unreachable!(); } - _ => unreachable!(), - }, + } InvocationKind::Derive { path, item, is_const } => match ext { SyntaxExtensionKind::Derive(expander) | SyntaxExtensionKind::LegacyDerive(expander) => { @@ -2155,6 +2154,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { attr_name, macro_name: pprust::path_to_string(&call.path), invoc_span: call.path.span, + attr_span: attr.span, }, ); } diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index 5b9d56ee2bc..80433b7be91 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -58,18 +58,6 @@ pub(super) fn failed_to_match_macro( let Some(BestFailure { token, msg: label, remaining_matcher, .. }) = tracker.best_failure else { - // FIXME: we should report this at macro resolution time, as we do for - // `resolve_macro_cannot_use_as_attr`. We can do that once we track multiple macro kinds for a - // Def. - if attr_args.is_none() && !rules.iter().any(|rule| matches!(rule, MacroRule::Func { .. })) { - let msg = format!("macro has no rules for function-like invocation `{name}!`"); - let mut err = psess.dcx().struct_span_err(sp, msg); - if !def_head_span.is_dummy() { - let msg = "this macro has no rules for function-like invocation"; - err.span_label(def_head_span, msg); - } - return (sp, err.emit()); - } return (sp, psess.dcx().span_delayed_bug(sp, "failed to match a macro")); }; diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs index 25987a50366..faeae1f494e 100644 --- a/compiler/rustc_expand/src/mbe/macro_check.rs +++ b/compiler/rustc_expand/src/mbe/macro_check.rs @@ -357,10 +357,10 @@ enum NestedMacroState { /// The token `macro_rules` was processed. MacroRules, /// The tokens `macro_rules!` were processed. - MacroRulesNot, + MacroRulesBang, /// The tokens `macro_rules!` followed by a name were processed. The name may be either directly /// an identifier or a meta-variable (that hopefully would be instantiated by an identifier). - MacroRulesNotName, + MacroRulesBangName, /// The keyword `macro` was processed. Macro, /// The keyword `macro` followed by a name was processed. @@ -408,24 +408,24 @@ fn check_nested_occurrences( NestedMacroState::MacroRules, &TokenTree::Token(Token { kind: TokenKind::Bang, .. }), ) => { - state = NestedMacroState::MacroRulesNot; + state = NestedMacroState::MacroRulesBang; } ( - NestedMacroState::MacroRulesNot, + NestedMacroState::MacroRulesBang, &TokenTree::Token(Token { kind: TokenKind::Ident(..), .. }), ) => { - state = NestedMacroState::MacroRulesNotName; + state = NestedMacroState::MacroRulesBangName; } - (NestedMacroState::MacroRulesNot, &TokenTree::MetaVar(..)) => { - state = NestedMacroState::MacroRulesNotName; + (NestedMacroState::MacroRulesBang, &TokenTree::MetaVar(..)) => { + state = NestedMacroState::MacroRulesBangName; // We check that the meta-variable is correctly used. check_occurrences(psess, node_id, tt, macros, binders, ops, guar); } - (NestedMacroState::MacroRulesNotName, TokenTree::Delimited(.., del)) + (NestedMacroState::MacroRulesBangName, TokenTree::Delimited(.., del)) | (NestedMacroState::MacroName, TokenTree::Delimited(.., del)) if del.delim == Delimiter::Brace => { - let macro_rules = state == NestedMacroState::MacroRulesNotName; + let macro_rules = state == NestedMacroState::MacroRulesBangName; state = NestedMacroState::Empty; let rest = check_nested_macro(psess, node_id, macro_rules, &del.tts, &nested_macros, guar); diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 08b0efb74a0..334f57f9d62 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -15,6 +15,7 @@ use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan}; use rustc_feature::Features; use rustc_hir as hir; use rustc_hir::attrs::AttributeKind; +use rustc_hir::def::MacroKinds; use rustc_hir::find_attr; use rustc_lint_defs::BuiltinLintDiag; use rustc_lint_defs::builtin::{ @@ -144,6 +145,7 @@ pub struct MacroRulesMacroExpander { name: Ident, span: Span, transparency: Transparency, + kinds: MacroKinds, rules: Vec<MacroRule>, } @@ -158,6 +160,10 @@ impl MacroRulesMacroExpander { }; if has_compile_error_macro(rhs) { None } else { Some((&self.name, span)) } } + + pub fn kinds(&self) -> MacroKinds { + self.kinds + } } impl TTMacroExpander for MacroRulesMacroExpander { @@ -540,13 +546,13 @@ pub fn compile_declarative_macro( span: Span, node_id: NodeId, edition: Edition, -) -> (SyntaxExtension, Option<Arc<SyntaxExtension>>, usize) { +) -> (SyntaxExtension, usize) { let mk_syn_ext = |kind| { let is_local = is_defined_in_current_crate(node_id); SyntaxExtension::new(sess, kind, span, Vec::new(), edition, ident.name, attrs, is_local) }; - let mk_bang_ext = |expander| mk_syn_ext(SyntaxExtensionKind::LegacyBang(expander)); - let dummy_syn_ext = |guar| (mk_bang_ext(Arc::new(DummyExpander(guar))), None, 0); + let dummy_syn_ext = + |guar| (mk_syn_ext(SyntaxExtensionKind::LegacyBang(Arc::new(DummyExpander(guar)))), 0); let macro_rules = macro_def.macro_rules; let exp_sep = if macro_rules { exp!(Semi) } else { exp!(Comma) }; @@ -559,12 +565,12 @@ pub fn compile_declarative_macro( let mut guar = None; let mut check_emission = |ret: Result<(), ErrorGuaranteed>| guar = guar.or(ret.err()); - let mut has_attr_rules = false; + let mut kinds = MacroKinds::empty(); let mut rules = Vec::new(); while p.token != token::Eof { let args = if p.eat_keyword_noexpect(sym::attr) { - has_attr_rules = true; + kinds |= MacroKinds::ATTR; if !features.macro_attr() { feature_err(sess, sym::macro_attr, span, "`macro_rules!` attributes are unstable") .emit(); @@ -581,6 +587,7 @@ pub fn compile_declarative_macro( } Some(args) } else { + kinds |= MacroKinds::BANG; None }; let lhs_tt = p.parse_token_tree(); @@ -627,6 +634,7 @@ pub fn compile_declarative_macro( let guar = sess.dcx().span_err(span, "macros must contain at least one rule"); return dummy_syn_ext(guar); } + assert!(!kinds.is_empty()); let transparency = find_attr!(attrs, AttributeKind::MacroTransparency(x) => *x) .unwrap_or(Transparency::fallback(macro_rules)); @@ -640,12 +648,8 @@ pub fn compile_declarative_macro( // Return the number of rules for unused rule linting, if this is a local macro. let nrules = if is_defined_in_current_crate(node_id) { rules.len() } else { 0 }; - let exp = Arc::new(MacroRulesMacroExpander { name: ident, span, node_id, transparency, rules }); - let opt_attr_ext = has_attr_rules.then(|| { - let exp = Arc::clone(&exp); - Arc::new(mk_syn_ext(SyntaxExtensionKind::Attr(exp))) - }); - (mk_bang_ext(exp), opt_attr_ext, nrules) + let exp = MacroRulesMacroExpander { name: ident, kinds, span, node_id, transparency, rules }; + (mk_syn_ext(SyntaxExtensionKind::MacroRules(Arc::new(exp))), nrules) } fn check_no_eof(sess: &Session, p: &Parser<'_>, msg: &'static str) -> Option<ErrorGuaranteed> { diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 83be3241b12..9fe55216f93 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -396,6 +396,8 @@ declare_features! ( (accepted, slice_patterns, "1.42.0", Some(62254)), /// Allows use of `&foo[a..b]` as a slicing syntax. (accepted, slicing_syntax, "1.0.0", None), + /// Allows use of `sse4a` target feature. + (accepted, sse4a_target_feature, "CURRENT_RUSTC_VERSION", Some(44839)), /// Allows elision of `'static` lifetimes in `static`s and `const`s. (accepted, static_in_const, "1.17.0", Some(35897)), /// Allows the definition recursive static items. @@ -408,6 +410,8 @@ declare_features! ( (accepted, target_feature, "1.27.0", None), /// Allows the use of `#[target_feature]` on safe functions. (accepted, target_feature_11, "1.86.0", Some(69098)), + /// Allows use of `tbm` target feature. + (accepted, tbm_target_feature, "CURRENT_RUSTC_VERSION", Some(44839)), /// Allows `fn main()` with return types which implements `Termination` (RFC 1937). (accepted, termination_trait, "1.26.0", Some(43301)), /// Allows `#[test]` functions where the return type implements `Termination` (RFC 1937). diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index acc21f6c6d2..87ecc7b41e2 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -334,8 +334,6 @@ declare_features! ( (unstable, rtm_target_feature, "1.35.0", Some(44839)), (unstable, s390x_target_feature, "1.82.0", Some(44839)), (unstable, sparc_target_feature, "1.84.0", Some(132783)), - (unstable, sse4a_target_feature, "1.27.0", Some(44839)), - (unstable, tbm_target_feature, "1.27.0", Some(44839)), (unstable, wasm_target_feature, "1.30.0", Some(44839)), (unstable, x87_target_feature, "1.85.0", Some(44839)), // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! diff --git a/compiler/rustc_hir/Cargo.toml b/compiler/rustc_hir/Cargo.toml index 539d2e6f0b1..71496b7ec32 100644 --- a/compiler/rustc_hir/Cargo.toml +++ b/compiler/rustc_hir/Cargo.toml @@ -5,6 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start +bitflags = "2.9.1" odht = { version = "0.3.1", features = ["nightly"] } rustc_abi = { path = "../rustc_abi" } rustc_arena = { path = "../rustc_arena" } diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index e02edf5fe24..510fc832978 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -187,6 +187,24 @@ pub enum CfgEntry { Version(Option<RustcVersion>, Span), } +/// Possible values for the `#[linkage]` attribute, allowing to specify the +/// linkage type for a `MonoItem`. +/// +/// See <https://llvm.org/docs/LangRef.html#linkage-types> for more details about these variants. +#[derive(Encodable, Decodable, Clone, Copy, Debug, PartialEq, Eq, Hash)] +#[derive(HashStable_Generic, PrintAttribute)] +pub enum Linkage { + AvailableExternally, + Common, + ExternalWeak, + External, + Internal, + LinkOnceAny, + LinkOnceODR, + WeakAny, + WeakODR, +} + /// Represents parsed *built-in* inert attributes. /// /// ## Overview @@ -360,6 +378,9 @@ pub enum AttributeKind { /// Represents [`#[link_section]`](https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute) LinkSection { name: Symbol, span: Span }, + /// Represents `#[linkage]`. + Linkage(Linkage, Span), + /// Represents `#[loop_match]`. LoopMatch(Span), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 7ce624dcc55..84a975523f2 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -46,6 +46,7 @@ impl AttributeKind { LinkName { .. } => Yes, // Needed for rustdoc LinkOrdinal { .. } => No, LinkSection { .. } => Yes, // Needed for rustdoc + Linkage(..) => No, LoopMatch(..) => No, MacroEscape(..) => No, MacroTransparency(..) => Yes, diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 339d4e2eab7..79319e24266 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -31,6 +31,53 @@ pub enum CtorKind { Const, } +/// A set of macro kinds, for macros that can have more than one kind +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable, Hash, Debug)] +#[derive(HashStable_Generic)] +pub struct MacroKinds(u8); +bitflags::bitflags! { + impl MacroKinds: u8 { + const BANG = 1 << 0; + const ATTR = 1 << 1; + const DERIVE = 1 << 2; + } +} + +impl From<MacroKind> for MacroKinds { + fn from(kind: MacroKind) -> Self { + match kind { + MacroKind::Bang => Self::BANG, + MacroKind::Attr => Self::ATTR, + MacroKind::Derive => Self::DERIVE, + } + } +} + +impl MacroKinds { + /// Convert the MacroKinds to a static string. + /// + /// This hardcodes all the possibilities, in order to return a static string. + pub fn descr(self) -> &'static str { + match self { + // FIXME: change this to "function-like macro" and fix all tests + Self::BANG => "macro", + Self::ATTR => "attribute macro", + Self::DERIVE => "derive macro", + _ if self == (Self::ATTR | Self::BANG) => "attribute/function macro", + _ if self == (Self::DERIVE | Self::BANG) => "derive/function macro", + _ if self == (Self::ATTR | Self::DERIVE) => "attribute/derive macro", + _ if self.is_all() => "attribute/derive/function macro", + _ if self.is_empty() => "useless macro", + _ => unreachable!(), + } + } + + /// Return an indefinite article (a/an) for use with `descr()` + pub fn article(self) -> &'static str { + if self.contains(Self::ATTR) { "an" } else { "a" } + } +} + /// An attribute that is not a macro; e.g., `#[inline]` or `#[rustfmt::skip]`. #[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug, HashStable_Generic)] pub enum NonMacroAttrKind { @@ -101,7 +148,7 @@ pub enum DefKind { AssocConst, // Macro namespace - Macro(MacroKind), + Macro(MacroKinds), // Not namespaced (or they are, but we don't treat them so) ExternCrate, @@ -177,7 +224,7 @@ impl DefKind { DefKind::AssocConst => "associated constant", DefKind::TyParam => "type parameter", DefKind::ConstParam => "const parameter", - DefKind::Macro(macro_kind) => macro_kind.descr(), + DefKind::Macro(kinds) => kinds.descr(), DefKind::LifetimeParam => "lifetime parameter", DefKind::Use => "import", DefKind::ForeignMod => "foreign module", @@ -208,7 +255,7 @@ impl DefKind { | DefKind::Use | DefKind::InlineConst | DefKind::ExternCrate => "an", - DefKind::Macro(macro_kind) => macro_kind.article(), + DefKind::Macro(kinds) => kinds.article(), _ => "a", } } @@ -845,10 +892,10 @@ impl<Id> Res<Id> { ) } - pub fn macro_kind(self) -> Option<MacroKind> { + pub fn macro_kinds(self) -> Option<MacroKinds> { match self { - Res::Def(DefKind::Macro(kind), _) => Some(kind), - Res::NonMacroAttr(..) => Some(MacroKind::Attr), + Res::Def(DefKind::Macro(kinds), _) => Some(kinds), + Res::NonMacroAttr(..) => Some(MacroKinds::ATTR), _ => None, } } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index b27c223527e..2c8986b7c7d 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -20,7 +20,6 @@ use rustc_data_structures::tagged_ptr::TaggedRef; use rustc_index::IndexVec; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::def_id::LocalDefId; -use rustc_span::hygiene::MacroKind; use rustc_span::source_map::Spanned; use rustc_span::{BytePos, DUMMY_SP, ErrorGuaranteed, Ident, Span, Symbol, kw, sym}; use rustc_target::asm::InlineAsmRegOrRegClass; @@ -30,7 +29,7 @@ use tracing::debug; use crate::LangItem; use crate::attrs::AttributeKind; -use crate::def::{CtorKind, DefKind, PerNS, Res}; +use crate::def::{CtorKind, DefKind, MacroKinds, PerNS, Res}; use crate::def_id::{DefId, LocalDefIdMap}; pub(crate) use crate::hir_id::{HirId, ItemLocalId, ItemLocalMap, OwnerId}; use crate::intravisit::{FnKind, VisitorExt}; @@ -1233,6 +1232,13 @@ impl Attribute { _ => None, } } + + pub fn is_parsed_attr(&self) -> bool { + match self { + Attribute::Parsed(_) => true, + Attribute::Unparsed(_) => false, + } + } } impl AttributeExt for Attribute { @@ -1303,14 +1309,10 @@ impl AttributeExt for Attribute { match &self { Attribute::Unparsed(u) => u.span, // FIXME: should not be needed anymore when all attrs are parsed - Attribute::Parsed(AttributeKind::Deprecation { span, .. }) => *span, Attribute::Parsed(AttributeKind::DocComment { span, .. }) => *span, - Attribute::Parsed(AttributeKind::MacroUse { span, .. }) => *span, - Attribute::Parsed(AttributeKind::MayDangle(span)) => *span, - Attribute::Parsed(AttributeKind::Ignore { span, .. }) => *span, - Attribute::Parsed(AttributeKind::ShouldPanic { span, .. }) => *span, - Attribute::Parsed(AttributeKind::AutomaticallyDerived(span)) => *span, + Attribute::Parsed(AttributeKind::Deprecation { span, .. }) => *span, Attribute::Parsed(AttributeKind::AllowInternalUnsafe(span)) => *span, + Attribute::Parsed(AttributeKind::Linkage(_, span)) => *span, a => panic!("can't get the span of an arbitrary parsed attribute: {a:?}"), } } @@ -4157,7 +4159,7 @@ impl<'hir> Item<'hir> { expect_fn, (Ident, &FnSig<'hir>, &'hir Generics<'hir>, BodyId), ItemKind::Fn { ident, sig, generics, body, .. }, (*ident, sig, generics, *body); - expect_macro, (Ident, &ast::MacroDef, MacroKind), + expect_macro, (Ident, &ast::MacroDef, MacroKinds), ItemKind::Macro(ident, def, mk), (*ident, def, *mk); expect_mod, (Ident, &'hir Mod<'hir>), ItemKind::Mod(ident, m), (*ident, m); @@ -4336,7 +4338,7 @@ pub enum ItemKind<'hir> { has_body: bool, }, /// A MBE macro definition (`macro_rules!` or `macro`). - Macro(Ident, &'hir ast::MacroDef, MacroKind), + Macro(Ident, &'hir ast::MacroDef, MacroKinds), /// A module. Mod(Ident, &'hir Mod<'hir>), /// An external module, e.g. `extern { .. }`. diff --git a/compiler/rustc_hir/src/lints.rs b/compiler/rustc_hir/src/lints.rs index c55a41eb2b7..e3cde2d3bb6 100644 --- a/compiler/rustc_hir/src/lints.rs +++ b/compiler/rustc_hir/src/lints.rs @@ -1,8 +1,8 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_macros::HashStable_Generic; -use rustc_span::Span; +use rustc_span::{Span, Symbol}; -use crate::HirId; +use crate::{HirId, Target}; #[derive(Debug)] pub struct DelayedLints { @@ -34,4 +34,5 @@ pub enum AttributeLintKind { UnusedDuplicate { this: Span, other: Span, warning: bool }, IllFormedAttributeInput { suggestions: Vec<String> }, EmptyAttribute { first_span: Span }, + InvalidTarget { name: Symbol, target: Target, applied: String, only: &'static str }, } diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs index d617f44f8d8..f68dad3a5e8 100644 --- a/compiler/rustc_hir/src/target.rs +++ b/compiler/rustc_hir/src/target.rs @@ -6,23 +6,34 @@ use std::fmt::{self, Display}; +use rustc_ast::visit::AssocCtxt; +use rustc_ast::{AssocItemKind, ForeignItemKind, ast}; +use rustc_macros::HashStable_Generic; + use crate::def::DefKind; use crate::{Item, ItemKind, TraitItem, TraitItemKind, hir}; -#[derive(Copy, Clone, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug, Eq, HashStable_Generic)] pub enum GenericParamKind { Type, Lifetime, Const, } -#[derive(Copy, Clone, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug, Eq, HashStable_Generic)] pub enum MethodKind { - Trait { body: bool }, + /// Method in a `trait Trait` block + Trait { + /// Whether a default is provided for this method + body: bool, + }, + /// Method in a `impl Trait for Type` block + TraitImpl, + /// Method in a `impl Type` block Inherent, } -#[derive(Copy, Clone, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug, Eq, HashStable_Generic)] pub enum Target { ExternCrate, Use, @@ -57,6 +68,9 @@ pub enum Target { PatField, ExprField, WherePredicate, + MacroCall, + Crate, + Delegation { mac: bool }, } impl Display for Target { @@ -98,7 +112,10 @@ impl Target { | Target::Param | Target::PatField | Target::ExprField - | Target::WherePredicate => false, + | Target::MacroCall + | Target::Crate + | Target::WherePredicate + | Target::Delegation { .. } => false, } } @@ -146,6 +163,39 @@ impl Target { } } + pub fn from_ast_item(item: &ast::Item) -> Target { + match item.kind { + ast::ItemKind::ExternCrate(..) => Target::ExternCrate, + ast::ItemKind::Use(..) => Target::Use, + ast::ItemKind::Static { .. } => Target::Static, + ast::ItemKind::Const(..) => Target::Const, + ast::ItemKind::Fn { .. } => Target::Fn, + ast::ItemKind::Mod(..) => Target::Mod, + ast::ItemKind::ForeignMod { .. } => Target::ForeignMod, + ast::ItemKind::GlobalAsm { .. } => Target::GlobalAsm, + ast::ItemKind::TyAlias(..) => Target::TyAlias, + ast::ItemKind::Enum(..) => Target::Enum, + ast::ItemKind::Struct(..) => Target::Struct, + ast::ItemKind::Union(..) => Target::Union, + ast::ItemKind::Trait(..) => Target::Trait, + ast::ItemKind::TraitAlias(..) => Target::TraitAlias, + ast::ItemKind::Impl(ref i) => Target::Impl { of_trait: i.of_trait.is_some() }, + ast::ItemKind::MacCall(..) => Target::MacroCall, + ast::ItemKind::MacroDef(..) => Target::MacroDef, + ast::ItemKind::Delegation(..) => Target::Delegation { mac: false }, + ast::ItemKind::DelegationMac(..) => Target::Delegation { mac: true }, + } + } + + pub fn from_foreign_item_kind(kind: &ast::ForeignItemKind) -> Target { + match kind { + ForeignItemKind::Static(_) => Target::ForeignStatic, + ForeignItemKind::Fn(_) => Target::ForeignFn, + ForeignItemKind::TyAlias(_) => Target::ForeignTy, + ForeignItemKind::MacCall(_) => Target::MacroCall, + } + } + pub fn from_trait_item(trait_item: &TraitItem<'_>) -> Target { match trait_item.kind { TraitItemKind::Const(..) => Target::AssocConst, @@ -183,12 +233,40 @@ impl Target { } } + pub fn from_assoc_item_kind(kind: &ast::AssocItemKind, assoc_ctxt: AssocCtxt) -> Target { + match kind { + AssocItemKind::Const(_) => Target::AssocConst, + AssocItemKind::Fn(f) => Target::Method(match assoc_ctxt { + AssocCtxt::Trait => MethodKind::Trait { body: f.body.is_some() }, + AssocCtxt::Impl { of_trait } => { + if of_trait { + MethodKind::TraitImpl + } else { + MethodKind::Inherent + } + } + }), + AssocItemKind::Type(_) => Target::AssocTy, + AssocItemKind::Delegation(_) => Target::Delegation { mac: false }, + AssocItemKind::DelegationMac(_) => Target::Delegation { mac: true }, + AssocItemKind::MacCall(_) => Target::MacroCall, + } + } + + pub fn from_expr(expr: &ast::Expr) -> Self { + match &expr.kind { + ast::ExprKind::Closure(..) | ast::ExprKind::Gen(..) => Self::Closure, + ast::ExprKind::Paren(e) => Self::from_expr(&e), + _ => Self::Expression, + } + } + pub fn name(self) -> &'static str { match self { Target::ExternCrate => "extern crate", Target::Use => "use", - Target::Static => "static item", - Target::Const => "constant item", + Target::Static => "static", + Target::Const => "constant", Target::Fn => "function", Target::Closure => "closure", Target::Mod => "module", @@ -202,8 +280,7 @@ impl Target { Target::Union => "union", Target::Trait => "trait", Target::TraitAlias => "trait alias", - Target::Impl { of_trait: false } => "inherent implementation block", - Target::Impl { of_trait: true } => "trait implementation block", + Target::Impl { .. } => "implementation block", Target::Expression => "expression", Target::Statement => "statement", Target::Arm => "match arm", @@ -212,12 +289,13 @@ impl Target { MethodKind::Inherent => "inherent method", MethodKind::Trait { body: false } => "required trait method", MethodKind::Trait { body: true } => "provided trait method", + MethodKind::TraitImpl => "trait method in an impl block", }, Target::AssocTy => "associated type", Target::ForeignFn => "foreign function", Target::ForeignStatic => "foreign static item", Target::ForeignTy => "foreign type", - Target::GenericParam { kind, has_default: _ } => match kind { + Target::GenericParam { kind, .. } => match kind { GenericParamKind::Type => "type parameter", GenericParamKind::Lifetime => "lifetime parameter", GenericParamKind::Const => "const parameter", @@ -227,6 +305,60 @@ impl Target { Target::PatField => "pattern field", Target::ExprField => "struct field", Target::WherePredicate => "where predicate", + Target::MacroCall => "macro call", + Target::Crate => "crate", + Target::Delegation { .. } => "delegation", + } + } + + pub fn plural_name(self) -> &'static str { + match self { + Target::ExternCrate => "extern crates", + Target::Use => "use statements", + Target::Static => "statics", + Target::Const => "constants", + Target::Fn => "functions", + Target::Closure => "closures", + Target::Mod => "modules", + Target::ForeignMod => "foreign modules", + Target::GlobalAsm => "global asms", + Target::TyAlias => "type aliases", + Target::Enum => "enums", + Target::Variant => "enum variants", + Target::Struct => "structs", + Target::Field => "struct fields", + Target::Union => "unions", + Target::Trait => "traits", + Target::TraitAlias => "trait aliases", + Target::Impl { of_trait: false } => "inherent impl blocks", + Target::Impl { of_trait: true } => "trait impl blocks", + Target::Expression => "expressions", + Target::Statement => "statements", + Target::Arm => "match arms", + Target::AssocConst => "associated consts", + Target::Method(kind) => match kind { + MethodKind::Inherent => "inherent methods", + MethodKind::Trait { body: false } => "required trait methods", + MethodKind::Trait { body: true } => "provided trait methods", + MethodKind::TraitImpl => "trait methods in impl blocks", + }, + Target::AssocTy => "associated types", + Target::ForeignFn => "foreign functions", + Target::ForeignStatic => "foreign statics", + Target::ForeignTy => "foreign types", + Target::GenericParam { kind, has_default: _ } => match kind { + GenericParamKind::Type => "type parameters", + GenericParamKind::Lifetime => "lifetime parameters", + GenericParamKind::Const => "const parameters", + }, + Target::MacroDef => "macro defs", + Target::Param => "function params", + Target::PatField => "pattern fields", + Target::ExprField => "struct fields", + Target::WherePredicate => "where predicates", + Target::MacroCall => "macro calls", + Target::Crate => "crates", + Target::Delegation { .. } => "delegations", } } } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 6767e5ed88d..e4827256193 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -445,10 +445,10 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( tcx: TyCtxt<'tcx>, impl_m_def_id: LocalDefId, ) -> Result<&'tcx DefIdMap<ty::EarlyBinder<'tcx, Ty<'tcx>>>, ErrorGuaranteed> { - let impl_m = tcx.opt_associated_item(impl_m_def_id.to_def_id()).unwrap(); - let trait_m = tcx.opt_associated_item(impl_m.trait_item_def_id.unwrap()).unwrap(); + let impl_m = tcx.associated_item(impl_m_def_id.to_def_id()); + let trait_m = tcx.associated_item(impl_m.trait_item_def_id.unwrap()); let impl_trait_ref = - tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap().instantiate_identity(); + tcx.impl_trait_ref(tcx.parent(impl_m_def_id.to_def_id())).unwrap().instantiate_identity(); // First, check a few of the same things as `compare_impl_method`, // just so we don't ICE during instantiation later. check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, true)?; diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index c642435b989..e6a1f6d8d8b 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -2287,8 +2287,7 @@ fn lint_redundant_lifetimes<'tcx>( // Proceed } DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => { - let parent_def_id = tcx.local_parent(owner_id); - if matches!(tcx.def_kind(parent_def_id), DefKind::Impl { of_trait: true }) { + if tcx.trait_impl_of_assoc(owner_id.to_def_id()).is_some() { // Don't check for redundant lifetimes for associated items of trait // implementations, since the signature is required to be compatible // with the trait, even if the implementation implies some lifetimes diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 6013430e1ff..aca3840712e 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -2378,6 +2378,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .filter_map(|variant| { let sole_field = &variant.single_field(); + // When expected_ty and expr_ty are the same ADT, we prefer to compare their internal generic params, + // When the current variant has a sole field whose type is still an unresolved inference variable, + // suggestions would be often wrong. So suppress the suggestion. See #145294. + if let (ty::Adt(exp_adt, _), ty::Adt(act_adt, _)) = (expected.kind(), expr_ty.kind()) + && exp_adt.did() == act_adt.did() + && sole_field.ty(self.tcx, args).is_ty_var() { + return None; + } + let field_is_local = sole_field.did.is_local(); let field_is_accessible = sole_field.vis.is_accessible_from(expr.hir_id.owner.def_id, self.tcx) diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 16474b231e0..0a764808f95 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -689,6 +689,7 @@ fn test_unstable_options_tracking_hash() { // Make sure that changing an [UNTRACKED] option leaves the hash unchanged. // tidy-alphabetical-start untracked!(assert_incr_state, Some(String::from("loaded"))); + untracked!(codegen_source_order, true); untracked!(deduplicate_diagnostics, false); untracked!(dump_dep_graph, true); untracked!(dump_mir, Some(String::from("abc"))); diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 776d8d35e05..c485e6fc849 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -983,6 +983,7 @@ lint_unused_allocation_mut = unnecessary allocation, use `&mut` instead lint_unused_builtin_attribute = unused attribute `{$attr_name}` .note = the built-in attribute `{$attr_name}` will be ignored, since it's applied to the macro invocation `{$macro_name}` + .suggestion = remove the attribute lint_unused_closure = unused {$pre}{$count -> diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 11181d10af5..d9163d94710 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -745,12 +745,12 @@ impl<'tcx> LateContext<'tcx> { /// } /// ``` pub fn get_def_path(&self, def_id: DefId) -> Vec<Symbol> { - struct AbsolutePathPrinter<'tcx> { + struct LintPathPrinter<'tcx> { tcx: TyCtxt<'tcx>, path: Vec<Symbol>, } - impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { + impl<'tcx> Printer<'tcx> for LintPathPrinter<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -774,12 +774,12 @@ impl<'tcx> LateContext<'tcx> { unreachable!(); // because `path_generic_args` ignores the `GenericArgs` } - fn path_crate(&mut self, cnum: CrateNum) -> Result<(), PrintError> { + fn print_crate_name(&mut self, cnum: CrateNum) -> Result<(), PrintError> { self.path = vec![self.tcx.crate_name(cnum)]; Ok(()) } - fn path_qualified( + fn print_path_with_qualified( &mut self, self_ty: Ty<'tcx>, trait_ref: Option<ty::TraitRef<'tcx>>, @@ -800,7 +800,7 @@ impl<'tcx> LateContext<'tcx> { }) } - fn path_append_impl( + fn print_path_with_impl( &mut self, print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, self_ty: Ty<'tcx>, @@ -825,7 +825,7 @@ impl<'tcx> LateContext<'tcx> { Ok(()) } - fn path_append( + fn print_path_with_simple( &mut self, print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, disambiguated_data: &DisambiguatedDefPathData, @@ -844,7 +844,7 @@ impl<'tcx> LateContext<'tcx> { Ok(()) } - fn path_generic_args( + fn print_path_with_generic_args( &mut self, print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, _args: &[GenericArg<'tcx>], @@ -853,7 +853,7 @@ impl<'tcx> LateContext<'tcx> { } } - let mut p = AbsolutePathPrinter { tcx: self.tcx, path: vec![] }; + let mut p = LintPathPrinter { tcx: self.tcx, path: vec![] }; p.print_def_path(def_id, &[]).unwrap(); p.path } diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index 1e4bc79ce70..678d3d1f8ed 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -205,8 +205,14 @@ pub fn decorate_builtin_lint( } .decorate_lint(diag); } - BuiltinLintDiag::UnusedBuiltinAttribute { attr_name, macro_name, invoc_span } => { - lints::UnusedBuiltinAttribute { invoc_span, attr_name, macro_name }.decorate_lint(diag); + BuiltinLintDiag::UnusedBuiltinAttribute { + attr_name, + macro_name, + invoc_span, + attr_span, + } => { + lints::UnusedBuiltinAttribute { invoc_span, attr_name, macro_name, attr_span } + .decorate_lint(diag); } BuiltinLintDiag::TrailingMacro(is_trailing, name) => { lints::TrailingMacro { is_trailing, name }.decorate_lint(diag); diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index ba0112c8ac6..a6d59af6900 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -2938,9 +2938,10 @@ pub(crate) struct RawPrefix { pub(crate) struct UnusedBuiltinAttribute { #[note] pub invoc_span: Span, - pub attr_name: Symbol, pub macro_name: String, + #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")] + pub attr_span: Span, } #[derive(LintDiagnostic)] diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index 2dd3425e66c..dca22b986ff 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -5,7 +5,7 @@ use rustc_hir::{Body, HirId, Item, ItemKind, Node, Path, TyKind}; use rustc_middle::ty::TyCtxt; use rustc_session::{declare_lint, impl_lint_pass}; use rustc_span::def_id::{DefId, LOCAL_CRATE}; -use rustc_span::{ExpnKind, MacroKind, Span, kw, sym}; +use rustc_span::{ExpnKind, Span, kw, sym}; use crate::lints::{NonLocalDefinitionsCargoUpdateNote, NonLocalDefinitionsDiag}; use crate::{LateContext, LateLintPass, LintContext, fluent_generated as fluent}; @@ -240,7 +240,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { }, ) } - ItemKind::Macro(_, _macro, MacroKind::Bang) + ItemKind::Macro(_, _macro, _kinds) if cx.tcx.has_attr(item.owner_id.def_id, sym::macro_export) => { cx.emit_span_lint( diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs index 4f65acd8001..29006732aad 100644 --- a/compiler/rustc_lint/src/pass_by_value.rs +++ b/compiler/rustc_lint/src/pass_by_value.rs @@ -24,10 +24,8 @@ impl<'tcx> LateLintPass<'tcx> for PassByValue { fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx, AmbigArg>) { match &ty.kind { TyKind::Ref(_, hir::MutTy { ty: inner_ty, mutbl: hir::Mutability::Not }) => { - if let Some(impl_did) = cx.tcx.impl_of_assoc(ty.hir_id.owner.to_def_id()) { - if cx.tcx.impl_trait_ref(impl_did).is_some() { - return; - } + if cx.tcx.trait_impl_of_assoc(ty.hir_id.owner.to_def_id()).is_some() { + return; } if let Some(t) = path_for_pass_by_value(cx, inner_ty) { cx.emit_span_lint( diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index b0afc333ebe..f8a692313f0 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1904,10 +1904,9 @@ impl InvalidAtomicOrdering { if let ExprKind::MethodCall(method_path, _, args, _) = &expr.kind && recognized_names.contains(&method_path.ident.name) && let Some(m_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) - && let Some(impl_did) = cx.tcx.impl_of_assoc(m_def_id) - && let Some(adt) = cx.tcx.type_of(impl_did).instantiate_identity().ty_adt_def() // skip extension traits, only lint functions from the standard library - && cx.tcx.trait_id_of_impl(impl_did).is_none() + && let Some(impl_did) = cx.tcx.inherent_impl_of_assoc(m_def_id) + && let Some(adt) = cx.tcx.type_of(impl_did).instantiate_identity().ty_adt_def() && let parent = cx.tcx.parent(adt.did()) && cx.tcx.is_diagnostic_item(sym::atomic_mod, parent) && ATOMIC_TYPES.contains(&cx.tcx.item_name(adt.did())) diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index dc5ea3922f1..3bb7bbce567 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -647,6 +647,7 @@ pub enum BuiltinLintDiag { attr_name: Symbol, macro_name: String, invoc_span: Span, + attr_span: Span, }, PatternsInFnsWithoutBody { span: Span, diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 588d867bbbf..cd4f80f808c 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -277,6 +277,7 @@ enum class LLVMRustAttributeKind { FnRetThunkExtern = 41, Writable = 42, DeadOnUnwind = 43, + DeadOnReturn = 44, }; static Attribute::AttrKind fromRust(LLVMRustAttributeKind Kind) { @@ -369,6 +370,12 @@ static Attribute::AttrKind fromRust(LLVMRustAttributeKind Kind) { return Attribute::Writable; case LLVMRustAttributeKind::DeadOnUnwind: return Attribute::DeadOnUnwind; + case LLVMRustAttributeKind::DeadOnReturn: +#if LLVM_VERSION_GE(21, 0) + return Attribute::DeadOnReturn; +#else + report_fatal_error("DeadOnReturn attribute requires LLVM 21 or later"); +#endif } report_fatal_error("bad LLVMRustAttributeKind"); } diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index 060799e981d..c310b99d535 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -146,7 +146,7 @@ impl<'ty> FieldInnerTy<'ty> { }; let path = &ty_path.path; - let ty = path.segments.iter().last().unwrap(); + let ty = path.segments.last().unwrap(); let syn::PathArguments::AngleBracketed(bracketed) = &ty.arguments else { panic!("expected bracketed generic arguments"); }; diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index d42c8b947a4..a7e7e9985f4 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1981,7 +1981,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { def_key.disambiguated_data.data = DefPathData::MacroNs(name); let def_id = id.to_def_id(); - self.tables.def_kind.set_some(def_id.index, DefKind::Macro(macro_kind)); + self.tables.def_kind.set_some(def_id.index, DefKind::Macro(macro_kind.into())); self.tables.proc_macro.set_some(def_id.index, macro_kind); self.encode_attrs(id); record!(self.tables.def_keys[def_id] <- def_key); diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 99174e4ad2f..1f7d142d330 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -11,7 +11,7 @@ use rustc_abi::{FieldIdx, ReprOptions, VariantIdx}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::svh::Svh; use rustc_hir::attrs::StrippedCfgItem; -use rustc_hir::def::{CtorKind, DefKind, DocLinkResMap}; +use rustc_hir::def::{CtorKind, DefKind, DocLinkResMap, MacroKinds}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIndex, DefPathHash, StableCrateId}; use rustc_hir::definitions::DefKey; use rustc_hir::lang_items::LangItem; diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 0671aa20399..2cb07a28a8a 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -81,7 +81,7 @@ impl FixedSizeEncoding for u64 { } macro_rules! fixed_size_enum { - ($ty:ty { $(($($pat:tt)*))* }) => { + ($ty:ty { $(($($pat:tt)*))* } $( unreachable { $(($($upat:tt)*))+ } )?) => { impl FixedSizeEncoding for Option<$ty> { type ByteArray = [u8;1]; @@ -103,12 +103,24 @@ macro_rules! fixed_size_enum { b[0] = match self { None => unreachable!(), $(Some($($pat)*) => 1 + ${index()},)* + $(Some($($($upat)*)|+) => unreachable!(),)? } } } } } +// Workaround; need const traits to construct bitflags in a const +macro_rules! const_macro_kinds { + ($($name:ident),+$(,)?) => (MacroKinds::from_bits_truncate($(MacroKinds::$name.bits())|+)) +} +const MACRO_KINDS_ATTR_BANG: MacroKinds = const_macro_kinds!(ATTR, BANG); +const MACRO_KINDS_DERIVE_BANG: MacroKinds = const_macro_kinds!(DERIVE, BANG); +const MACRO_KINDS_DERIVE_ATTR: MacroKinds = const_macro_kinds!(DERIVE, ATTR); +const MACRO_KINDS_DERIVE_ATTR_BANG: MacroKinds = const_macro_kinds!(DERIVE, ATTR, BANG); +// Ensure that we get a compilation error if MacroKinds gets extended without updating metadata. +const _: () = assert!(MACRO_KINDS_DERIVE_ATTR_BANG.is_all()); + fixed_size_enum! { DefKind { ( Mod ) @@ -151,10 +163,16 @@ fixed_size_enum! { ( Ctor(CtorOf::Struct, CtorKind::Const) ) ( Ctor(CtorOf::Variant, CtorKind::Fn) ) ( Ctor(CtorOf::Variant, CtorKind::Const) ) - ( Macro(MacroKind::Bang) ) - ( Macro(MacroKind::Attr) ) - ( Macro(MacroKind::Derive) ) + ( Macro(MacroKinds::BANG) ) + ( Macro(MacroKinds::ATTR) ) + ( Macro(MacroKinds::DERIVE) ) + ( Macro(MACRO_KINDS_ATTR_BANG) ) + ( Macro(MACRO_KINDS_DERIVE_ATTR) ) + ( Macro(MACRO_KINDS_DERIVE_BANG) ) + ( Macro(MACRO_KINDS_DERIVE_ATTR_BANG) ) ( SyntheticCoroutineBody ) + } unreachable { + ( Macro(_) ) } } diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index 52341df0740..2852c4cbd34 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -2,13 +2,12 @@ use std::borrow::Cow; use rustc_abi::Align; use rustc_ast::expand::autodiff_attrs::AutoDiffAttrs; -use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, OptimizeAttr}; +use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, Linkage, OptimizeAttr}; use rustc_hir::def_id::DefId; use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_span::Symbol; use rustc_target::spec::SanitizerSet; -use crate::mir::mono::Linkage; use crate::ty::{InstanceKind, TyCtxt}; impl<'tcx> TyCtxt<'tcx> { diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs index 785ddd1ee29..e3e04c9d180 100644 --- a/compiler/rustc_middle/src/middle/privacy.rs +++ b/compiler/rustc_middle/src/middle/privacy.rs @@ -181,11 +181,7 @@ impl EffectiveVisibilities { // nominal visibility. For some items nominal visibility doesn't make sense so we // don't check this condition for them. let is_impl = matches!(tcx.def_kind(def_id), DefKind::Impl { .. }); - let is_associated_item_in_trait_impl = tcx - .impl_of_assoc(def_id.to_def_id()) - .and_then(|impl_id| tcx.trait_id_of_impl(impl_id)) - .is_some(); - if !is_impl && !is_associated_item_in_trait_impl { + if !is_impl && tcx.trait_impl_of_assoc(def_id.to_def_id()).is_none() { let nominal_vis = tcx.visibility(def_id); if !nominal_vis.is_at_least(ev.reachable, tcx) { span_bug!( diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 3afd946b30a..440771b3d68 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -10,9 +10,8 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHas use rustc_data_structures::unord::UnordMap; use rustc_hashes::Hash128; use rustc_hir::ItemId; -use rustc_hir::attrs::InlineAttr; +use rustc_hir::attrs::{InlineAttr, Linkage}; use rustc_hir::def_id::{CrateNum, DefId, DefIdSet, LOCAL_CRATE}; -use rustc_index::Idx; use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_query_system::ich::StableHashingContext; use rustc_session::config::OptLevel; @@ -369,22 +368,6 @@ pub struct MonoItemData { pub size_estimate: usize, } -/// Specifies the linkage type for a `MonoItem`. -/// -/// See <https://llvm.org/docs/LangRef.html#linkage-types> for more details about these variants. -#[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)] -pub enum Linkage { - External, - AvailableExternally, - LinkOnceAny, - LinkOnceODR, - WeakAny, - WeakODR, - Internal, - ExternalWeak, - Common, -} - /// Specifies the symbol visibility with regards to dynamic linking. /// /// Visibility doesn't have any effect when linkage is internal. @@ -526,44 +509,50 @@ impl<'tcx> CodegenUnit<'tcx> { tcx: TyCtxt<'tcx>, ) -> Vec<(MonoItem<'tcx>, MonoItemData)> { // The codegen tests rely on items being process in the same order as - // they appear in the file, so for local items, we sort by node_id first + // they appear in the file, so for local items, we sort by span first #[derive(PartialEq, Eq, PartialOrd, Ord)] - struct ItemSortKey<'tcx>(Option<usize>, SymbolName<'tcx>); - + struct ItemSortKey<'tcx>(Option<Span>, SymbolName<'tcx>); + + // We only want to take HirIds of user-defines instances into account. + // The others don't matter for the codegen tests and can even make item + // order unstable. + fn local_item_id<'tcx>(item: MonoItem<'tcx>) -> Option<DefId> { + match item { + MonoItem::Fn(ref instance) => match instance.def { + InstanceKind::Item(def) => def.as_local().map(|_| def), + InstanceKind::VTableShim(..) + | InstanceKind::ReifyShim(..) + | InstanceKind::Intrinsic(..) + | InstanceKind::FnPtrShim(..) + | InstanceKind::Virtual(..) + | InstanceKind::ClosureOnceShim { .. } + | InstanceKind::ConstructCoroutineInClosureShim { .. } + | InstanceKind::DropGlue(..) + | InstanceKind::CloneShim(..) + | InstanceKind::ThreadLocalShim(..) + | InstanceKind::FnPtrAddrShim(..) + | InstanceKind::AsyncDropGlue(..) + | InstanceKind::FutureDropPollShim(..) + | InstanceKind::AsyncDropGlueCtorShim(..) => None, + }, + MonoItem::Static(def_id) => def_id.as_local().map(|_| def_id), + MonoItem::GlobalAsm(item_id) => Some(item_id.owner_id.def_id.to_def_id()), + } + } fn item_sort_key<'tcx>(tcx: TyCtxt<'tcx>, item: MonoItem<'tcx>) -> ItemSortKey<'tcx> { ItemSortKey( - match item { - MonoItem::Fn(ref instance) => { - match instance.def { - // We only want to take HirIds of user-defined - // instances into account. The others don't matter for - // the codegen tests and can even make item order - // unstable. - InstanceKind::Item(def) => def.as_local().map(Idx::index), - InstanceKind::VTableShim(..) - | InstanceKind::ReifyShim(..) - | InstanceKind::Intrinsic(..) - | InstanceKind::FnPtrShim(..) - | InstanceKind::Virtual(..) - | InstanceKind::ClosureOnceShim { .. } - | InstanceKind::ConstructCoroutineInClosureShim { .. } - | InstanceKind::DropGlue(..) - | InstanceKind::CloneShim(..) - | InstanceKind::ThreadLocalShim(..) - | InstanceKind::FnPtrAddrShim(..) - | InstanceKind::AsyncDropGlue(..) - | InstanceKind::FutureDropPollShim(..) - | InstanceKind::AsyncDropGlueCtorShim(..) => None, - } - } - MonoItem::Static(def_id) => def_id.as_local().map(Idx::index), - MonoItem::GlobalAsm(item_id) => Some(item_id.owner_id.def_id.index()), - }, + local_item_id(item) + .map(|def_id| tcx.def_span(def_id).find_ancestor_not_from_macro()) + .flatten(), item.symbol_name(tcx), ) } let mut items: Vec<_> = self.items().iter().map(|(&i, &data)| (i, data)).collect(); + if !tcx.sess.opts.unstable_opts.codegen_source_order { + // It's already deterministic, so we can just use it. + return items; + } items.sort_by_cached_key(|&(i, _)| item_sort_key(tcx, i)); items } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 84abcf550d2..d4d925d2057 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -1932,7 +1932,7 @@ fn pretty_print_const_value_tcx<'tcx>( let args = tcx.lift(args).unwrap(); let mut p = FmtPrinter::new(tcx, Namespace::ValueNS); p.print_alloc_ids = true; - p.print_value_path(variant_def.def_id, args)?; + p.pretty_print_value_path(variant_def.def_id, args)?; fmt.write_str(&p.into_buffer())?; match variant_def.ctor_kind() { @@ -1974,7 +1974,7 @@ fn pretty_print_const_value_tcx<'tcx>( (ConstValue::ZeroSized, ty::FnDef(d, s)) => { let mut p = FmtPrinter::new(tcx, Namespace::ValueNS); p.print_alloc_ids = true; - p.print_value_path(*d, s)?; + p.pretty_print_value_path(*d, s)?; fmt.write_str(&p.into_buffer())?; return Ok(()); } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 73e1661106e..e70c98ab704 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1925,21 +1925,50 @@ impl<'tcx> TyCtxt<'tcx> { self.impl_trait_ref(def_id).map(|tr| tr.skip_binder().def_id) } - /// If the given `DefId` is an associated item, returns the `DefId` of the parent trait or impl. - pub fn assoc_parent(self, def_id: DefId) -> Option<DefId> { - self.def_kind(def_id).is_assoc().then(|| self.parent(def_id)) + /// If the given `DefId` is an associated item, returns the `DefId` and `DefKind` of the parent trait or impl. + pub fn assoc_parent(self, def_id: DefId) -> Option<(DefId, DefKind)> { + if !self.def_kind(def_id).is_assoc() { + return None; + } + let parent = self.parent(def_id); + let def_kind = self.def_kind(parent); + Some((parent, def_kind)) } /// If the given `DefId` is an associated item of a trait, /// returns the `DefId` of the trait; otherwise, returns `None`. pub fn trait_of_assoc(self, def_id: DefId) -> Option<DefId> { - self.assoc_parent(def_id).filter(|id| self.def_kind(id) == DefKind::Trait) + match self.assoc_parent(def_id) { + Some((id, DefKind::Trait)) => Some(id), + _ => None, + } } /// If the given `DefId` is an associated item of an impl, /// returns the `DefId` of the impl; otherwise returns `None`. pub fn impl_of_assoc(self, def_id: DefId) -> Option<DefId> { - self.assoc_parent(def_id).filter(|id| matches!(self.def_kind(id), DefKind::Impl { .. })) + match self.assoc_parent(def_id) { + Some((id, DefKind::Impl { .. })) => Some(id), + _ => None, + } + } + + /// If the given `DefId` is an associated item of an inherent impl, + /// returns the `DefId` of the impl; otherwise, returns `None`. + pub fn inherent_impl_of_assoc(self, def_id: DefId) -> Option<DefId> { + match self.assoc_parent(def_id) { + Some((id, DefKind::Impl { of_trait: false })) => Some(id), + _ => None, + } + } + + /// If the given `DefId` is an associated item of a trait impl, + /// returns the `DefId` of the impl; otherwise, returns `None`. + pub fn trait_impl_of_assoc(self, def_id: DefId) -> Option<DefId> { + match self.assoc_parent(def_id) { + Some((id, DefKind::Impl { of_trait: true })) => Some(id), + _ => None, + } } pub fn is_exportable(self, def_id: DefId) -> bool { diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index efa017074db..e6feafea122 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -19,18 +19,16 @@ pub trait Print<'tcx, P> { fn print(&self, p: &mut P) -> Result<(), PrintError>; } -/// Interface for outputting user-facing "type-system entities" -/// (paths, types, lifetimes, constants, etc.) as a side-effect -/// (e.g. formatting, like `PrettyPrinter` implementors do) or by -/// constructing some alternative representation (e.g. an AST), -/// which the associated types allow passing through the methods. -/// -/// For pretty-printing/formatting in particular, see `PrettyPrinter`. -// -// FIXME(eddyb) find a better name; this is more general than "printing". +/// A trait that "prints" user-facing type system entities: paths, types, lifetimes, constants, +/// etc. "Printing" here means building up a representation of the entity's path, usually as a +/// `String` (e.g. "std::io::Read") or a `Vec<Symbol>` (e.g. `[sym::std, sym::io, sym::Read]`). The +/// representation is built up by appending one or more pieces. The specific details included in +/// the built-up representation depend on the purpose of the printer. The more advanced printers +/// also rely on the `PrettyPrinter` sub-trait. pub trait Printer<'tcx>: Sized { fn tcx<'a>(&'a self) -> TyCtxt<'tcx>; + /// Appends a representation of an entity with a normal path, e.g. "std::io::Read". fn print_def_path( &mut self, def_id: DefId, @@ -39,6 +37,7 @@ pub trait Printer<'tcx>: Sized { self.default_print_def_path(def_id, args) } + /// Like `print_def_path`, but for `DefPathData::Impl`. fn print_impl_path( &mut self, impl_def_id: DefId, @@ -64,48 +63,67 @@ pub trait Printer<'tcx>: Sized { self.default_print_impl_path(impl_def_id, self_ty, impl_trait_ref) } + /// Appends a representation of a region. fn print_region(&mut self, region: ty::Region<'tcx>) -> Result<(), PrintError>; + /// Appends a representation of a type. fn print_type(&mut self, ty: Ty<'tcx>) -> Result<(), PrintError>; + /// Appends a representation of a list of `PolyExistentialPredicate`s. fn print_dyn_existential( &mut self, predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>, ) -> Result<(), PrintError>; + /// Appends a representation of a const. fn print_const(&mut self, ct: ty::Const<'tcx>) -> Result<(), PrintError>; - fn path_crate(&mut self, cnum: CrateNum) -> Result<(), PrintError>; + /// Appends a representation of a crate name, e.g. `std`, or even ``. + fn print_crate_name(&mut self, cnum: CrateNum) -> Result<(), PrintError>; - fn path_qualified( + /// Appends a representation of a (full or partial) simple path, in two parts. `print_prefix`, + /// when called, appends the representation of the leading segments. The rest of the method + /// appends the representation of the final segment, the details of which are in + /// `disambiguated_data`. + /// + /// E.g. `std::io` + `Read` -> `std::io::Read`. + fn print_path_with_simple( &mut self, - self_ty: Ty<'tcx>, - trait_ref: Option<ty::TraitRef<'tcx>>, + print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, + disambiguated_data: &DisambiguatedDefPathData, ) -> Result<(), PrintError>; - fn path_append_impl( + /// Similar to `print_path_with_simple`, but the final segment is an `impl` segment. + /// + /// E.g. `slice` + `<impl [T]>` -> `slice::<impl [T]>`, which may then be further appended to, + /// giving a longer path representation such as `slice::<impl [T]>::to_vec_in::ConvertVec`. + fn print_path_with_impl( &mut self, print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, self_ty: Ty<'tcx>, trait_ref: Option<ty::TraitRef<'tcx>>, ) -> Result<(), PrintError>; - fn path_append( + /// Appends a representation of a path ending in generic args, in two parts. `print_prefix`, + /// when called, appends the leading segments. The rest of the method appends the + /// representation of the generic args. (Some printers choose to skip appending the generic + /// args.) + /// + /// E.g. `ImplementsTraitForUsize` + `<usize>` -> `ImplementsTraitForUsize<usize>`. + fn print_path_with_generic_args( &mut self, print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, - disambiguated_data: &DisambiguatedDefPathData, + args: &[GenericArg<'tcx>], ) -> Result<(), PrintError>; - fn path_generic_args( + /// Appends a representation of a qualified path segment, e.g. `<OsString as From<&T>>`. + /// If `trait_ref` is `None`, it may fall back to simpler forms, e.g. `<Vec<T>>` or just `Foo`. + fn print_path_with_qualified( &mut self, - print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, - args: &[GenericArg<'tcx>], + self_ty: Ty<'tcx>, + trait_ref: Option<ty::TraitRef<'tcx>>, ) -> Result<(), PrintError>; - fn should_truncate(&mut self) -> bool { - false - } - // Defaults (should not be overridden): #[instrument(skip(self), level = "debug")] @@ -120,7 +138,7 @@ pub trait Printer<'tcx>: Sized { match key.disambiguated_data.data { DefPathData::CrateRoot => { assert!(key.parent.is_none()); - self.path_crate(def_id.krate) + self.print_crate_name(def_id.krate) } DefPathData::Impl => self.print_impl_path(def_id, args), @@ -144,7 +162,7 @@ pub trait Printer<'tcx>: Sized { )) = self.tcx().coroutine_kind(def_id) && args.len() > parent_args.len() { - return self.path_generic_args( + return self.print_path_with_generic_args( |p| p.print_def_path(def_id, parent_args), &args[..parent_args.len() + 1][..1], ); @@ -166,7 +184,7 @@ pub trait Printer<'tcx>: Sized { _ => { if !generics.is_own_empty() && args.len() >= generics.count() { let args = generics.own_args_no_defaults(self.tcx(), args); - return self.path_generic_args( + return self.print_path_with_generic_args( |p| p.print_def_path(def_id, parent_args), args, ); @@ -182,7 +200,7 @@ pub trait Printer<'tcx>: Sized { && self.tcx().generics_of(parent_def_id).parent_count == 0; } - self.path_append( + self.print_path_with_simple( |p: &mut Self| { if trait_qualify_parent { let trait_ref = ty::TraitRef::new( @@ -190,7 +208,7 @@ pub trait Printer<'tcx>: Sized { parent_def_id, parent_args.iter().copied(), ); - p.path_qualified(trait_ref.self_ty(), Some(trait_ref)) + p.print_path_with_qualified(trait_ref.self_ty(), Some(trait_ref)) } else { p.print_def_path(parent_def_id, parent_args) } @@ -233,11 +251,15 @@ pub trait Printer<'tcx>: Sized { // If the impl is not co-located with either self-type or // trait-type, then fallback to a format that identifies // the module more clearly. - self.path_append_impl(|p| p.print_def_path(parent_def_id, &[]), self_ty, impl_trait_ref) + self.print_path_with_impl( + |p| p.print_def_path(parent_def_id, &[]), + self_ty, + impl_trait_ref, + ) } else { // Otherwise, try to give a good form that would be valid language // syntax. Preferably using associated item notation. - self.path_qualified(self_ty, impl_trait_ref) + self.print_path_with_qualified(self_ty, impl_trait_ref) } } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 67244e767cb..0a976f3a0ac 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -245,7 +245,7 @@ impl<'tcx> RegionHighlightMode<'tcx> { /// Trait for printers that pretty-print using `fmt::Write` to the printer. pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { /// Like `print_def_path` but for value paths. - fn print_value_path( + fn pretty_print_value_path( &mut self, def_id: DefId, args: &'tcx [GenericArg<'tcx>], @@ -253,7 +253,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { self.print_def_path(def_id, args) } - fn print_in_binder<T>(&mut self, value: &ty::Binder<'tcx, T>) -> Result<(), PrintError> + fn pretty_print_in_binder<T>(&mut self, value: &ty::Binder<'tcx, T>) -> Result<(), PrintError> where T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>, { @@ -333,6 +333,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { f: impl FnOnce(&mut Self) -> Result<(), PrintError>, ) -> Result<(), PrintError>; + fn should_truncate(&mut self) -> bool { + false + } + /// Returns `true` if the region should be printed in /// optional positions, e.g., `&'a T` or `dyn Tr + 'b`. /// This is typically the case for all non-`'_` regions. @@ -470,7 +474,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { // path to the crate followed by the path to the item within the crate. if let Some(cnum) = def_id.as_crate_root() { if cnum == LOCAL_CRATE { - self.path_crate(cnum)?; + self.print_crate_name(cnum)?; return Ok(true); } @@ -494,7 +498,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { // or avoid ending up with `ExternCrateSource::Extern`, // for the injected `std`/`core`. if span.is_dummy() { - self.path_crate(cnum)?; + self.print_crate_name(cnum)?; return Ok(true); } @@ -508,13 +512,13 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { return Ok(true); } (ExternCrateSource::Path, LOCAL_CRATE) => { - self.path_crate(cnum)?; + self.print_crate_name(cnum)?; return Ok(true); } _ => {} }, None => { - self.path_crate(cnum)?; + self.print_crate_name(cnum)?; return Ok(true); } } @@ -624,7 +628,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { return Ok(false); } callers.push(visible_parent); - // HACK(eddyb) this bypasses `path_append`'s prefix printing to avoid + // HACK(eddyb) this bypasses `print_path_with_simple`'s prefix printing to avoid // knowing ahead of time whether the entire path will succeed or not. // To support printers that do not implement `PrettyPrinter`, a `Vec` or // linked list on the stack would need to be built, before any printing. @@ -633,11 +637,14 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { true => {} } callers.pop(); - self.path_append(|_| Ok(()), &DisambiguatedDefPathData { data, disambiguator: 0 })?; + self.print_path_with_simple( + |_| Ok(()), + &DisambiguatedDefPathData { data, disambiguator: 0 }, + )?; Ok(true) } - fn pretty_path_qualified( + fn pretty_print_path_with_qualified( &mut self, self_ty: Ty<'tcx>, trait_ref: Option<ty::TraitRef<'tcx>>, @@ -672,7 +679,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { }) } - fn pretty_path_append_impl( + fn pretty_print_path_with_impl( &mut self, print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, self_ty: Ty<'tcx>, @@ -739,7 +746,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { } sig.print(self)?; write!(self, " {{")?; - self.print_value_path(def_id, args)?; + self.pretty_print_value_path(def_id, args)?; write!(self, "}}")?; } } @@ -1308,10 +1315,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { alias_ty: ty::AliasTerm<'tcx>, ) -> Result<(), PrintError> { let def_key = self.tcx().def_key(alias_ty.def_id); - self.path_generic_args( + self.print_path_with_generic_args( |p| { - p.path_append( - |p| p.path_qualified(alias_ty.self_ty(), None), + p.print_path_with_simple( + |p| p.print_path_with_qualified(alias_ty.self_ty(), None), &def_key.disambiguated_data, ) }, @@ -1386,7 +1393,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { if let ty::Tuple(tys) = principal.args.type_at(0).kind() { let mut projections = predicates.projection_bounds(); if let (Some(proj), None) = (projections.next(), projections.next()) { - p.pretty_fn_sig( + p.pretty_print_fn_sig( tys, false, proj.skip_binder().term.as_type().expect("Return type was a const"), @@ -1396,7 +1403,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { } } - // HACK(eddyb) this duplicates `FmtPrinter`'s `path_generic_args`, + // HACK(eddyb) this duplicates `FmtPrinter`'s `print_path_with_generic_args`, // in order to place the projections inside the `<...>`. if !resugared { let principal_with_self = @@ -1488,7 +1495,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { Ok(()) } - fn pretty_fn_sig( + fn pretty_print_fn_sig( &mut self, inputs: &[Ty<'tcx>], c_variadic: bool, @@ -1525,7 +1532,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args }) => { match self.tcx().def_kind(def) { DefKind::Const | DefKind::AssocConst => { - self.print_value_path(def, args)?; + self.pretty_print_value_path(def, args)?; } DefKind::AnonConst => { if def.is_local() @@ -1534,13 +1541,13 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { { write!(self, "{snip}")?; } else { - // Do not call `print_value_path` as if a parent of this anon const is - // an impl it will attempt to print out the impl trait ref i.e. `<T as - // Trait>::{constant#0}`. This would cause printing to enter an - // infinite recursion if the anon const is in the self type i.e. - // `impl<T: Default> Default for [T; 32 - 1 - 1 - 1] {` where we would - // try to print - // `<[T; /* print constant#0 again */] as // Default>::{constant#0}`. + // Do not call `pretty_print_value_path` as if a parent of this anon + // const is an impl it will attempt to print out the impl trait ref + // i.e. `<T as Trait>::{constant#0}`. This would cause printing to + // enter an infinite recursion if the anon const is in the self type + // i.e. `impl<T: Default> Default for [T; 32 - 1 - 1 - 1] {` where we + // would try to print `<[T; /* print constant#0 again */] as // + // Default>::{constant#0}`. write!( self, "{}::{}", @@ -1742,7 +1749,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { self.tcx().try_get_global_alloc(prov.alloc_id()) { self.typed_value( - |this| this.print_value_path(instance.def_id(), instance.args), + |this| this.pretty_print_value_path(instance.def_id(), instance.args), |this| this.print_type(ty), " as ", )?; @@ -1936,7 +1943,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { let variant_idx = contents.variant.expect("destructed const of adt without variant idx"); let variant_def = &def.variant(variant_idx); - self.print_value_path(variant_def.def_id, args)?; + self.pretty_print_value_path(variant_def.def_id, args)?; match variant_def.ctor_kind() { Some(CtorKind::Const) => {} Some(CtorKind::Fn) => { @@ -1972,7 +1979,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { } (_, ty::FnDef(def_id, args)) => { // Never allowed today, but we still encounter them in invalid const args. - self.print_value_path(def_id, args)?; + self.pretty_print_value_path(def_id, args)?; return Ok(()); } // FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading @@ -1993,7 +2000,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { Ok(()) } - fn pretty_closure_as_impl( + fn pretty_print_closure_as_impl( &mut self, closure: ty::ClosureArgs<TyCtxt<'tcx>>, ) -> Result<(), PrintError> { @@ -2131,8 +2138,6 @@ impl<'a, 'tcx> FmtPrinter<'a, 'tcx> { } } -// HACK(eddyb) get rid of `def_path_str` and/or pass `Namespace` explicitly always -// (but also some things just print a `DefId` generally so maybe we need this?) fn guess_def_namespace(tcx: TyCtxt<'_>, def_id: DefId) -> Namespace { match tcx.def_key(def_id).disambiguated_data.data { DefPathData::TypeNs(..) | DefPathData::CrateRoot | DefPathData::OpaqueTy => { @@ -2157,6 +2162,7 @@ impl<'t> TyCtxt<'t> { self.def_path_str_with_args(def_id, &[]) } + /// For this one we determine the appropriate namespace for the `def_id`. pub fn def_path_str_with_args( self, def_id: impl IntoQueryParam<DefId>, @@ -2169,16 +2175,17 @@ impl<'t> TyCtxt<'t> { FmtPrinter::print_string(self, ns, |p| p.print_def_path(def_id, args)).unwrap() } + /// For this one we always use value namespace. pub fn value_path_str_with_args( self, def_id: impl IntoQueryParam<DefId>, args: &'t [GenericArg<'t>], ) -> String { let def_id = def_id.into_query_param(); - let ns = guess_def_namespace(self, def_id); + let ns = Namespace::ValueNS; debug!("value_path_str: def_id={:?}, ns={:?}", def_id, ns); - FmtPrinter::print_string(self, ns, |p| p.print_value_path(def_id, args)).unwrap() + FmtPrinter::print_string(self, ns, |p| p.print_def_path(def_id, args)).unwrap() } } @@ -2230,7 +2237,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { self.print_def_path(parent_def_id, &[])?; - // HACK(eddyb) copy of `path_append` to avoid + // HACK(eddyb) copy of `print_path_with_simple` to avoid // constructing a `DisambiguatedDefPathData`. if !self.empty_path { write!(self, "::")?; @@ -2295,10 +2302,6 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { } } - fn should_truncate(&mut self) -> bool { - !self.type_length_limit.value_within_limit(self.printed_type_count) - } - fn print_dyn_existential( &mut self, predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>, @@ -2310,7 +2313,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { self.pretty_print_const(ct, false) } - fn path_crate(&mut self, cnum: CrateNum) -> Result<(), PrintError> { + fn print_crate_name(&mut self, cnum: CrateNum) -> Result<(), PrintError> { self.empty_path = true; if cnum == LOCAL_CRATE { if self.tcx.sess.at_least_rust_2018() { @@ -2327,23 +2330,23 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { Ok(()) } - fn path_qualified( + fn print_path_with_qualified( &mut self, self_ty: Ty<'tcx>, trait_ref: Option<ty::TraitRef<'tcx>>, ) -> Result<(), PrintError> { - self.pretty_path_qualified(self_ty, trait_ref)?; + self.pretty_print_path_with_qualified(self_ty, trait_ref)?; self.empty_path = false; Ok(()) } - fn path_append_impl( + fn print_path_with_impl( &mut self, print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, self_ty: Ty<'tcx>, trait_ref: Option<ty::TraitRef<'tcx>>, ) -> Result<(), PrintError> { - self.pretty_path_append_impl( + self.pretty_print_path_with_impl( |p| { print_prefix(p)?; if !p.empty_path { @@ -2359,7 +2362,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { Ok(()) } - fn path_append( + fn print_path_with_simple( &mut self, print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, disambiguated_data: &DisambiguatedDefPathData, @@ -2390,7 +2393,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { Ok(()) } - fn path_generic_args( + fn print_path_with_generic_args( &mut self, print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, args: &[GenericArg<'tcx>], @@ -2421,7 +2424,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { self.0.const_infer_name_resolver.as_ref().and_then(|func| func(id)) } - fn print_value_path( + fn pretty_print_value_path( &mut self, def_id: DefId, args: &'tcx [GenericArg<'tcx>], @@ -2433,7 +2436,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { Ok(()) } - fn print_in_binder<T>(&mut self, value: &ty::Binder<'tcx, T>) -> Result<(), PrintError> + fn pretty_print_in_binder<T>(&mut self, value: &ty::Binder<'tcx, T>) -> Result<(), PrintError> where T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>, { @@ -2487,6 +2490,10 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { Ok(()) } + fn should_truncate(&mut self) -> bool { + !self.type_length_limit.value_within_limit(self.printed_type_count) + } + fn should_print_region(&self, region: ty::Region<'tcx>) -> bool { let highlight = self.region_highlight_mode; if highlight.region_highlighted(region).is_some() { @@ -2892,7 +2899,7 @@ where T: Print<'tcx, P> + TypeFoldable<TyCtxt<'tcx>>, { fn print(&self, p: &mut P) -> Result<(), PrintError> { - p.print_in_binder(self) + p.pretty_print_in_binder(self) } } @@ -3090,7 +3097,7 @@ define_print! { } write!(p, "fn")?; - p.pretty_fn_sig(self.inputs(), self.c_variadic, self.output())?; + p.pretty_print_fn_sig(self.inputs(), self.c_variadic, self.output())?; } ty::TraitRef<'tcx> { @@ -3225,7 +3232,7 @@ define_print! { // The args don't contain the self ty (as it has been erased) but the corresp. // generics do as the trait always has a self ty param. We need to offset. let args = &self.args[p.tcx().generics_of(self.def_id).parent_count - 1..]; - p.path_generic_args(|p| write!(p, "{name}"), args)?; + p.print_path_with_generic_args(|p| write!(p, "{name}"), args)?; write!(p, " = ")?; self.term.print(p)?; } @@ -3314,7 +3321,7 @@ define_print_and_forward_display! { } PrintClosureAsImpl<'tcx> { - p.pretty_closure_as_impl(self.closure)?; + p.pretty_print_closure_as_impl(self.closure)?; } ty::ParamTy { diff --git a/compiler/rustc_mir_transform/src/check_call_recursion.rs b/compiler/rustc_mir_transform/src/check_call_recursion.rs index 6d61ac2dd80..a9acb1da5a3 100644 --- a/compiler/rustc_mir_transform/src/check_call_recursion.rs +++ b/compiler/rustc_mir_transform/src/check_call_recursion.rs @@ -43,8 +43,8 @@ impl<'tcx> MirLint<'tcx> for CheckDropRecursion { // First check if `body` is an `fn drop()` of `Drop` if let DefKind::AssocFn = tcx.def_kind(def_id) - && let Some(trait_ref) = - tcx.impl_of_assoc(def_id.to_def_id()).and_then(|def_id| tcx.impl_trait_ref(def_id)) + && let Some(impl_id) = tcx.trait_impl_of_assoc(def_id.to_def_id()) + && let trait_ref = tcx.impl_trait_ref(impl_id).unwrap() && tcx.is_lang_item(trait_ref.instantiate_identity().def_id, LangItem::Drop) // avoid erroneous `Drop` impls from causing ICEs below && let sig = tcx.fn_sig(def_id).instantiate_identity() diff --git a/compiler/rustc_mir_transform/src/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs index dcb812c7899..100104e9de0 100644 --- a/compiler/rustc_mir_transform/src/check_packed_ref.rs +++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs @@ -40,7 +40,7 @@ impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> { if context.is_borrow() && util::is_disaligned(self.tcx, self.body, self.typing_env, *place) { let def_id = self.body.source.instance.def_id(); - if let Some(impl_def_id) = self.tcx.impl_of_assoc(def_id) + if let Some(impl_def_id) = self.tcx.trait_impl_of_assoc(def_id) && self.tcx.is_builtin_derived(impl_def_id) { // If we ever reach here it means that the generated derive diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index c687036f544..c6760b3583f 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -75,7 +75,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body< build_call_shim(tcx, instance, Some(adjustment), CallKind::Direct(def_id)) } ty::InstanceKind::FnPtrShim(def_id, ty) => { - let trait_ = tcx.trait_of_assoc(def_id).unwrap(); + let trait_ = tcx.parent(def_id); // Supports `Fn` or `async Fn` traits. let adjustment = match tcx .fn_trait_kind_from_def_id(trait_) diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index d76b27d9970..628ea2b63de 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -104,7 +104,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::sync; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_hir::LangItem; -use rustc_hir::attrs::InlineAttr; +use rustc_hir::attrs::{InlineAttr, Linkage}; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, DefIdSet, LOCAL_CRATE}; use rustc_hir::definitions::DefPathDataName; @@ -112,7 +112,7 @@ use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel}; use rustc_middle::mir::mono::{ - CodegenUnit, CodegenUnitNameBuilder, InstantiationMode, Linkage, MonoItem, MonoItemData, + CodegenUnit, CodegenUnitNameBuilder, InstantiationMode, MonoItem, MonoItemData, MonoItemPartitions, Visibility, }; use rustc_middle::ty::print::{characteristic_def_id_of_type, with_no_trimmed_paths}; @@ -650,17 +650,18 @@ fn characteristic_def_id_of_mono_item<'tcx>( // its self-type. If the self-type does not provide a characteristic // DefId, we use the location of the impl after all. - if tcx.trait_of_assoc(def_id).is_some() { + let assoc_parent = tcx.assoc_parent(def_id); + + if let Some((_, DefKind::Trait)) = assoc_parent { let self_ty = instance.args.type_at(0); // This is a default implementation of a trait method. return characteristic_def_id_of_type(self_ty).or(Some(def_id)); } - if let Some(impl_def_id) = tcx.impl_of_assoc(def_id) { - if tcx.sess.opts.incremental.is_some() - && tcx - .trait_id_of_impl(impl_def_id) - .is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::Drop)) + if let Some((impl_def_id, DefKind::Impl { of_trait })) = assoc_parent { + if of_trait + && tcx.sess.opts.incremental.is_some() + && tcx.is_lang_item(tcx.trait_id_of_impl(impl_def_id).unwrap(), LangItem::Drop) { // Put `Drop::drop` into the same cgu as `drop_in_place` // since `drop_in_place` is the only thing that can diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 3a21eea3d0a..9e0075c21b9 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -862,8 +862,8 @@ parse_too_many_hashes = too many `#` symbols: raw strings may be delimited by up parse_too_short_hex_escape = numeric character escape is too short -parse_trailing_vert_not_allowed = a trailing `|` is not allowed in an or-pattern - .suggestion = remove the `{$token}` +parse_trailing_vert_not_allowed = a trailing `{$token}` is not allowed in an or-pattern +parse_trailing_vert_not_allowed_suggestion = remove the `{$token}` parse_trait_alias_cannot_be_auto = trait aliases cannot be `auto` parse_trait_alias_cannot_be_const = trait aliases cannot be `const` diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index a07d0606fd0..a105dd1909e 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2661,7 +2661,7 @@ pub(crate) enum TopLevelOrPatternNotAllowedSugg { parse_sugg_remove_leading_vert_in_pattern, code = "", applicability = "machine-applicable", - style = "verbose" + style = "tool-only" )] RemoveLeadingVert { #[primary_span] @@ -2694,12 +2694,25 @@ pub(crate) struct UnexpectedVertVertInPattern { pub start: Option<Span>, } +#[derive(Subdiagnostic)] +#[suggestion( + parse_trailing_vert_not_allowed, + code = "", + applicability = "machine-applicable", + style = "tool-only" +)] +pub(crate) struct TrailingVertSuggestion { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(parse_trailing_vert_not_allowed)] pub(crate) struct TrailingVertNotAllowed { #[primary_span] - #[suggestion(code = "", applicability = "machine-applicable", style = "verbose")] pub span: Span, + #[subdiagnostic] + pub suggestion: TrailingVertSuggestion, #[label(parse_label_while_parsing_or_pattern_here)] pub start: Option<Span>, pub token: Token, diff --git a/compiler/rustc_parse/src/parser/cfg_select.rs b/compiler/rustc_parse/src/parser/cfg_select.rs index 2c6fb224d70..08a71db4de8 100644 --- a/compiler/rustc_parse/src/parser/cfg_select.rs +++ b/compiler/rustc_parse/src/parser/cfg_select.rs @@ -1,11 +1,12 @@ use rustc_ast::token::Token; use rustc_ast::tokenstream::{TokenStream, TokenTree}; +use rustc_ast::util::classify; use rustc_ast::{MetaItemInner, token}; use rustc_errors::PResult; use rustc_span::Span; use crate::exp; -use crate::parser::Parser; +use crate::parser::{AttrWrapper, ForceCollect, Parser, Restrictions, Trailing, UsePreAttrPos}; pub enum CfgSelectPredicate { Cfg(MetaItemInner), @@ -23,19 +24,26 @@ pub struct CfgSelectBranches { pub unreachable: Vec<(CfgSelectPredicate, TokenStream, Span)>, } -/// Parses a `TokenTree` that must be of the form `{ /* ... */ }`, and returns a `TokenStream` where -/// the surrounding braces are stripped. +/// Parses a `TokenTree` consisting either of `{ /* ... */ }` (and strip the braces) or an +/// expression followed by a comma (and strip the comma). fn parse_token_tree<'a>(p: &mut Parser<'a>) -> PResult<'a, TokenStream> { - // Generate an error if the `=>` is not followed by `{`. - if p.token != token::OpenBrace { - p.expect(exp!(OpenBrace))?; + if p.token == token::OpenBrace { + // Strip the outer '{' and '}'. + match p.parse_token_tree() { + TokenTree::Token(..) => unreachable!("because of the expect above"), + TokenTree::Delimited(.., tts) => return Ok(tts), + } } - - // Strip the outer '{' and '}'. - match p.parse_token_tree() { - TokenTree::Token(..) => unreachable!("because of the expect above"), - TokenTree::Delimited(.., tts) => Ok(tts), + let expr = p.collect_tokens(None, AttrWrapper::empty(), ForceCollect::Yes, |p, _| { + p.parse_expr_res(Restrictions::STMT_EXPR, AttrWrapper::empty()) + .map(|(expr, _)| (expr, Trailing::No, UsePreAttrPos::No)) + })?; + if !classify::expr_is_complete(&expr) && p.token != token::CloseBrace && p.token != token::Eof { + p.expect(exp!(Comma))?; + } else { + let _ = p.eat(exp!(Comma)); } + Ok(TokenStream::from_ast(&expr)) } pub fn parse_cfg_select<'a>(p: &mut Parser<'a>) -> PResult<'a, CfgSelectBranches> { diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index a415849b915..9754691a0b9 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -24,10 +24,10 @@ use crate::errors::{ GenericArgsInPatRequireTurbofishSyntax, InclusiveRangeExtraEquals, InclusiveRangeMatchArrow, InclusiveRangeNoEnd, InvalidMutInPattern, ParenRangeSuggestion, PatternOnWrongSideOfAt, RemoveLet, RepeatedMutInPattern, SwitchRefBoxOrder, TopLevelOrPatternNotAllowed, - TopLevelOrPatternNotAllowedSugg, TrailingVertNotAllowed, UnexpectedExpressionInPattern, - UnexpectedExpressionInPatternSugg, UnexpectedLifetimeInPattern, UnexpectedParenInRangePat, - UnexpectedParenInRangePatSugg, UnexpectedVertVertBeforeFunctionParam, - UnexpectedVertVertInPattern, WrapInParens, + TopLevelOrPatternNotAllowedSugg, TrailingVertNotAllowed, TrailingVertSuggestion, + UnexpectedExpressionInPattern, UnexpectedExpressionInPatternSugg, UnexpectedLifetimeInPattern, + UnexpectedParenInRangePat, UnexpectedParenInRangePatSugg, + UnexpectedVertVertBeforeFunctionParam, UnexpectedVertVertInPattern, WrapInParens, }; use crate::parser::expr::{DestructuredFloat, could_be_unclosed_char_literal}; use crate::{exp, maybe_recover_from_interpolated_ty_qpath}; @@ -267,10 +267,9 @@ impl<'a> Parser<'a> { if let PatKind::Or(pats) = &pat.kind { let span = pat.span; - let sub = if pats.len() == 1 { - Some(TopLevelOrPatternNotAllowedSugg::RemoveLeadingVert { - span: span.with_hi(span.lo() + BytePos(1)), - }) + let sub = if let [_] = &pats[..] { + let span = span.with_hi(span.lo() + BytePos(1)); + Some(TopLevelOrPatternNotAllowedSugg::RemoveLeadingVert { span }) } else { Some(TopLevelOrPatternNotAllowedSugg::WrapInParens { span, @@ -362,6 +361,9 @@ impl<'a> Parser<'a> { self.dcx().emit_err(TrailingVertNotAllowed { span: self.token.span, start: lo, + suggestion: TrailingVertSuggestion { + span: self.prev_token.span.shrink_to_hi().with_hi(self.token.span.hi()), + }, token: self.token, note_double_vert: self.token.kind == token::OrOr, }); diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index b5031f5d02e..7481b0ea960 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -13,22 +13,6 @@ passes_abi_ne = passes_abi_of = fn_abi_of({$fn_name}) = {$fn_abi} -passes_align_attr_application = - `#[rustc_align(...)]` should be applied to a function item - .label = not a function item - -passes_align_on_fields = - attribute should be applied to a function or method - .warn = {-passes_previously_accepted} - -passes_align_should_be_repr_align = - `#[rustc_align(...)]` is not supported on {$item} items - .suggestion = use `#[repr(align(...))]` instead - -passes_allow_incoherent_impl = - `rustc_allow_incoherent_impl` attribute should be applied to impl items - .label = the only currently supported targets are inherent methods - passes_macro_only_attribute = attribute should be applied to a macro .label = not a macro @@ -78,18 +62,10 @@ passes_change_fields_to_be_of_unit_type = *[other] fields } -passes_cold = - {passes_should_be_applied_to_fn} - .warn = {-passes_previously_accepted} - .label = {passes_should_be_applied_to_fn.label} - passes_collapse_debuginfo = `collapse_debuginfo` attribute should be applied to macro definitions .label = not a macro definition -passes_confusables = attribute should be applied to an inherent method - .label = not an inherent method - passes_const_continue_attr = `#[const_continue]` should be applied to a break expression .label = not a break expression @@ -98,16 +74,6 @@ passes_const_stable_not_stable = attribute `#[rustc_const_stable]` can only be applied to functions that are declared `#[stable]` .label = attribute specified here -passes_coroutine_on_non_closure = - attribute should be applied to closures - .label = not a closure - -passes_coverage_attribute_not_allowed = - coverage attribute not allowed here - .not_fn_impl_mod = not a function, impl block, or module - .no_body = function has no body - .help = coverage attribute can be applied to a function (with body), impl block, or module - passes_dead_codes = { $multiple -> *[true] multiple {$descr}s are @@ -129,9 +95,6 @@ passes_debug_visualizer_placement = passes_debug_visualizer_unreadable = couldn't read {$file}: {$error} -passes_deprecated = - attribute is ignored here - passes_deprecated_annotation_has_no_effect = this `#[deprecated]` annotation has no effect .suggestion = remove the unnecessary deprecation attribute @@ -304,10 +267,6 @@ passes_duplicate_lang_item_crate_depends = passes_enum_variant_same_name = it is impossible to refer to the {$dead_descr} `{$dead_name}` because it is shadowed by this enum variant with the same name -passes_export_name = - attribute should be applied to a free function, impl method or static - .label = not a free function, impl method or static - passes_extern_main = the `main` function cannot be declared in an `extern` block @@ -317,21 +276,10 @@ passes_feature_previously_declared = passes_feature_stable_twice = feature `{$feature}` is declared stable since {$since}, but was previously declared stable since {$prev_since} -passes_ffi_const_invalid_target = - `#[ffi_const]` may only be used on foreign functions - -passes_ffi_pure_invalid_target = - `#[ffi_pure]` may only be used on foreign functions - passes_has_incoherent_inherent_impl = `rustc_has_incoherent_inherent_impls` attribute should be applied to types or traits .label = only adts, extern types and traits are supported -passes_ignored_attr = - `#[{$sym}]` is ignored on struct fields and match arms - .warn = {-passes_previously_accepted} - .note = {-passes_see_issue(issue: "80564")} - passes_ignored_attr_with_macro = `#[{$sym}]` is ignored on struct fields, match arms and macro defs .warn = {-passes_previously_accepted} @@ -373,22 +321,10 @@ passes_incorrect_target = passes_ineffective_unstable_impl = an `#[unstable]` annotation here has no effect .note = see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information -passes_inline_ignored_constants = - `#[inline]` is ignored on constants - .warn = {-passes_previously_accepted} - .note = {-passes_see_issue(issue: "65833")} - passes_inline_ignored_for_exported = `#[inline]` is ignored on externally exported functions .help = externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]` -passes_inline_ignored_function_prototype = - `#[inline]` is ignored on function prototypes - -passes_inline_not_fn_or_closure = - attribute should be applied to function or closure - .label = not a function or closure - passes_inner_crate_level_attr = crate-level attribute should be in the root module @@ -438,25 +374,6 @@ passes_link = .warn = {-passes_previously_accepted} .label = not an `extern` block -passes_link_name = - attribute should be applied to a foreign function or static - .warn = {-passes_previously_accepted} - .label = not a foreign function or static - .help = try `#[link(name = "{$value}")]` instead - -passes_link_ordinal = - attribute should be applied to a foreign function or static - .label = not a foreign function or static - -passes_link_section = - attribute should be applied to a function or static - .warn = {-passes_previously_accepted} - .label = not a function or static - -passes_linkage = - attribute should be applied to a function or static - .label = not a function definition or static - passes_loop_match_attr = `#[loop_match]` should be applied to a loop .label = not a loop @@ -468,9 +385,6 @@ passes_macro_export_on_decl_macro = `#[macro_export]` has no effect on declarative macro definitions .note = declarative macros follow the same exporting rules as regular items -passes_macro_use = - `#[{$name}]` only has an effect on `extern crate` and modules - passes_may_dangle = `#[may_dangle]` must be applied to a lifetime or type generic parameter in `Drop` impl @@ -509,7 +423,8 @@ passes_must_not_suspend = .label = is not a struct, enum, union, or trait passes_must_use_no_effect = - `#[must_use]` has no effect when applied to {$article} {$target} + `#[must_use]` has no effect when applied to {$target} + .suggestion = remove the attribute passes_no_link = attribute should be applied to an `extern crate` item @@ -529,18 +444,6 @@ passes_no_main_function = .teach_note = If you don't know the basics of Rust, you can go look to the Rust Book to get started: https://doc.rust-lang.org/book/ .non_function_main = non-function item at `crate::main` is found -passes_no_mangle = - attribute should be applied to a free function, impl method or static - .warn = {-passes_previously_accepted} - .label = not a free function, impl method or static - -passes_no_mangle_foreign = - `#[no_mangle]` has no effect on a foreign {$foreign_item_kind} - .warn = {-passes_previously_accepted} - .label = foreign {$foreign_item_kind} - .note = symbol names in extern blocks are not mangled - .suggestion = remove this attribute - passes_no_sanitize = `#[no_sanitize({$attr_str})]` should be applied to {$accepted_kind} .label = not {$accepted_kind} @@ -556,19 +459,6 @@ passes_non_exported_macro_invalid_attrs = passes_object_lifetime_err = {$repr} -passes_only_has_effect_on = - `#[{$attr_name}]` only has an effect on {$target_name -> - [function] functions - [module] modules - [trait_implementation_block] trait implementation blocks - [inherent_implementation_block] inherent implementation blocks - *[unspecified] (unspecified--this is a compiler bug) - } - -passes_optimize_invalid_target = - attribute applied to an invalid target - .label = invalid target - passes_outer_crate_level_attr = crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` @@ -584,10 +474,6 @@ passes_parent_info = *[other] {$descr}s } in this {$parent_descr} -passes_pass_by_value = - `pass_by_value` attribute should be applied to a struct, enum or type alias - .label = is not a struct, enum or type alias - passes_proc_macro_bad_sig = {$kind} has incorrect signature passes_remove_fields = @@ -604,7 +490,7 @@ passes_repr_align_greater_than_target_max = .note = `isize::MAX` is {$size} for the current target passes_repr_align_should_be_align = - `#[repr(align(...))]` is not supported on {$item} items + `#[repr(align(...))]` is not supported on {$item} .help = use `#[rustc_align(...)]` instead passes_repr_conflicting = @@ -619,18 +505,10 @@ passes_rustc_const_stable_indirect_pairing = passes_rustc_dirty_clean = attribute requires -Z query-dep-graph to be enabled -passes_rustc_force_inline = - attribute should be applied to a function - .label = not a function definition - passes_rustc_force_inline_coro = attribute cannot be applied to a `async`, `gen` or `async gen` function .label = `async`, `gen` or `async gen` function -passes_rustc_layout_scalar_valid_range_not_struct = - attribute should be applied to a struct - .label = not a struct - passes_rustc_legacy_const_generics_index = #[rustc_legacy_const_generics] must have one index for each generic parameter .label = generic parameters @@ -664,14 +542,6 @@ passes_rustc_pub_transparent = attribute should be applied to `#[repr(transparent)]` types .label = not a `#[repr(transparent)]` type -passes_rustc_std_internal_symbol = - attribute should be applied to functions or statics - .label = not a function or static - -passes_rustc_unstable_feature_bound = - attribute should be applied to `impl`, trait or free function - .label = not an `impl`, trait or free function - passes_should_be_applied_to_fn = attribute should be applied to a function definition .label = {$on_crate -> @@ -683,24 +553,12 @@ passes_should_be_applied_to_static = attribute should be applied to a static .label = not a static -passes_should_be_applied_to_struct_enum = - attribute should be applied to a struct or enum - .label = not a struct or enum - passes_should_be_applied_to_trait = attribute should be applied to a trait .label = not a trait -passes_stability_promotable = - attribute cannot be applied to an expression - passes_string_interpolation_only_works = string interpolation only works in `format!` invocations -passes_target_feature_on_statement = - {passes_should_be_applied_to_fn} - .warn = {-passes_previously_accepted} - .label = {passes_should_be_applied_to_fn.label} - passes_trait_impl_const_stability_mismatch = const stability on the impl does not match the const stability on the trait passes_trait_impl_const_stability_mismatch_impl_stable = this impl is (implicitly) stable... passes_trait_impl_const_stability_mismatch_impl_unstable = this impl is unstable... @@ -825,11 +683,6 @@ passes_unused_variable_try_prefix = unused variable: `{$name}` .label = unused variable .suggestion = if this is intentional, prefix it with an underscore - -passes_used_static = - attribute must be applied to a `static` variable - .label = but this is a {$target} - passes_useless_assignment = useless assignment of {$is_field_assign -> [true] field diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 3695537d28a..0e28c51e981 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -10,7 +10,7 @@ use std::collections::hash_map::Entry; use std::slice; use rustc_abi::{Align, ExternAbi, Size}; -use rustc_ast::{AttrStyle, LitKind, MetaItemInner, MetaItemKind, ast, join_path_syms}; +use rustc_ast::{AttrStyle, LitKind, MetaItemInner, MetaItemKind, ast}; use rustc_attr_parsing::{AttributeParser, Late}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Applicability, DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey}; @@ -40,7 +40,6 @@ use rustc_session::lint; use rustc_session::lint::builtin::{ CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, INVALID_MACRO_EXPORT_ARGUMENTS, MALFORMED_DIAGNOSTIC_ATTRIBUTES, MISPLACED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES, - USELESS_DEPRECATED, }; use rustc_session::parse::feature_err; use rustc_span::edition::Edition; @@ -50,7 +49,6 @@ use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs}; use rustc_trait_selection::traits::ObligationCtxt; use tracing::debug; -use crate::errors::AlignOnFields; use crate::{errors, fluent_generated as fluent}; #[derive(LintDiagnostic)] @@ -134,56 +132,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Attribute::Parsed(AttributeKind::ProcMacroAttribute(_)) => { self.check_proc_macro(hir_id, target, ProcMacroKind::Attribute); } - Attribute::Parsed(AttributeKind::ProcMacroDerive { span: attr_span, .. }) => { - self.check_generic_attr( - hir_id, - sym::proc_macro_derive, - *attr_span, - target, - Target::Fn, - ); + Attribute::Parsed(AttributeKind::ProcMacroDerive { .. }) => { self.check_proc_macro(hir_id, target, ProcMacroKind::Derive) } - Attribute::Parsed( - AttributeKind::SkipDuringMethodDispatch { span: attr_span, .. } - | AttributeKind::Coinductive(attr_span) - | AttributeKind::ConstTrait(attr_span) - | AttributeKind::DenyExplicitImpl(attr_span) - | AttributeKind::DoNotImplementViaObject(attr_span), - ) => { - self.check_must_be_applied_to_trait(*attr_span, span, target); - } - &Attribute::Parsed( - AttributeKind::SpecializationTrait(attr_span) - | AttributeKind::UnsafeSpecializationMarker(attr_span) - | AttributeKind::ParenSugar(attr_span), - ) => { - // FIXME: more validation is needed - self.check_must_be_applied_to_trait(attr_span, span, target); - } &Attribute::Parsed(AttributeKind::TypeConst(attr_span)) => { self.check_type_const(hir_id, attr_span, target) } - &Attribute::Parsed(AttributeKind::Marker(attr_span)) => { - self.check_marker(hir_id, attr_span, span, target) - } - Attribute::Parsed(AttributeKind::Fundamental | AttributeKind::CoherenceIsCore) => { - // FIXME: add validation - } - &Attribute::Parsed(AttributeKind::AllowIncoherentImpl(attr_span)) => { - self.check_allow_incoherent_impl(attr_span, span, target) - } - Attribute::Parsed(AttributeKind::Confusables { first_span, .. }) => { - self.check_confusables(*first_span, target); - } - Attribute::Parsed(AttributeKind::AutomaticallyDerived(attr_span)) => self - .check_generic_attr( - hir_id, - sym::automatically_derived, - *attr_span, - target, - Target::Impl { of_trait: true }, - ), Attribute::Parsed( AttributeKind::Stability { span: attr_span, @@ -193,13 +147,10 @@ impl<'tcx> CheckAttrVisitor<'tcx> { span: attr_span, stability: PartialConstStability { level, feature, .. }, }, - ) => self.check_stability(*attr_span, span, level, *feature, target), + ) => self.check_stability(*attr_span, span, level, *feature), Attribute::Parsed(AttributeKind::Inline(InlineAttr::Force { .. }, ..)) => {} // handled separately below Attribute::Parsed(AttributeKind::Inline(kind, attr_span)) => { - self.check_inline(hir_id, *attr_span, span, kind, target) - } - Attribute::Parsed(AttributeKind::Optimize(_, attr_span)) => { - self.check_optimize(hir_id, *attr_span, span, target) + self.check_inline(hir_id, *attr_span, kind, target) } Attribute::Parsed(AttributeKind::LoopMatch(attr_span)) => { self.check_loop_match(hir_id, *attr_span, target) @@ -207,11 +158,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Attribute::Parsed(AttributeKind::ConstContinue(attr_span)) => { self.check_const_continue(hir_id, *attr_span, target) } - Attribute::Parsed(AttributeKind::AllowInternalUnsafe(attr_span)) => { - self.check_allow_internal_unsafe(hir_id, *attr_span, span, target, attrs) - } - Attribute::Parsed(AttributeKind::AllowInternalUnstable(_, first_span)) => { - self.check_allow_internal_unstable(hir_id, *first_span, span, target, attrs) + Attribute::Parsed(AttributeKind::AllowInternalUnsafe(attr_span) | AttributeKind::AllowInternalUnstable(.., attr_span)) => { + self.check_macro_only_attr(*attr_span, span, target, attrs) } Attribute::Parsed(AttributeKind::AllowConstFnUnstable(_, first_span)) => { self.check_rustc_allow_const_fn_unstable(hir_id, *first_span, span, target) @@ -220,11 +168,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.check_deprecated(hir_id, attr, span, target) } Attribute::Parsed(AttributeKind::TargetFeature(_, attr_span)) => { - self.check_target_feature(hir_id, *attr_span, span, target, attrs) - } - Attribute::Parsed(AttributeKind::DocComment { .. }) => { /* `#[doc]` is actually a lot more than just doc comments, so is checked below*/ - } - Attribute::Parsed(AttributeKind::Repr { .. }) => { /* handled below this loop and elsewhere */ + self.check_target_feature(hir_id, *attr_span, target, attrs) } Attribute::Parsed(AttributeKind::RustcObjectLifetimeDefault) => { self.check_object_lifetime_default(hir_id); @@ -232,59 +176,26 @@ impl<'tcx> CheckAttrVisitor<'tcx> { &Attribute::Parsed(AttributeKind::PubTransparent(attr_span)) => { self.check_rustc_pub_transparent(attr_span, span, attrs) } - Attribute::Parsed(AttributeKind::Cold(attr_span)) => { - self.check_cold(hir_id, *attr_span, span, target) - } - Attribute::Parsed(AttributeKind::ExportName { span: attr_span, .. }) => { - self.check_export_name(hir_id, *attr_span, span, target) - } Attribute::Parsed(AttributeKind::Align { align, span: attr_span }) => { - self.check_align(span, hir_id, target, *align, *attr_span) - } - Attribute::Parsed(AttributeKind::LinkSection { span: attr_span, .. }) => { - self.check_link_section(hir_id, *attr_span, span, target) - } - Attribute::Parsed(AttributeKind::MacroUse { span, .. }) => { - self.check_macro_use(hir_id, sym::macro_use, *span, target) + self.check_align(*align, *attr_span) } - Attribute::Parsed(AttributeKind::MacroEscape(span)) => { - self.check_macro_use(hir_id, sym::macro_escape, *span, target) - } - Attribute::Parsed(AttributeKind::Naked(attr_span)) => { - self.check_naked(hir_id, *attr_span, span, target) - } - Attribute::Parsed(AttributeKind::NoImplicitPrelude(attr_span)) => self - .check_generic_attr( - hir_id, - sym::no_implicit_prelude, - *attr_span, - target, - Target::Mod, - ), - Attribute::Parsed(AttributeKind::Path(_, attr_span)) => { - self.check_generic_attr(hir_id, sym::path, *attr_span, target, Target::Mod) + Attribute::Parsed(AttributeKind::Naked(..)) => { + self.check_naked(hir_id, target) } Attribute::Parsed(AttributeKind::TrackCaller(attr_span)) => { - self.check_track_caller(hir_id, *attr_span, attrs, span, target) + self.check_track_caller(hir_id, *attr_span, attrs, target) } Attribute::Parsed(AttributeKind::NonExhaustive(attr_span)) => { - self.check_non_exhaustive(hir_id, *attr_span, span, target, item) - } - Attribute::Parsed( - AttributeKind::RustcLayoutScalarValidRangeStart(_num, attr_span) - | AttributeKind::RustcLayoutScalarValidRangeEnd(_num, attr_span), - ) => self.check_rustc_layout_scalar_valid_range(*attr_span, span, target), - Attribute::Parsed(AttributeKind::ExportStable) => { - // handled in `check_export` - } - &Attribute::Parsed(AttributeKind::FfiConst(attr_span)) => { - self.check_ffi_const(attr_span, target) + self.check_non_exhaustive(*attr_span, span, target, item) } &Attribute::Parsed(AttributeKind::FfiPure(attr_span)) => { - self.check_ffi_pure(attr_span, attrs, target) + self.check_ffi_pure(attr_span, attrs) } - Attribute::Parsed(AttributeKind::UnstableFeatureBound(syms)) => { - self.check_unstable_feature_bound(syms.first().unwrap().1, span, target) + Attribute::Parsed(AttributeKind::MayDangle(attr_span)) => { + self.check_may_dangle(hir_id, *attr_span) + } + Attribute::Parsed(AttributeKind::MustUse { span, .. }) => { + self.check_must_use(hir_id, *span, target) } Attribute::Parsed( AttributeKind::BodyStability { .. } @@ -292,46 +203,52 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::MacroTransparency(_) | AttributeKind::Pointee(..) | AttributeKind::Dummy - | AttributeKind::RustcBuiltinMacro { .. }, + | AttributeKind::RustcBuiltinMacro { .. } + | AttributeKind::Ignore { .. } + | AttributeKind::Path(..) + | AttributeKind::NoImplicitPrelude(..) + | AttributeKind::AutomaticallyDerived(..) + | AttributeKind::Marker(..) + | AttributeKind::SkipDuringMethodDispatch { .. } + | AttributeKind::Coinductive(..) + | AttributeKind::ConstTrait(..) + | AttributeKind::DenyExplicitImpl(..) + | AttributeKind::DoNotImplementViaObject(..) + | AttributeKind::SpecializationTrait(..) + | AttributeKind::UnsafeSpecializationMarker(..) + | AttributeKind::ParenSugar(..) + | AttributeKind::AllowIncoherentImpl(..) + | AttributeKind::Confusables { .. } + // `#[doc]` is actually a lot more than just doc comments, so is checked below + | AttributeKind::DocComment {..} + // handled below this loop and elsewhere + | AttributeKind::Repr { .. } + | AttributeKind::Cold(..) + | AttributeKind::ExportName { .. } + | AttributeKind::CoherenceIsCore + | AttributeKind::Fundamental + | AttributeKind::Optimize(..) + | AttributeKind::LinkSection { .. } + | AttributeKind::MacroUse { .. } + | AttributeKind::MacroEscape( .. ) + | AttributeKind::RustcLayoutScalarValidRangeStart(..) + | AttributeKind::RustcLayoutScalarValidRangeEnd(..) + | AttributeKind::ExportStable + | AttributeKind::FfiConst(..) + | AttributeKind::UnstableFeatureBound(..) + | AttributeKind::AsPtr(..) + | AttributeKind::LinkName { .. } + | AttributeKind::LinkOrdinal { .. } + | AttributeKind::NoMangle(..) + | AttributeKind::Used { .. } + | AttributeKind::PassByValue (..) + | AttributeKind::StdInternalSymbol (..) + | AttributeKind::Coverage (..) + | AttributeKind::ShouldPanic { .. } + | AttributeKind::Coroutine(..) + | AttributeKind::Linkage(..), ) => { /* do nothing */ } - Attribute::Parsed(AttributeKind::AsPtr(attr_span)) => { - self.check_applied_to_fn_or_method(hir_id, *attr_span, span, target) - } - Attribute::Parsed(AttributeKind::LinkName { span: attr_span, name }) => { - self.check_link_name(hir_id, *attr_span, *name, span, target) - } - Attribute::Parsed(AttributeKind::LinkOrdinal { span: attr_span, .. }) => { - self.check_link_ordinal(*attr_span, span, target) - } - Attribute::Parsed(AttributeKind::MayDangle(attr_span)) => { - self.check_may_dangle(hir_id, *attr_span) - } - Attribute::Parsed(AttributeKind::Ignore { span, .. }) => { - self.check_generic_attr(hir_id, sym::ignore, *span, target, Target::Fn) - } - Attribute::Parsed(AttributeKind::MustUse { span, .. }) => { - self.check_must_use(hir_id, *span, target) - } - Attribute::Parsed(AttributeKind::NoMangle(attr_span)) => { - self.check_no_mangle(hir_id, *attr_span, span, target) - } - Attribute::Parsed(AttributeKind::Used { span: attr_span, .. }) => { - self.check_used(*attr_span, target, span); - } - Attribute::Parsed(AttributeKind::ShouldPanic { span: attr_span, .. }) => self - .check_generic_attr(hir_id, sym::should_panic, *attr_span, target, Target::Fn), - &Attribute::Parsed(AttributeKind::PassByValue(attr_span)) => { - self.check_pass_by_value(attr_span, span, target) - } - &Attribute::Parsed(AttributeKind::StdInternalSymbol(attr_span)) => { - self.check_rustc_std_internal_symbol(attr_span, span, target) - } - &Attribute::Parsed(AttributeKind::Coverage(attr_span, _)) => { - self.check_coverage(attr_span, span, target) - } - &Attribute::Parsed(AttributeKind::Coroutine(attr_span)) => { - self.check_coroutine(attr_span, target) - } + Attribute::Unparsed(attr_item) => { style = Some(attr_item.style); match attr.path().as_slice() { @@ -387,15 +304,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::rustc_has_incoherent_inherent_impls, ..] => { self.check_has_incoherent_inherent_impls(attr, span, target) } - [sym::ffi_pure, ..] => self.check_ffi_pure(attr.span(), attrs, target), - [sym::ffi_const, ..] => self.check_ffi_const(attr.span(), target), [sym::link, ..] => self.check_link(hir_id, attr, span, target), - [sym::path, ..] => self.check_generic_attr_unparsed(hir_id, attr, target, Target::Mod), [sym::macro_export, ..] => self.check_macro_export(hir_id, attr, target), [sym::autodiff_forward, ..] | [sym::autodiff_reverse, ..] => { self.check_autodiff(hir_id, attr, span, target) } - [sym::linkage, ..] => self.check_linkage(attr, span, target), [ // ok sym::allow @@ -483,7 +396,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } self.check_repr(attrs, span, target, item, hir_id); - self.check_rustc_force_inline(hir_id, attrs, span, target); + self.check_rustc_force_inline(hir_id, attrs, target); self.check_mix_no_mangle_export(hir_id, attrs); } @@ -496,15 +409,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { ); } - fn inline_attr_str_error_without_macro_def(&self, hir_id: HirId, attr_span: Span, sym: &str) { - self.tcx.emit_node_span_lint( - UNUSED_ATTRIBUTES, - hir_id, - attr_span, - errors::IgnoredAttr { sym }, - ); - } - /// Checks if `#[diagnostic::do_not_recommend]` is applied on a trait impl and that it has no /// arguments. fn check_do_not_recommend( @@ -552,14 +456,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } /// Checks if an `#[inline]` is applied to a function or a closure. - fn check_inline( - &self, - hir_id: HirId, - attr_span: Span, - defn_span: Span, - kind: &InlineAttr, - target: Target, - ) { + fn check_inline(&self, hir_id: HirId, attr_span: Span, kind: &InlineAttr, target: Target) { match target { Target::Fn | Target::Closure @@ -581,81 +478,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } } - Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => { - self.tcx.emit_node_span_lint( - UNUSED_ATTRIBUTES, - hir_id, - attr_span, - errors::IgnoredInlineAttrFnProto, - ) - } - // FIXME(#65833): We permit associated consts to have an `#[inline]` attribute with - // just a lint, because we previously erroneously allowed it and some crates used it - // accidentally, to be compatible with crates depending on them, we can't throw an - // error here. - Target::AssocConst => self.tcx.emit_node_span_lint( - UNUSED_ATTRIBUTES, - hir_id, - attr_span, - errors::IgnoredInlineAttrConstants, - ), - // FIXME(#80564): Same for fields, arms, and macro defs - Target::Field | Target::Arm | Target::MacroDef => { - self.inline_attr_str_error_with_macro_def(hir_id, attr_span, "inline") - } - _ => { - self.dcx().emit_err(errors::InlineNotFnOrClosure { attr_span, defn_span }); - } - } - } - - /// Checks that `#[coverage(..)]` is applied to a function/closure/method, - /// or to an impl block or module. - fn check_coverage(&self, attr_span: Span, target_span: Span, target: Target) { - let mut not_fn_impl_mod = None; - let mut no_body = None; - - match target { - Target::Fn - | Target::Closure - | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) - | Target::Impl { .. } - | Target::Mod => return, - - // These are "functions", but they aren't allowed because they don't - // have a body, so the usual explanation would be confusing. - Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => { - no_body = Some(target_span); - } - - _ => { - not_fn_impl_mod = Some(target_span); - } - } - - self.dcx().emit_err(errors::CoverageAttributeNotAllowed { - attr_span, - not_fn_impl_mod, - no_body, - help: (), - }); - } - - /// Checks that `#[optimize(..)]` is applied to a function/closure/method, - /// or to an impl block or module. - fn check_optimize(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target) { - let is_valid = matches!( - target, - Target::Fn - | Target::Closure - | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) - ); - if !is_valid { - self.dcx().emit_err(errors::OptimizeInvalidTarget { - attr_span, - defn_span: span, - on_crate: hir_id == CRATE_HIR_ID, - }); + _ => {} } } @@ -695,51 +518,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - /// FIXME: Remove when all attributes are ported to the new parser - fn check_generic_attr_unparsed( - &self, - hir_id: HirId, - attr: &Attribute, - target: Target, - allowed_target: Target, - ) { - if target != allowed_target { - let attr_name = join_path_syms(attr.path()); - self.tcx.emit_node_span_lint( - UNUSED_ATTRIBUTES, - hir_id, - attr.span(), - errors::OnlyHasEffectOn { - attr_name, - target_name: allowed_target.name().replace(' ', "_"), - }, - ); - } - } - - fn check_generic_attr( - &self, - hir_id: HirId, - attr_name: Symbol, - attr_span: Span, - target: Target, - allowed_target: Target, - ) { - if target != allowed_target { - self.tcx.emit_node_span_lint( - UNUSED_ATTRIBUTES, - hir_id, - attr_span, - errors::OnlyHasEffectOn { - attr_name: attr_name.to_string(), - target_name: allowed_target.name().replace(' ', "_"), - }, - ); - } - } - /// Checks if `#[naked]` is applied to a function definition. - fn check_naked(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target) { + fn check_naked(&self, hir_id: HirId, target: Target) { match target { Target::Fn | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => { @@ -758,13 +538,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { .emit(); } } - _ => { - self.dcx().emit_err(errors::AttrShouldBeAppliedToFn { - attr_span, - defn_span: span, - on_crate: hir_id == CRATE_HIR_ID, - }); - } + _ => {} } } @@ -807,7 +581,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { hir_id: HirId, attr_span: Span, attrs: &[Attribute], - span: Span, target: Target, ) { match target { @@ -827,28 +600,13 @@ impl<'tcx> CheckAttrVisitor<'tcx> { }); } } - Target::Method(..) | Target::ForeignFn | Target::Closure => {} - // FIXME(#80564): We permit struct fields, match arms and macro defs to have an - // `#[track_caller]` attribute with just a lint, because we previously - // erroneously allowed it and some crates used it accidentally, to be compatible - // with crates depending on them, we can't throw an error here. - Target::Field | Target::Arm | Target::MacroDef => { - self.inline_attr_str_error_with_macro_def(hir_id, attr_span, "track_caller"); - } - _ => { - self.dcx().emit_err(errors::TrackedCallerWrongLocation { - attr_span, - defn_span: span, - on_crate: hir_id == CRATE_HIR_ID, - }); - } + _ => {} } } /// Checks if the `#[non_exhaustive]` attribute on an `item` is valid. fn check_non_exhaustive( &self, - hir_id: HirId, attr_span: Span, span: Span, target: Target, @@ -869,36 +627,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { }); } } - Target::Enum | Target::Variant => {} - // FIXME(#80564): We permit struct fields, match arms and macro defs to have an - // `#[non_exhaustive]` attribute with just a lint, because we previously - // erroneously allowed it and some crates used it accidentally, to be compatible - // with crates depending on them, we can't throw an error here. - Target::Field | Target::Arm | Target::MacroDef => { - self.inline_attr_str_error_with_macro_def(hir_id, attr_span, "non_exhaustive"); - } - _ => { - self.dcx() - .emit_err(errors::NonExhaustiveWrongLocation { attr_span, defn_span: span }); - } - } - } - - /// Checks if the `#[marker]` attribute on an `item` is valid. - fn check_marker(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target) { - match target { - Target::Trait => {} - // FIXME(#80564): We permit struct fields, match arms and macro defs to have an - // `#[marker]` attribute with just a lint, because we previously - // erroneously allowed it and some crates used it accidentally, to be compatible - // with crates depending on them, we can't throw an error here. - Target::Field | Target::Arm | Target::MacroDef => { - self.inline_attr_str_error_with_macro_def(hir_id, attr_span, "marker"); - } - _ => { - self.dcx() - .emit_err(errors::AttrShouldBeAppliedToTrait { attr_span, defn_span: span }); - } + _ => {} } } @@ -907,7 +636,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { &self, hir_id: HirId, attr_span: Span, - span: Span, target: Target, attrs: &[Attribute], ) { @@ -930,30 +658,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { }); } } - // FIXME: #[target_feature] was previously erroneously allowed on statements and some - // crates used this, so only emit a warning. - Target::Statement => { - self.tcx.emit_node_span_lint( - UNUSED_ATTRIBUTES, - hir_id, - attr_span, - errors::TargetFeatureOnStatement, - ); - } - // FIXME(#80564): We permit struct fields, match arms and macro defs to have an - // `#[target_feature]` attribute with just a lint, because we previously - // erroneously allowed it and some crates used it accidentally, to be compatible - // with crates depending on them, we can't throw an error here. - Target::Field | Target::Arm | Target::MacroDef => { - self.inline_attr_str_error_with_macro_def(hir_id, attr_span, "target_feature"); - } - _ => { - self.dcx().emit_err(errors::AttrShouldBeAppliedToFn { - attr_span, - defn_span: span, - on_crate: hir_id == CRATE_HIR_ID, - }); - } + _ => {} } } @@ -1057,7 +762,10 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | Target::GenericParam { .. } | Target::MacroDef | Target::PatField - | Target::ExprField => None, + | Target::ExprField + | Target::Crate + | Target::MacroCall + | Target::Delegation { .. } => None, } { tcx.dcx().emit_err(errors::DocAliasBadLocation { span, attr_str, location }); return; @@ -1533,25 +1241,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - /// Warns against some misuses of `#[pass_by_value]` - fn check_pass_by_value(&self, attr_span: Span, span: Span, target: Target) { - match target { - Target::Struct | Target::Enum | Target::TyAlias => {} - _ => { - self.dcx().emit_err(errors::PassByValue { attr_span, span }); - } - } - } - - fn check_allow_incoherent_impl(&self, attr_span: Span, span: Span, target: Target) { - match target { - Target::Method(MethodKind::Inherent) => {} - _ => { - self.dcx().emit_err(errors::AllowIncoherentImpl { attr_span, span }); - } - } - } - fn check_has_incoherent_inherent_impls(&self, attr: &Attribute, span: Span, target: Target) { match target { Target::Trait | Target::Struct | Target::Enum | Target::Union | Target::ForeignTy => {} @@ -1563,23 +1252,13 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_ffi_pure(&self, attr_span: Span, attrs: &[Attribute], target: Target) { - if target != Target::ForeignFn { - self.dcx().emit_err(errors::FfiPureInvalidTarget { attr_span }); - return; - } + fn check_ffi_pure(&self, attr_span: Span, attrs: &[Attribute]) { if find_attr!(attrs, AttributeKind::FfiConst(_)) { // `#[ffi_const]` functions cannot be `#[ffi_pure]` self.dcx().emit_err(errors::BothFfiConstAndPure { attr_span }); } } - fn check_ffi_const(&self, attr_span: Span, target: Target) { - if target != Target::ForeignFn { - self.dcx().emit_err(errors::FfiConstInvalidTarget { attr_span }); - } - } - /// Warns against some misuses of `#[must_use]` fn check_must_use(&self, hir_id: HirId, attr_span: Span, target: Target) { if matches!( @@ -1607,22 +1286,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> { return; } - let article = match target { - Target::ExternCrate - | Target::Enum - | Target::Impl { .. } - | Target::Expression - | Target::Arm - | Target::AssocConst - | Target::AssocTy => "an", - _ => "a", - }; - self.tcx.emit_node_span_lint( UNUSED_ATTRIBUTES, hir_id, attr_span, - errors::MustUseNoEffect { article, target }, + errors::MustUseNoEffect { target: target.plural_name(), attr_span }, ); } @@ -1657,30 +1325,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.dcx().emit_err(errors::InvalidMayDangle { attr_span }); } - /// Checks if `#[cold]` is applied to a non-function. - fn check_cold(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target) { - match target { - Target::Fn | Target::Method(..) | Target::ForeignFn | Target::Closure => {} - // FIXME(#80564): We permit struct fields, match arms and macro defs to have an - // `#[cold]` attribute with just a lint, because we previously - // erroneously allowed it and some crates used it accidentally, to be compatible - // with crates depending on them, we can't throw an error here. - Target::Field | Target::Arm | Target::MacroDef => { - self.inline_attr_str_error_with_macro_def(hir_id, attr_span, "cold"); - } - _ => { - // FIXME: #[cold] was previously allowed on non-functions and some crates used - // this, so only emit a warning. - self.tcx.emit_node_span_lint( - UNUSED_ATTRIBUTES, - hir_id, - attr_span, - errors::Cold { span, on_crate: hir_id == CRATE_HIR_ID }, - ); - } - } - } - /// Checks if `#[link]` is applied to an item other than a foreign module. fn check_link(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) { if target == Target::ForeignMod @@ -1699,38 +1343,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { ); } - /// Checks if `#[link_name]` is applied to an item other than a foreign function or static. - fn check_link_name( - &self, - hir_id: HirId, - attr_span: Span, - name: Symbol, - span: Span, - target: Target, - ) { - match target { - Target::ForeignFn | Target::ForeignStatic => {} - // FIXME(#80564): We permit struct fields, match arms and macro defs to have an - // `#[link_name]` attribute with just a lint, because we previously - // erroneously allowed it and some crates used it accidentally, to be compatible - // with crates depending on them, we can't throw an error here. - Target::Field | Target::Arm | Target::MacroDef => { - self.inline_attr_str_error_with_macro_def(hir_id, attr_span, "link_name"); - } - _ => { - // FIXME: #[link_name] was previously allowed on non-functions/statics and some crates - // used this, so only emit a warning. - let help_span = matches!(target, Target::ForeignMod).then_some(attr_span); - self.tcx.emit_node_span_lint( - UNUSED_ATTRIBUTES, - hir_id, - attr_span, - errors::LinkName { span, help_span, value: name.as_str() }, - ); - } - } - } - /// Checks if `#[no_link]` is applied to an `extern crate`. fn check_no_link(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) { match target { @@ -1748,35 +1360,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn is_impl_item(&self, hir_id: HirId) -> bool { - matches!(self.tcx.hir_node(hir_id), hir::Node::ImplItem(..)) - } - - /// Checks if `#[export_name]` is applied to a function or static. - fn check_export_name(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target) { - match target { - Target::Static | Target::Fn => {} - Target::Method(..) if self.is_impl_item(hir_id) => {} - // FIXME(#80564): We permit struct fields, match arms and macro defs to have an - // `#[export_name]` attribute with just a lint, because we previously - // erroneously allowed it and some crates used it accidentally, to be compatible - // with crates depending on them, we can't throw an error here. - Target::Field | Target::Arm | Target::MacroDef => { - self.inline_attr_str_error_with_macro_def(hir_id, attr_span, "export_name"); - } - _ => { - self.dcx().emit_err(errors::ExportName { attr_span, span }); - } - } - } - - fn check_rustc_layout_scalar_valid_range(&self, attr_span: Span, span: Span, target: Target) { - if target != Target::Struct { - self.dcx().emit_err(errors::RustcLayoutScalarValidRangeNotStruct { attr_span, span }); - return; - } - } - /// Checks if `#[rustc_legacy_const_generics]` is applied to a function and has a valid argument. fn check_rustc_legacy_const_generics( &self, @@ -1911,106 +1494,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - /// Checks if `#[link_section]` is applied to a function or static. - fn check_link_section(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target) { - match target { - Target::Static | Target::Fn | Target::Method(..) => {} - // FIXME(#80564): We permit struct fields, match arms and macro defs to have an - // `#[link_section]` attribute with just a lint, because we previously - // erroneously allowed it and some crates used it accidentally, to be compatible - // with crates depending on them, we can't throw an error here. - Target::Field | Target::Arm | Target::MacroDef => { - self.inline_attr_str_error_with_macro_def(hir_id, attr_span, "link_section"); - } - _ => { - // FIXME: #[link_section] was previously allowed on non-functions/statics and some - // crates used this, so only emit a warning. - self.tcx.emit_node_span_lint( - UNUSED_ATTRIBUTES, - hir_id, - attr_span, - errors::LinkSection { span }, - ); - } - } - } - - /// Checks if `#[no_mangle]` is applied to a function or static. - fn check_no_mangle(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target) { - match target { - Target::Static | Target::Fn => {} - Target::Method(..) if self.is_impl_item(hir_id) => {} - // FIXME(#80564): We permit struct fields, match arms and macro defs to have an - // `#[no_mangle]` attribute with just a lint, because we previously - // erroneously allowed it and some crates used it accidentally, to be compatible - // with crates depending on them, we can't throw an error here. - Target::Field | Target::Arm | Target::MacroDef => { - self.inline_attr_str_error_with_macro_def(hir_id, attr_span, "no_mangle"); - } - // FIXME: #[no_mangle] was previously allowed on non-functions/statics, this should be an error - // The error should specify that the item that is wrong is specifically a *foreign* fn/static - // otherwise the error seems odd - Target::ForeignFn | Target::ForeignStatic => { - let foreign_item_kind = match target { - Target::ForeignFn => "function", - Target::ForeignStatic => "static", - _ => unreachable!(), - }; - self.tcx.emit_node_span_lint( - UNUSED_ATTRIBUTES, - hir_id, - attr_span, - errors::NoMangleForeign { span, attr_span, foreign_item_kind }, - ); - } - _ => { - // FIXME: #[no_mangle] was previously allowed on non-functions/statics and some - // crates used this, so only emit a warning. - self.tcx.emit_node_span_lint( - UNUSED_ATTRIBUTES, - hir_id, - attr_span, - errors::NoMangle { span }, - ); - } - } - } - - /// Checks if the `#[align]` attributes on `item` are valid. - // FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity - fn check_align( - &self, - span: Span, - hir_id: HirId, - target: Target, - align: Align, - attr_span: Span, - ) { - match target { - Target::Fn | Target::Method(_) | Target::ForeignFn => {} - Target::Field => { - self.tcx.emit_node_span_lint( - UNUSED_ATTRIBUTES, - hir_id, - attr_span, - AlignOnFields { span }, - ); - } - Target::Struct | Target::Union | Target::Enum => { - self.dcx().emit_err(errors::AlignShouldBeReprAlign { - span: attr_span, - item: target.name(), - align_bytes: align.bytes(), - }); - } - _ => { - self.dcx().emit_err(errors::AlignAttrApplication { hint_span: attr_span, span }); - } - } - - self.check_align_value(align, attr_span); - } - /// Checks if the `#[repr]` attributes on `item` are valid. fn check_repr( &self, @@ -2065,7 +1548,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Target::Fn | Target::Method(_) => { self.dcx().emit_err(errors::ReprAlignShouldBeAlign { span: *repr_span, - item: target.name(), + item: target.plural_name(), }); } _ => { @@ -2076,7 +1559,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - self.check_align_value(*align, *repr_span); + self.check_align(*align, *repr_span); } ReprAttr::ReprPacked(_) => { if target != Target::Struct && target != Target::Union { @@ -2135,7 +1618,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Target::Fn | Target::Method(_) => { self.dcx().emit_err(errors::ReprAlignShouldBeAlign { span: first_attr_span, - item: target.name(), + item: target.plural_name(), }); } _ => { @@ -2182,7 +1665,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_align_value(&self, align: Align, span: Span) { + fn check_align(&self, align: Align, span: Span) { if align.bytes() > 2_u64.pow(29) { // for values greater than 2^29, a different error will be emitted, make sure that happens self.dcx().span_delayed_bug( @@ -2201,61 +1684,16 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_used(&self, attr_span: Span, target: Target, target_span: Span) { - if target != Target::Static { - self.dcx().emit_err(errors::UsedStatic { - attr_span, - span: target_span, - target: target.name(), - }); - } - } - - /// Outputs an error for `#[allow_internal_unstable]` which can only be applied to macros. - /// (Allows proc_macro functions) - fn check_allow_internal_unstable( - &self, - hir_id: HirId, - attr_span: Span, - span: Span, - target: Target, - attrs: &[Attribute], - ) { - self.check_macro_only_attr( - hir_id, - attr_span, - span, - target, - attrs, - "allow_internal_unstable", - ) - } - - /// Outputs an error for `#[allow_internal_unsafe]` which can only be applied to macros. - /// (Allows proc_macro functions) - fn check_allow_internal_unsafe( - &self, - hir_id: HirId, - attr_span: Span, - span: Span, - target: Target, - attrs: &[Attribute], - ) { - self.check_macro_only_attr(hir_id, attr_span, span, target, attrs, "allow_internal_unsafe") - } - /// Outputs an error for attributes that can only be applied to macros, such as /// `#[allow_internal_unsafe]` and `#[allow_internal_unstable]`. /// (Allows proc_macro functions) // FIXME(jdonszelmann): if possible, move to attr parsing fn check_macro_only_attr( &self, - hir_id: HirId, attr_span: Span, span: Span, target: Target, attrs: &[Attribute], - attr_name: &str, ) { match target { Target::Fn => { @@ -2265,23 +1703,10 @@ impl<'tcx> CheckAttrVisitor<'tcx> { return; } } - // continue out of the match - } - // return on decl macros - Target::MacroDef => return, - // FIXME(#80564): We permit struct fields and match arms to have an - // `#[allow_internal_unstable]` attribute with just a lint, because we previously - // erroneously allowed it and some crates used it accidentally, to be compatible - // with crates depending on them, we can't throw an error here. - Target::Field | Target::Arm => { - self.inline_attr_str_error_without_macro_def(hir_id, attr_span, attr_name); - return; + self.tcx.dcx().emit_err(errors::MacroOnlyAttribute { attr_span, span }); } - // otherwise continue out of the match _ => {} } - - self.tcx.dcx().emit_err(errors::MacroOnlyAttribute { attr_span, span }); } /// Checks if the items on the `#[debugger_visualizer]` attribute are valid. @@ -2308,66 +1733,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> { target: Target, ) { match target { - Target::Fn | Target::Method(_) - if self.tcx.is_const_fn(hir_id.expect_owner().to_def_id()) => {} - // FIXME(#80564): We permit struct fields and match arms to have an - // `#[allow_internal_unstable]` attribute with just a lint, because we previously - // erroneously allowed it and some crates used it accidentally, to be compatible - // with crates depending on them, we can't throw an error here. - Target::Field | Target::Arm | Target::MacroDef => self - .inline_attr_str_error_with_macro_def(hir_id, attr_span, "allow_internal_unstable"), - _ => { - self.tcx.dcx().emit_err(errors::RustcAllowConstFnUnstable { attr_span, span }); - } - } - } - - fn check_unstable_feature_bound(&self, attr_span: Span, span: Span, target: Target) { - match target { - // FIXME(staged_api): There's no reason we can't support more targets here. We're just - // being conservative to begin with. - Target::Fn | Target::Impl { .. } | Target::Trait => {} - Target::ExternCrate - | Target::Use - | Target::Static - | Target::Const - | Target::Closure - | Target::Mod - | Target::ForeignMod - | Target::GlobalAsm - | Target::TyAlias - | Target::Enum - | Target::Variant - | Target::Struct - | Target::Field - | Target::Union - | Target::TraitAlias - | Target::Expression - | Target::Statement - | Target::Arm - | Target::AssocConst - | Target::Method(_) - | Target::AssocTy - | Target::ForeignFn - | Target::ForeignStatic - | Target::ForeignTy - | Target::GenericParam { .. } - | Target::MacroDef - | Target::Param - | Target::PatField - | Target::ExprField - | Target::WherePredicate => { - self.tcx.dcx().emit_err(errors::RustcUnstableFeatureBound { attr_span, span }); - } - } - } - - fn check_rustc_std_internal_symbol(&self, attr_span: Span, span: Span, target: Target) { - match target { - Target::Fn | Target::Static | Target::ForeignFn | Target::ForeignStatic => {} - _ => { - self.tcx.dcx().emit_err(errors::RustcStdInternalSymbol { attr_span, span }); + Target::Fn | Target::Method(_) => { + if !self.tcx.is_const_fn(hir_id.expect_owner().to_def_id()) { + self.tcx.dcx().emit_err(errors::RustcAllowConstFnUnstable { attr_span, span }); + } } + _ => {} } } @@ -2377,15 +1748,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { item_span: Span, level: &StabilityLevel, feature: Symbol, - target: Target, ) { - match target { - Target::Expression => { - self.dcx().emit_err(errors::StabilityPromotable { attr_span }); - } - _ => {} - } - // Stable *language* features shouldn't be used as unstable library features. // (Not doing this for stable library features is checked by tidy.) if level.is_unstable() @@ -2397,40 +1760,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_link_ordinal(&self, attr_span: Span, _span: Span, target: Target) { - match target { - Target::ForeignFn | Target::ForeignStatic => {} - _ => { - self.dcx().emit_err(errors::LinkOrdinal { attr_span }); - } - } - } - - fn check_confusables(&self, span: Span, target: Target) { - if !matches!(target, Target::Method(MethodKind::Inherent)) { - self.dcx().emit_err(errors::Confusables { attr_span: span }); - } - } - fn check_deprecated(&self, hir_id: HirId, attr: &Attribute, _span: Span, target: Target) { match target { - Target::Closure | Target::Expression | Target::Statement | Target::Arm => { - self.tcx.emit_node_span_lint( - UNUSED_ATTRIBUTES, - hir_id, - attr.span(), - errors::Deprecated, - ); - } - Target::Impl { of_trait: true } - | Target::GenericParam { has_default: false, kind: _ } => { - self.tcx.emit_node_span_lint( - USELESS_DEPRECATED, - hir_id, - attr.span(), - errors::DeprecatedAnnotationHasNoEffect { span: attr.span() }, - ); - } Target::AssocConst | Target::Method(..) | Target::AssocTy if matches!( self.tcx.def_kind(self.tcx.local_parent(hir_id.owner.def_id)), @@ -2438,7 +1769,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { ) => { self.tcx.emit_node_span_lint( - USELESS_DEPRECATED, + UNUSED_ATTRIBUTES, hir_id, attr.span(), errors::DeprecatedAnnotationHasNoEffect { span: attr.span() }, @@ -2448,20 +1779,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_macro_use(&self, hir_id: HirId, name: Symbol, attr_span: Span, target: Target) { - match target { - Target::ExternCrate | Target::Mod => {} - _ => { - self.tcx.emit_node_span_lint( - UNUSED_ATTRIBUTES, - hir_id, - attr_span, - errors::MacroUse { name }, - ); - } - } - } - fn check_macro_export(&self, hir_id: HirId, attr: &Attribute, target: Target) { if target != Target::MacroDef { self.tcx.emit_node_span_lint( @@ -2681,15 +1998,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_coroutine(&self, attr_span: Span, target: Target) { - match target { - Target::Closure => return, - _ => { - self.dcx().emit_err(errors::CoroutineOnNonClosure { span: attr_span }); - } - } - } - fn check_type_const(&self, hir_id: HirId, attr_span: Span, target: Target) { let tcx = self.tcx; if target == Target::AssocConst @@ -2707,19 +2015,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_linkage(&self, attr: &Attribute, span: Span, target: Target) { - match target { - Target::Fn - | Target::Method(..) - | Target::Static - | Target::ForeignStatic - | Target::ForeignFn => {} - _ => { - self.dcx().emit_err(errors::Linkage { attr_span: attr.span(), span }); - } - } - } - fn check_rustc_pub_transparent(&self, attr_span: Span, span: Span, attrs: &[Attribute]) { if !find_attr!(attrs, AttributeKind::Repr { reprs, .. } => reprs.iter().any(|(r, _)| r == &ReprAttr::ReprTransparent)) .unwrap_or(false) @@ -2728,43 +2023,28 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_rustc_force_inline( - &self, - hir_id: HirId, - attrs: &[Attribute], - span: Span, - target: Target, - ) { - match ( + fn check_rustc_force_inline(&self, hir_id: HirId, attrs: &[Attribute], target: Target) { + if let (Target::Closure, None) = ( target, find_attr!(attrs, AttributeKind::Inline(InlineAttr::Force { attr_span, .. }, _) => *attr_span), ) { - (Target::Closure, None) => { - let is_coro = matches!( - self.tcx.hir_expect_expr(hir_id).kind, - hir::ExprKind::Closure(hir::Closure { - kind: hir::ClosureKind::Coroutine(..) - | hir::ClosureKind::CoroutineClosure(..), - .. - }) - ); - let parent_did = self.tcx.hir_get_parent_item(hir_id).to_def_id(); - let parent_span = self.tcx.def_span(parent_did); + let is_coro = matches!( + self.tcx.hir_expect_expr(hir_id).kind, + hir::ExprKind::Closure(hir::Closure { + kind: hir::ClosureKind::Coroutine(..) | hir::ClosureKind::CoroutineClosure(..), + .. + }) + ); + let parent_did = self.tcx.hir_get_parent_item(hir_id).to_def_id(); + let parent_span = self.tcx.def_span(parent_did); - if let Some(attr_span) = find_attr!( - self.tcx.get_all_attrs(parent_did), - AttributeKind::Inline(InlineAttr::Force { attr_span, .. }, _) => *attr_span - ) && is_coro - { - self.dcx() - .emit_err(errors::RustcForceInlineCoro { attr_span, span: parent_span }); - } - } - (Target::Fn, _) => (), - (_, Some(attr_span)) => { - self.dcx().emit_err(errors::RustcForceInline { attr_span, span }); + if let Some(attr_span) = find_attr!( + self.tcx.get_all_attrs(parent_did), + AttributeKind::Inline(InlineAttr::Force { attr_span, .. }, _) => *attr_span + ) && is_coro + { + self.dcx().emit_err(errors::RustcForceInlineCoro { attr_span, span: parent_span }); } - (_, None) => (), } } @@ -2814,8 +2094,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { let node_span = self.tcx.hir_span(hir_id); if !matches!(target, Target::Expression) { - self.dcx().emit_err(errors::LoopMatchAttr { attr_span, node_span }); - return; + return; // Handled in target checking during attr parse } if !matches!(self.tcx.hir_expect_expr(hir_id).kind, hir::ExprKind::Loop(..)) { @@ -2827,8 +2106,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { let node_span = self.tcx.hir_span(hir_id); if !matches!(target, Target::Expression) { - self.dcx().emit_err(errors::ConstContinueAttr { attr_span, node_span }); - return; + return; // Handled in target checking during attr parse } if !matches!(self.tcx.hir_expect_expr(hir_id).kind, hir::ExprKind::Break(..)) { @@ -2871,6 +2149,7 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> { .hir_attrs(where_predicate.hir_id) .iter() .filter(|attr| !ATTRS_ALLOWED.iter().any(|&sym| attr.has_name(sym))) + .filter(|attr| !attr.is_parsed_attr()) .map(|attr| attr.span()) .collect::<Vec<_>>(); if !spans.is_empty() { @@ -3001,10 +2280,6 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) { }) = attr { (*first_attr_span, sym::repr) - } else if let Attribute::Parsed(AttributeKind::Path(.., span)) = attr { - (*span, sym::path) - } else if let Attribute::Parsed(AttributeKind::AutomaticallyDerived(span)) = attr { - (*span, sym::automatically_derived) } else { continue; }; diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index de52973acbb..08d06402000 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -371,7 +371,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { /// will be ignored for the purposes of dead code analysis (see PR #85200 /// for discussion). fn should_ignore_item(&mut self, def_id: DefId) -> bool { - if let Some(impl_of) = self.tcx.impl_of_assoc(def_id) { + if let Some(impl_of) = self.tcx.trait_impl_of_assoc(def_id) { if !self.tcx.is_automatically_derived(impl_of) { return false; } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 10b30fbe8c9..c5d5155d0e5 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -75,58 +75,6 @@ pub(crate) struct IgnoredAttrWithMacro<'a> { pub sym: &'a str, } -#[derive(LintDiagnostic)] -#[diag(passes_ignored_attr)] -pub(crate) struct IgnoredAttr<'a> { - pub sym: &'a str, -} - -#[derive(LintDiagnostic)] -#[diag(passes_inline_ignored_function_prototype)] -pub(crate) struct IgnoredInlineAttrFnProto; - -#[derive(LintDiagnostic)] -#[diag(passes_inline_ignored_constants)] -#[warning] -#[note] -pub(crate) struct IgnoredInlineAttrConstants; - -#[derive(Diagnostic)] -#[diag(passes_inline_not_fn_or_closure, code = E0518)] -pub(crate) struct InlineNotFnOrClosure { - #[primary_span] - pub attr_span: Span, - #[label] - pub defn_span: Span, -} - -/// "coverage attribute not allowed here" -#[derive(Diagnostic)] -#[diag(passes_coverage_attribute_not_allowed, code = E0788)] -pub(crate) struct CoverageAttributeNotAllowed { - #[primary_span] - pub attr_span: Span, - /// "not a function, impl block, or module" - #[label(passes_not_fn_impl_mod)] - pub not_fn_impl_mod: Option<Span>, - /// "function has no body" - #[label(passes_no_body)] - pub no_body: Option<Span>, - /// "coverage attribute can be applied to a function (with body), impl block, or module" - #[help] - pub help: (), -} - -#[derive(Diagnostic)] -#[diag(passes_optimize_invalid_target)] -pub(crate) struct OptimizeInvalidTarget { - #[primary_span] - pub attr_span: Span, - #[label] - pub defn_span: Span, - pub on_crate: bool, -} - #[derive(Diagnostic)] #[diag(passes_should_be_applied_to_fn)] pub(crate) struct AttrShouldBeAppliedToFn { @@ -138,25 +86,6 @@ pub(crate) struct AttrShouldBeAppliedToFn { } #[derive(Diagnostic)] -#[diag(passes_should_be_applied_to_fn, code = E0739)] -pub(crate) struct TrackedCallerWrongLocation { - #[primary_span] - pub attr_span: Span, - #[label] - pub defn_span: Span, - pub on_crate: bool, -} - -#[derive(Diagnostic)] -#[diag(passes_should_be_applied_to_struct_enum, code = E0701)] -pub(crate) struct NonExhaustiveWrongLocation { - #[primary_span] - pub attr_span: Span, - #[label] - pub defn_span: Span, -} - -#[derive(Diagnostic)] #[diag(passes_non_exhaustive_with_default_field_values)] pub(crate) struct NonExhaustiveWithDefaultFieldValues { #[primary_span] @@ -174,10 +103,6 @@ pub(crate) struct AttrShouldBeAppliedToTrait { pub defn_span: Span, } -#[derive(LintDiagnostic)] -#[diag(passes_target_feature_on_statement)] -pub(crate) struct TargetFeatureOnStatement; - #[derive(Diagnostic)] #[diag(passes_should_be_applied_to_static)] pub(crate) struct AttrShouldBeAppliedToStatic { @@ -417,24 +342,6 @@ pub(crate) struct DocTestUnknownInclude { pub(crate) struct DocInvalid; #[derive(Diagnostic)] -#[diag(passes_pass_by_value)] -pub(crate) struct PassByValue { - #[primary_span] - pub attr_span: Span, - #[label] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(passes_allow_incoherent_impl)] -pub(crate) struct AllowIncoherentImpl { - #[primary_span] - pub attr_span: Span, - #[label] - pub span: Span, -} - -#[derive(Diagnostic)] #[diag(passes_has_incoherent_inherent_impl)] pub(crate) struct HasIncoherentInherentImpl { #[primary_span] @@ -450,25 +357,12 @@ pub(crate) struct BothFfiConstAndPure { pub attr_span: Span, } -#[derive(Diagnostic)] -#[diag(passes_ffi_pure_invalid_target, code = E0755)] -pub(crate) struct FfiPureInvalidTarget { - #[primary_span] - pub attr_span: Span, -} - -#[derive(Diagnostic)] -#[diag(passes_ffi_const_invalid_target, code = E0756)] -pub(crate) struct FfiConstInvalidTarget { - #[primary_span] - pub attr_span: Span, -} - #[derive(LintDiagnostic)] #[diag(passes_must_use_no_effect)] pub(crate) struct MustUseNoEffect { - pub article: &'static str, - pub target: rustc_hir::Target, + pub target: &'static str, + #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")] + pub attr_span: Span, } #[derive(Diagnostic)] @@ -481,15 +375,6 @@ pub(crate) struct MustNotSuspend { } #[derive(LintDiagnostic)] -#[diag(passes_cold)] -#[warning] -pub(crate) struct Cold { - #[label] - pub span: Span, - pub on_crate: bool, -} - -#[derive(LintDiagnostic)] #[diag(passes_link)] #[warning] pub(crate) struct Link { @@ -497,17 +382,6 @@ pub(crate) struct Link { pub span: Option<Span>, } -#[derive(LintDiagnostic)] -#[diag(passes_link_name)] -#[warning] -pub(crate) struct LinkName<'a> { - #[help] - pub help_span: Option<Span>, - #[label] - pub span: Span, - pub value: &'a str, -} - #[derive(Diagnostic)] #[diag(passes_no_link)] pub(crate) struct NoLink { @@ -518,24 +392,6 @@ pub(crate) struct NoLink { } #[derive(Diagnostic)] -#[diag(passes_export_name)] -pub(crate) struct ExportName { - #[primary_span] - pub attr_span: Span, - #[label] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(passes_rustc_layout_scalar_valid_range_not_struct)] -pub(crate) struct RustcLayoutScalarValidRangeNotStruct { - #[primary_span] - pub attr_span: Span, - #[label] - pub span: Span, -} - -#[derive(Diagnostic)] #[diag(passes_rustc_legacy_const_generics_only)] pub(crate) struct RustcLegacyConstGenericsOnly { #[primary_span] @@ -576,42 +432,6 @@ pub(crate) struct RustcDirtyClean { pub span: Span, } -#[derive(LintDiagnostic)] -#[diag(passes_link_section)] -#[warning] -pub(crate) struct LinkSection { - #[label] - pub span: Span, -} - -#[derive(LintDiagnostic)] -#[diag(passes_no_mangle_foreign)] -#[warning] -#[note] -pub(crate) struct NoMangleForeign { - #[label] - pub span: Span, - #[suggestion(code = "", applicability = "machine-applicable")] - pub attr_span: Span, - pub foreign_item_kind: &'static str, -} - -#[derive(LintDiagnostic)] -#[diag(passes_no_mangle)] -#[warning] -pub(crate) struct NoMangle { - #[label] - pub span: Span, -} - -#[derive(LintDiagnostic)] -#[diag(passes_align_on_fields)] -#[warning] -pub(crate) struct AlignOnFields { - #[label] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(passes_repr_conflicting, code = E0566)] pub(crate) struct ReprConflicting { @@ -633,16 +453,6 @@ pub(crate) struct InvalidReprAlignForTarget { pub(crate) struct ReprConflictingLint; #[derive(Diagnostic)] -#[diag(passes_used_static)] -pub(crate) struct UsedStatic { - #[primary_span] - pub attr_span: Span, - #[label] - pub span: Span, - pub target: &'static str, -} - -#[derive(Diagnostic)] #[diag(passes_macro_only_attribute)] pub(crate) struct MacroOnlyAttribute { #[primary_span] @@ -687,24 +497,6 @@ pub(crate) struct RustcAllowConstFnUnstable { } #[derive(Diagnostic)] -#[diag(passes_rustc_unstable_feature_bound)] -pub(crate) struct RustcUnstableFeatureBound { - #[primary_span] - pub attr_span: Span, - #[label] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(passes_rustc_std_internal_symbol)] -pub(crate) struct RustcStdInternalSymbol { - #[primary_span] - pub attr_span: Span, - #[label] - pub span: Span, -} - -#[derive(Diagnostic)] #[diag(passes_rustc_pub_transparent)] pub(crate) struct RustcPubTransparent { #[primary_span] @@ -714,15 +506,6 @@ pub(crate) struct RustcPubTransparent { } #[derive(Diagnostic)] -#[diag(passes_rustc_force_inline)] -pub(crate) struct RustcForceInline { - #[primary_span] - pub attr_span: Span, - #[label] - pub span: Span, -} - -#[derive(Diagnostic)] #[diag(passes_rustc_force_inline_coro)] pub(crate) struct RustcForceInlineCoro { #[primary_span] @@ -731,53 +514,6 @@ pub(crate) struct RustcForceInlineCoro { pub span: Span, } -#[derive(Diagnostic)] -#[diag(passes_link_ordinal)] -pub(crate) struct LinkOrdinal { - #[primary_span] - pub attr_span: Span, -} - -#[derive(Diagnostic)] -#[diag(passes_confusables)] -pub(crate) struct Confusables { - #[primary_span] - pub attr_span: Span, -} - -#[derive(Diagnostic)] -#[diag(passes_coroutine_on_non_closure)] -pub(crate) struct CoroutineOnNonClosure { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(passes_linkage)] -pub(crate) struct Linkage { - #[primary_span] - pub attr_span: Span, - #[label] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(passes_stability_promotable)] -pub(crate) struct StabilityPromotable { - #[primary_span] - pub attr_span: Span, -} - -#[derive(LintDiagnostic)] -#[diag(passes_deprecated)] -pub(crate) struct Deprecated; - -#[derive(LintDiagnostic)] -#[diag(passes_macro_use)] -pub(crate) struct MacroUse { - pub name: Symbol, -} - #[derive(LintDiagnostic)] pub(crate) enum MacroExport { #[diag(passes_macro_export)] @@ -1281,13 +1017,6 @@ pub(crate) struct UselessAssignment<'a> { } #[derive(LintDiagnostic)] -#[diag(passes_only_has_effect_on)] -pub(crate) struct OnlyHasEffectOn { - pub attr_name: String, - pub target_name: String, -} - -#[derive(LintDiagnostic)] #[diag(passes_inline_ignored_for_exported)] #[help] pub(crate) struct InlineIgnoredForExported {} @@ -1841,26 +1570,3 @@ pub(crate) struct ReprAlignShouldBeAlign { pub span: Span, pub item: &'static str, } - -#[derive(Diagnostic)] -#[diag(passes_align_should_be_repr_align)] -pub(crate) struct AlignShouldBeReprAlign { - #[primary_span] - #[suggestion( - style = "verbose", - applicability = "machine-applicable", - code = "#[repr(align({align_bytes}))]" - )] - pub span: Span, - pub item: &'static str, - pub align_bytes: u64, -} - -#[derive(Diagnostic)] -#[diag(passes_align_attr_application)] -pub(crate) struct AlignAttrApplication { - #[primary_span] - pub hint_span: Span, - #[label] - pub span: Span, -} diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index 6fac01827a4..141a60a8ec3 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -329,7 +329,7 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> { match &self.parent_item.unwrap().kind { ast::ItemKind::Impl(i) => { if i.of_trait.is_some() { - Target::Method(MethodKind::Trait { body }) + Target::Method(MethodKind::TraitImpl) } else { Target::Method(MethodKind::Inherent) } diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index ceef558c0cf..d5ff8a4b609 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -242,6 +242,9 @@ resolve_lowercase_self = attempt to use a non-constant value in a constant .suggestion = try using `Self` +resolve_macro_cannot_use_as_fn_like = + `{$ident}` exists, but has no rules for function-like invocation + resolve_macro_cannot_use_as_attr = `{$ident}` exists, but has no `attr` rules diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 3fee2ab6afe..580fa4f5b2c 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -971,40 +971,35 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { let imported_binding = self.r.import(binding, import); if ident.name != kw::Underscore && parent == self.r.graph_root { let norm_ident = Macros20NormalizedIdent::new(ident); + // FIXME: this error is technically unnecessary now when extern prelude is split into + // two scopes, remove it with lang team approval. if let Some(entry) = self.r.extern_prelude.get(&norm_ident) && expansion != LocalExpnId::ROOT && orig_name.is_some() - && !entry.is_import() + && entry.item_binding.is_none() { self.r.dcx().emit_err( errors::MacroExpandedExternCrateCannotShadowExternArguments { span: item.span }, ); - // `return` is intended to discard this binding because it's an - // unregistered ambiguity error which would result in a panic - // caused by inconsistency `path_res` - // more details: https://github.com/rust-lang/rust/pull/111761 - return; } use indexmap::map::Entry; match self.r.extern_prelude.entry(norm_ident) { Entry::Occupied(mut occupied) => { let entry = occupied.get_mut(); - if let Some(old_binding) = entry.binding.get() - && old_binding.is_import() - { + if entry.item_binding.is_some() { let msg = format!("extern crate `{ident}` already in extern prelude"); self.r.tcx.dcx().span_delayed_bug(item.span, msg); } else { - // Binding from `extern crate` item in source code can replace - // a binding from `--extern` on command line here. - entry.binding.set(Some(imported_binding)); + entry.item_binding = Some(imported_binding); entry.introduced_by_item = orig_name.is_some(); } entry } Entry::Vacant(vacant) => vacant.insert(ExternPreludeEntry { - binding: Cell::new(Some(imported_binding)), + item_binding: Some(imported_binding), + flag_binding: Cell::new(None), + only_item: true, introduced_by_item: true, }), }; @@ -1232,7 +1227,8 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { ItemKind::Fn(box ast::Fn { ident: fn_ident, .. }) => { match self.proc_macro_stub(item, *fn_ident) { Some((macro_kind, ident, span)) => { - let res = Res::Def(DefKind::Macro(macro_kind), def_id.to_def_id()); + let macro_kinds = macro_kind.into(); + let res = Res::Def(DefKind::Macro(macro_kinds), def_id.to_def_id()); let macro_data = MacroData::new(self.r.dummy_ext(macro_kind)); self.r.new_local_macro(def_id, macro_data); self.r.proc_macro_stubs.insert(def_id); diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 7d51fef28d3..14538df8187 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -5,6 +5,7 @@ use rustc_ast::*; use rustc_attr_parsing::{AttributeParser, Early, OmitDoc, ShouldEmit}; use rustc_expand::expand::AstFragment; use rustc_hir as hir; +use rustc_hir::Target; use rustc_hir::def::{CtorKind, CtorOf, DefKind}; use rustc_hir::def_id::LocalDefId; use rustc_middle::span_bug; @@ -138,6 +139,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { &i.attrs, i.span, i.id, + Target::MacroDef, OmitDoc::Skip, std::convert::identity, |_l| { @@ -149,9 +151,9 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { let macro_data = self.resolver.compile_macro(def, *ident, &attrs, i.span, i.id, edition); - let macro_kind = macro_data.ext.macro_kind(); + let macro_kinds = macro_data.ext.macro_kinds(); opt_macro_data = Some(macro_data); - DefKind::Macro(macro_kind) + DefKind::Macro(macro_kinds) } ItemKind::GlobalAsm(..) => DefKind::GlobalAsm, ItemKind::Use(use_tree) => { diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 210ab72678c..c5fcbdfb42f 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -13,7 +13,7 @@ use rustc_errors::{ use rustc_feature::BUILTIN_ATTRIBUTES; use rustc_hir::attrs::{AttributeKind, CfgEntry, StrippedCfgItem}; use rustc_hir::def::Namespace::{self, *}; -use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind, PerNS}; +use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, MacroKinds, NonMacroAttrKind, PerNS}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; use rustc_hir::{PrimTy, Stability, StabilityLevel, find_attr}; use rustc_middle::bug; @@ -1016,16 +1016,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .emit() } - /// Lookup typo candidate in scope for a macro or import. - fn early_lookup_typo_candidate( + pub(crate) fn add_scope_set_candidates( &mut self, + suggestions: &mut Vec<TypoSuggestion>, scope_set: ScopeSet<'ra>, parent_scope: &ParentScope<'ra>, - ident: Ident, + ctxt: SyntaxContext, filter_fn: &impl Fn(Res) -> bool, - ) -> Option<TypoSuggestion> { - let mut suggestions = Vec::new(); - let ctxt = ident.span.ctxt(); + ) { self.cm().visit_scopes(scope_set, parent_scope, ctxt, |this, scope, use_prelude, _| { match scope { Scope::DeriveHelpers(expn_id) => { @@ -1041,28 +1039,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } Scope::DeriveHelpersCompat => { - let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat); - if filter_fn(res) { - for derive in parent_scope.derives { - let parent_scope = &ParentScope { derives: &[], ..*parent_scope }; - let Ok((Some(ext), _)) = this.reborrow().resolve_macro_path( - derive, - Some(MacroKind::Derive), - parent_scope, - false, - false, - None, - None, - ) else { - continue; - }; - suggestions.extend( - ext.helper_attrs - .iter() - .map(|name| TypoSuggestion::typo_from_name(*name, res)), - ); - } - } + // Never recommend deprecated helper attributes. } Scope::MacroRules(macro_rules_scope) => { if let MacroRulesScope::Binding(macro_rules_binding) = macro_rules_scope.get() { @@ -1076,7 +1053,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } Scope::Module(module, _) => { - this.add_module_candidates(module, &mut suggestions, filter_fn, None); + this.add_module_candidates(module, suggestions, filter_fn, None); } Scope::MacroUsePrelude => { suggestions.extend(this.macro_use_prelude.iter().filter_map( @@ -1096,12 +1073,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ); } } - Scope::ExternPrelude => { + Scope::ExternPreludeItems => { + // Add idents from both item and flag scopes. suggestions.extend(this.extern_prelude.keys().filter_map(|ident| { let res = Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id()); filter_fn(res).then_some(TypoSuggestion::typo_from_ident(ident.0, res)) })); } + Scope::ExternPreludeFlags => {} Scope::ToolPrelude => { let res = Res::NonMacroAttr(NonMacroAttrKind::Tool); suggestions.extend( @@ -1132,6 +1111,19 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { None::<()> }); + } + + /// Lookup typo candidate in scope for a macro or import. + fn early_lookup_typo_candidate( + &mut self, + scope_set: ScopeSet<'ra>, + parent_scope: &ParentScope<'ra>, + ident: Ident, + filter_fn: &impl Fn(Res) -> bool, + ) -> Option<TypoSuggestion> { + let mut suggestions = Vec::new(); + let ctxt = ident.span.ctxt(); + self.add_scope_set_candidates(&mut suggestions, scope_set, parent_scope, ctxt, filter_fn); // Make sure error reporting is deterministic. suggestions.sort_by(|a, b| a.candidate.as_str().cmp(b.candidate.as_str())); @@ -1491,11 +1483,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let Some(binding) = resolution.borrow().best_binding() else { continue; }; - let Res::Def(DefKind::Macro(MacroKind::Derive | MacroKind::Attr), def_id) = - binding.res() - else { + let Res::Def(DefKind::Macro(kinds), def_id) = binding.res() else { continue; }; + if !kinds.intersects(MacroKinds::ATTR | MacroKinds::DERIVE) { + continue; + } // By doing this all *imported* macros get added to the `macro_map` even if they // are *unused*, which makes the later suggestions find them and work. let _ = this.get_macro_by_def_id(def_id); @@ -1504,7 +1497,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }, ); - let is_expected = &|res: Res| res.macro_kind() == Some(macro_kind); + let is_expected = + &|res: Res| res.macro_kinds().is_some_and(|k| k.contains(macro_kind.into())); let suggestion = self.early_lookup_typo_candidate( ScopeSet::Macro(macro_kind), parent_scope, @@ -1553,11 +1547,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if let Some((def_id, unused_ident)) = unused_macro { let scope = self.local_macro_def_scopes[&def_id]; let parent_nearest = parent_scope.module.nearest_parent_mod(); - if Some(parent_nearest) == scope.opt_def_id() { + let unused_macro_kinds = self.local_macro_map[def_id].ext.macro_kinds(); + if !unused_macro_kinds.contains(macro_kind.into()) { match macro_kind { MacroKind::Bang => { - err.subdiagnostic(MacroDefinedLater { span: unused_ident.span }); - err.subdiagnostic(MacroSuggMovePosition { span: ident.span, ident }); + err.subdiagnostic(MacroRulesNot::Func { span: unused_ident.span, ident }); } MacroKind::Attr => { err.subdiagnostic(MacroRulesNot::Attr { span: unused_ident.span, ident }); @@ -1566,14 +1560,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { err.subdiagnostic(MacroRulesNot::Derive { span: unused_ident.span, ident }); } } - return; } - } - - if self.macro_names.contains(&ident.normalize_to_macros_2_0()) { - err.subdiagnostic(AddedMacroUse); - return; + if Some(parent_nearest) == scope.opt_def_id() { + err.subdiagnostic(MacroDefinedLater { span: unused_ident.span }); + err.subdiagnostic(MacroSuggMovePosition { span: ident.span, ident }); + return; + } } if ident.name == kw::Default @@ -1601,13 +1594,18 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }; let desc = match binding.res() { - Res::Def(DefKind::Macro(MacroKind::Bang), _) => "a function-like macro".to_string(), - Res::Def(DefKind::Macro(MacroKind::Attr), _) | Res::NonMacroAttr(..) => { + Res::Def(DefKind::Macro(MacroKinds::BANG), _) => { + "a function-like macro".to_string() + } + Res::Def(DefKind::Macro(MacroKinds::ATTR), _) | Res::NonMacroAttr(..) => { format!("an attribute: `#[{ident}]`") } - Res::Def(DefKind::Macro(MacroKind::Derive), _) => { + Res::Def(DefKind::Macro(MacroKinds::DERIVE), _) => { format!("a derive macro: `#[derive({ident})]`") } + Res::Def(DefKind::Macro(kinds), _) => { + format!("{} {}", kinds.article(), kinds.descr()) + } Res::ToolMod => { // Don't confuse the user with tool modules. continue; @@ -1644,6 +1642,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { err.subdiagnostic(note); return; } + + if self.macro_names.contains(&ident.normalize_to_macros_2_0()) { + err.subdiagnostic(AddedMacroUse); + return; + } } /// Given an attribute macro that failed to be resolved, look for `derive` macros that could @@ -1862,14 +1865,20 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } - fn ambiguity_diagnostics(&self, ambiguity_error: &AmbiguityError<'_>) -> AmbiguityErrorDiag { + fn ambiguity_diagnostics(&self, ambiguity_error: &AmbiguityError<'ra>) -> AmbiguityErrorDiag { let AmbiguityError { kind, ident, b1, b2, misc1, misc2, .. } = *ambiguity_error; + let extern_prelude_ambiguity = || { + self.extern_prelude.get(&Macros20NormalizedIdent::new(ident)).is_some_and(|entry| { + entry.item_binding == Some(b1) && entry.flag_binding.get() == Some(b2) + }) + }; let (b1, b2, misc1, misc2, swapped) = if b2.span.is_dummy() && !b1.span.is_dummy() { // We have to print the span-less alternative first, otherwise formatting looks bad. (b2, b1, misc2, misc1, true) } else { (b1, b2, misc1, misc2, false) }; + let could_refer_to = |b: NameBinding<'_>, misc: AmbiguityErrorMisc, also: &str| { let what = self.binding_description(b, ident, misc == AmbiguityErrorMisc::FromPrelude); let note_msg = format!("`{ident}` could{also} refer to {what}"); @@ -1885,7 +1894,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { "consider adding an explicit import of `{ident}` to disambiguate" )) } - if b.is_extern_crate() && ident.span.at_least_rust_2018() { + if b.is_extern_crate() && ident.span.at_least_rust_2018() && !extern_prelude_ambiguity() + { help_msgs.push(format!("use `::{ident}` to refer to this {thing} unambiguously")) } match misc { @@ -2748,9 +2758,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let binding_key = BindingKey::new(ident, MacroNS); let binding = self.resolution(crate_module, binding_key)?.binding()?; - let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() else { + let Res::Def(DefKind::Macro(kinds), _) = binding.res() else { return None; }; + if !kinds.contains(MacroKinds::BANG) { + return None; + } let module_name = crate_module.kind.name().unwrap_or(kw::Crate); let import_snippet = match import.kind { ImportKind::Single { source, target, .. } if source != target => { diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 2747ba135ed..a1d62ba7a68 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -672,6 +672,12 @@ pub(crate) struct MacroSuggMovePosition { #[derive(Subdiagnostic)] pub(crate) enum MacroRulesNot { + #[label(resolve_macro_cannot_use_as_fn_like)] + Func { + #[primary_span] + span: Span, + ident: Ident, + }, #[label(resolve_macro_cannot_use_as_attr)] Attr { #[primary_span] diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 9efcef695b7..dc01c94af57 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -2,7 +2,7 @@ use Determinacy::*; use Namespace::*; use rustc_ast::{self as ast, NodeId}; use rustc_errors::ErrorGuaranteed; -use rustc_hir::def::{DefKind, Namespace, NonMacroAttrKind, PartialRes, PerNS}; +use rustc_hir::def::{DefKind, MacroKinds, Namespace, NonMacroAttrKind, PartialRes, PerNS}; use rustc_middle::bug; use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK; @@ -102,6 +102,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ScopeSet::All(ns) | ScopeSet::ModuleAndExternPrelude(ns, _) | ScopeSet::Late(ns, ..) => (ns, None), + ScopeSet::ExternPrelude => (TypeNS, None), ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind)), }; let module = match scope_set { @@ -111,8 +112,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { _ => parent_scope.module.nearest_item_scope(), }; let module_and_extern_prelude = matches!(scope_set, ScopeSet::ModuleAndExternPrelude(..)); + let extern_prelude = matches!(scope_set, ScopeSet::ExternPrelude); let mut scope = match ns { _ if module_and_extern_prelude => Scope::Module(module, None), + _ if extern_prelude => Scope::ExternPreludeItems, TypeNS | ValueNS => Scope::Module(module, None), MacroNS => Scope::DeriveHelpers(parent_scope.expansion), }; @@ -143,7 +146,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Scope::Module(..) => true, Scope::MacroUsePrelude => use_prelude || rust_2015, Scope::BuiltinAttrs => true, - Scope::ExternPrelude => use_prelude || module_and_extern_prelude, + Scope::ExternPreludeItems | Scope::ExternPreludeFlags => { + use_prelude || module_and_extern_prelude || extern_prelude + } Scope::ToolPrelude => use_prelude, Scope::StdLibPrelude => use_prelude || ns == MacroNS, Scope::BuiltinTypes => true, @@ -182,7 +187,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Scope::Module(..) if module_and_extern_prelude => match ns { TypeNS => { ctxt.adjust(ExpnId::root()); - Scope::ExternPrelude + Scope::ExternPreludeItems } ValueNS | MacroNS => break, }, @@ -199,7 +204,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { None => { ctxt.adjust(ExpnId::root()); match ns { - TypeNS => Scope::ExternPrelude, + TypeNS => Scope::ExternPreludeItems, ValueNS => Scope::StdLibPrelude, MacroNS => Scope::MacroUsePrelude, } @@ -208,8 +213,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } Scope::MacroUsePrelude => Scope::StdLibPrelude, Scope::BuiltinAttrs => break, // nowhere else to search - Scope::ExternPrelude if module_and_extern_prelude => break, - Scope::ExternPrelude => Scope::ToolPrelude, + Scope::ExternPreludeItems => Scope::ExternPreludeFlags, + Scope::ExternPreludeFlags if module_and_extern_prelude || extern_prelude => break, + Scope::ExternPreludeFlags => Scope::ToolPrelude, Scope::ToolPrelude => Scope::StdLibPrelude, Scope::StdLibPrelude => match ns { TypeNS => Scope::BuiltinTypes, @@ -259,7 +265,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { { let ext = &self.get_macro_by_def_id(def_id).ext; if ext.builtin_name.is_none() - && ext.macro_kind() == MacroKind::Derive + && ext.macro_kinds() == MacroKinds::DERIVE && parent.expansion.outer_expn_is_descendant_of(*ctxt) { return Some((parent, derive_fallback_lint_id)); @@ -413,6 +419,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ScopeSet::All(ns) | ScopeSet::ModuleAndExternPrelude(ns, _) | ScopeSet::Late(ns, ..) => (ns, None), + ScopeSet::ExternPrelude => (TypeNS, None), ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind)), }; @@ -429,6 +436,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // to detect potential ambiguities. let mut innermost_result: Option<(NameBinding<'_>, Flags)> = None; let mut determinacy = Determinacy::Determined; + // Shadowed bindings don't need to be marked as used or non-speculatively loaded. + macro finalize_scope() { + if innermost_result.is_none() { finalize } else { None } + } // Go through all the scopes and try to resolve the name. let break_result = self.visit_scopes( @@ -448,17 +459,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } Scope::DeriveHelpersCompat => { - // FIXME: Try running this logic earlier, to allocate name bindings for - // legacy derive helpers when creating an attribute invocation with - // following derives. Legacy derive helpers are not common, so it shouldn't - // affect performance. It should also allow to remove the `derives` - // component from `ParentScope`. let mut result = Err(Determinacy::Determined); for derive in parent_scope.derives { let parent_scope = &ParentScope { derives: &[], ..*parent_scope }; match this.reborrow().resolve_macro_path( derive, - Some(MacroKind::Derive), + MacroKind::Derive, parent_scope, true, force, @@ -494,7 +500,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { _ => Err(Determinacy::Determined), }, Scope::Module(module, derive_fallback_lint_id) => { - let (adjusted_parent_scope, finalize) = + // FIXME: use `finalize_scope` here. + let (adjusted_parent_scope, adjusted_finalize) = if matches!(scope_set, ScopeSet::ModuleAndExternPrelude(..)) { (parent_scope, finalize) } else { @@ -513,7 +520,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } else { Shadowing::Restricted }, - finalize, + adjusted_finalize, ignore_binding, ignore_import, ); @@ -561,14 +568,21 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Some(binding) => Ok((*binding, Flags::empty())), None => Err(Determinacy::Determined), }, - Scope::ExternPrelude => { - match this.reborrow().extern_prelude_get(ident, finalize.is_some()) { + Scope::ExternPreludeItems => { + // FIXME: use `finalize_scope` here. + match this.reborrow().extern_prelude_get_item(ident, finalize.is_some()) { Some(binding) => Ok((binding, Flags::empty())), None => Err(Determinacy::determined( this.graph_root.unexpanded_invocations.borrow().is_empty(), )), } } + Scope::ExternPreludeFlags => { + match this.extern_prelude_get_flag(ident, finalize_scope!().is_some()) { + Some(binding) => Ok((binding, Flags::empty())), + None => Err(Determinacy::Determined), + } + } Scope::ToolPrelude => match this.registered_tool_bindings.get(&ident) { Some(binding) => Ok((*binding, Flags::empty())), None => Err(Determinacy::Determined), @@ -599,8 +613,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if matches!(ident.name, sym::f16) && !this.tcx.features().f16() && !ident.span.allows_unstable(sym::f16) - && finalize.is_some() - && innermost_result.is_none() + && finalize_scope!().is_some() { feature_err( this.tcx.sess, @@ -613,8 +626,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if matches!(ident.name, sym::f128) && !this.tcx.features().f128() && !ident.span.allows_unstable(sym::f128) - && finalize.is_some() - && innermost_result.is_none() + && finalize_scope!().is_some() { feature_err( this.tcx.sess, @@ -632,17 +644,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { match result { Ok((binding, flags)) => { - let binding_macro_kind = binding.macro_kind(); - // If we're looking for an attribute, that might be supported by a - // `macro_rules!` macro. - // FIXME: Replace this with tracking multiple macro kinds for one Def. - if !(sub_namespace_match(binding_macro_kind, macro_kind) - || (binding_macro_kind == Some(MacroKind::Bang) - && macro_kind == Some(MacroKind::Attr) - && this - .get_macro(binding.res()) - .is_some_and(|macro_data| macro_data.attr_ext.is_some()))) - { + if !sub_namespace_match(binding.macro_kinds(), macro_kind) { return None; } @@ -829,15 +831,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { assert_eq!(shadowing, Shadowing::Unrestricted); return if ns != TypeNS { Err((Determined, Weak::No)) - } else if let Some(binding) = - self.reborrow().extern_prelude_get(ident, finalize.is_some()) - { - Ok(binding) - } else if !self.graph_root.unexpanded_invocations.borrow().is_empty() { - // Macro-expanded `extern crate` items can add names to extern prelude. - Err((Undetermined, Weak::No)) } else { - Err((Determined, Weak::No)) + let binding = self.early_resolve_ident_in_lexical_scope( + ident, + ScopeSet::ExternPrelude, + parent_scope, + finalize, + finalize.is_some(), + ignore_binding, + ignore_import, + ); + return binding.map_err(|determinacy| (determinacy, Weak::No)); }; } ModuleOrUniformRoot::CurrentScope => { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index e52cbeb733a..1e4ab57a316 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -4315,7 +4315,6 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { qself, path, ns, - path_span, source.defer_to_typeck(), finalize, source, @@ -4438,7 +4437,6 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { qself: &Option<Box<QSelf>>, path: &[Segment], primary_ns: Namespace, - span: Span, defer_to_typeck: bool, finalize: Finalize, source: PathSource<'_, 'ast, 'ra>, @@ -4463,21 +4461,11 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } assert!(primary_ns != MacroNS); - - if qself.is_none() { - let path_seg = |seg: &Segment| PathSegment::from_ident(seg.ident); - let path = Path { segments: path.iter().map(path_seg).collect(), span, tokens: None }; - if let Ok((_, res)) = self.r.cm().resolve_macro_path( - &path, - None, - &self.parent_scope, - false, - false, - None, - None, - ) { - return Ok(Some(PartialRes::new(res))); - } + if qself.is_none() + && let PathResult::NonModule(res) = + self.r.cm().maybe_resolve_path(path, Some(MacroNS), &self.parent_scope, None) + { + return Ok(Some(res)); } Ok(fin_res) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index aca251da71d..6a753b38035 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -19,14 +19,13 @@ use rustc_errors::{ }; use rustc_hir as hir; use rustc_hir::def::Namespace::{self, *}; -use rustc_hir::def::{self, CtorKind, CtorOf, DefKind}; +use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, MacroKinds}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; use rustc_hir::{MissingLifetimeKind, PrimTy}; use rustc_middle::ty; use rustc_session::{Session, lint}; use rustc_span::edit_distance::{edit_distance, find_best_match_for_name}; use rustc_span::edition::Edition; -use rustc_span::hygiene::MacroKind; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym}; use thin_vec::ThinVec; use tracing::debug; @@ -39,8 +38,8 @@ use crate::late::{ }; use crate::ty::fast_reject::SimplifiedType; use crate::{ - Module, ModuleKind, ModuleOrUniformRoot, PathResult, PathSource, Resolver, Segment, errors, - path_names_to_string, + Module, ModuleKind, ModuleOrUniformRoot, PathResult, PathSource, Resolver, ScopeSet, Segment, + errors, path_names_to_string, }; type Res = def::Res<ast::NodeId>; @@ -1850,12 +1849,12 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { match (res, source) { ( - Res::Def(DefKind::Macro(MacroKind::Bang), def_id), + Res::Def(DefKind::Macro(kinds), def_id), PathSource::Expr(Some(Expr { kind: ExprKind::Index(..) | ExprKind::Call(..), .. })) | PathSource::Struct(_), - ) => { + ) if kinds.contains(MacroKinds::BANG) => { // Don't suggest macro if it's unstable. let suggestable = def_id.is_local() || self.r.tcx.lookup_stability(def_id).is_none_or(|s| s.is_stable()); @@ -1880,7 +1879,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { err.note("if you want the `try` keyword, you need Rust 2018 or later"); } } - (Res::Def(DefKind::Macro(MacroKind::Bang), _), _) => { + (Res::Def(DefKind::Macro(kinds), _), _) if kinds.contains(MacroKinds::BANG) => { err.span_label(span, fallback_label.to_string()); } (Res::Def(DefKind::TyAlias, def_id), PathSource::Trait(_)) => { @@ -2459,44 +2458,29 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } } + if let RibKind::Module(module) = rib.kind + && let ModuleKind::Block = module.kind + { + self.r.add_module_candidates(module, &mut names, &filter_fn, Some(ctxt)); + } else if let RibKind::Module(module) = rib.kind { + // Encountered a module item, abandon ribs and look into that module and preludes. + self.r.add_scope_set_candidates( + &mut names, + ScopeSet::Late(ns, module, None), + &self.parent_scope, + ctxt, + filter_fn, + ); + break; + } + if let RibKind::MacroDefinition(def) = rib.kind && def == self.r.macro_def(ctxt) { // If an invocation of this macro created `ident`, give up on `ident` // and switch to `ident`'s source from the macro definition. ctxt.remove_mark(); - continue; } - - // Items in scope - if let RibKind::Module(module) = rib.kind { - // Items from this module - self.r.add_module_candidates(module, &mut names, &filter_fn, Some(ctxt)); - - if let ModuleKind::Block = module.kind { - // We can see through blocks - } else { - // Items from the prelude - if !module.no_implicit_prelude { - names.extend(self.r.extern_prelude.keys().flat_map(|ident| { - let res = Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id()); - filter_fn(res) - .then_some(TypoSuggestion::typo_from_ident(ident.0, res)) - })); - - if let Some(prelude) = self.r.prelude { - self.r.add_module_candidates(prelude, &mut names, &filter_fn, None); - } - } - break; - } - } - } - // Add primitive types to the mix - if filter_fn(Res::PrimTy(PrimTy::Bool)) { - names.extend(PrimTy::ALL.iter().map(|prim_ty| { - TypoSuggestion::typo_from_name(prim_ty.name(), Res::PrimTy(*prim_ty)) - })) } } else { // Search in module. diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index b43f71913d9..ca9c124fca6 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -15,6 +15,8 @@ #![feature(arbitrary_self_types)] #![feature(assert_matches)] #![feature(box_patterns)] +#![feature(decl_macro)] +#![feature(default_field_values)] #![feature(if_let_guard)] #![feature(iter_intersperse)] #![feature(rustc_attrs)] @@ -53,7 +55,8 @@ use rustc_feature::BUILTIN_ATTRIBUTES; use rustc_hir::attrs::StrippedCfgItem; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{ - self, CtorOf, DefKind, DocLinkResMap, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS, + self, CtorOf, DefKind, DocLinkResMap, LifetimeRes, MacroKinds, NonMacroAttrKind, PartialRes, + PerNS, }; use rustc_hir::def_id::{CRATE_DEF_ID, CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap}; use rustc_hir::definitions::DisambiguatorState; @@ -113,34 +116,46 @@ impl Determinacy { } /// A specific scope in which a name can be looked up. -/// This enum is currently used only for early resolution (imports and macros), -/// but not for late resolution yet. #[derive(Clone, Copy, Debug)] enum Scope<'ra> { + /// Inert attributes registered by derive macros. DeriveHelpers(LocalExpnId), + /// Inert attributes registered by derive macros, but used before they are actually declared. + /// This scope will exist until the compatibility lint `LEGACY_DERIVE_HELPERS` + /// is turned into a hard error. DeriveHelpersCompat, + /// Textual `let`-like scopes introduced by `macro_rules!` items. MacroRules(MacroRulesScopeRef<'ra>), - // The node ID is for reporting the `PROC_MACRO_DERIVE_RESOLUTION_FALLBACK` - // lint if it should be reported. + /// Names declared in the given module. + /// The node ID is for reporting the `PROC_MACRO_DERIVE_RESOLUTION_FALLBACK` + /// lint if it should be reported. Module(Module<'ra>, Option<NodeId>), + /// Names introduced by `#[macro_use]` attributes on `extern crate` items. MacroUsePrelude, + /// Built-in attributes. BuiltinAttrs, - ExternPrelude, + /// Extern prelude names introduced by `extern crate` items. + ExternPreludeItems, + /// Extern prelude names introduced by `--extern` flags. + ExternPreludeFlags, + /// Tool modules introduced with `#![register_tool]`. ToolPrelude, + /// Standard library prelude introduced with an internal `#[prelude_import]` import. StdLibPrelude, + /// Built-in types. BuiltinTypes, } /// Names from different contexts may want to visit different subsets of all specific scopes /// with different restrictions when looking up the resolution. -/// This enum is currently used only for early resolution (imports and macros), -/// but not for late resolution yet. #[derive(Clone, Copy, Debug)] enum ScopeSet<'ra> { /// All scopes with the given namespace. All(Namespace), /// A module, then extern prelude (used for mixed 2015-2018 mode in macros). ModuleAndExternPrelude(Namespace, Module<'ra>), + /// Just two extern prelude scopes. + ExternPrelude, /// All scopes with macro namespace and the given macro kind restriction. Macro(MacroKind), /// All scopes with the given namespace, used for partially performing late resolution. @@ -969,8 +984,8 @@ impl<'ra> NameBindingData<'ra> { matches!(self.res(), Res::Def(DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy, _)) } - fn macro_kind(&self) -> Option<MacroKind> { - self.res().macro_kind() + fn macro_kinds(&self) -> Option<MacroKinds> { + self.res().macro_kinds() } // Suppose that we resolved macro invocation with `invoc_parent_expansion` to binding `binding` @@ -1012,16 +1027,18 @@ impl<'ra> NameBindingData<'ra> { #[derive(Default, Clone)] struct ExternPreludeEntry<'ra> { - binding: Cell<Option<NameBinding<'ra>>>, + /// Binding from an `extern crate` item. + item_binding: Option<NameBinding<'ra>>, + /// Binding from an `--extern` flag, lazily populated on first use. + flag_binding: Cell<Option<NameBinding<'ra>>>, + /// There was no `--extern` flag introducing this name, + /// `flag_binding` doesn't need to be populated. + only_item: bool, + /// `item_binding` is non-redundant, happens either when `only_item` is true, + /// or when `extern crate` introducing `item_binding` used renaming. introduced_by_item: bool, } -impl ExternPreludeEntry<'_> { - fn is_import(&self) -> bool { - self.binding.get().is_some_and(|binding| binding.is_import()) - } -} - struct DeriveData { resolutions: Vec<DeriveResolution>, helper_attrs: Vec<(usize, Ident)>, @@ -1030,14 +1047,13 @@ struct DeriveData { struct MacroData { ext: Arc<SyntaxExtension>, - attr_ext: Option<Arc<SyntaxExtension>>, nrules: usize, macro_rules: bool, } impl MacroData { fn new(ext: Arc<SyntaxExtension>) -> MacroData { - MacroData { ext, attr_ext: None, nrules: 0, macro_rules: false } + MacroData { ext, nrules: 0, macro_rules: false } } } @@ -1060,7 +1076,7 @@ pub struct Resolver<'ra, 'tcx> { /// Assert that we are in speculative resolution mode. assert_speculative: bool, - prelude: Option<Module<'ra>>, + prelude: Option<Module<'ra>> = None, extern_prelude: FxIndexMap<Macros20NormalizedIdent, ExternPreludeEntry<'ra>>, /// N.B., this is used only for better diagnostics, not name resolution itself. @@ -1072,10 +1088,10 @@ pub struct Resolver<'ra, 'tcx> { field_visibility_spans: FxHashMap<DefId, Vec<Span>>, /// All imports known to succeed or fail. - determined_imports: Vec<Import<'ra>>, + determined_imports: Vec<Import<'ra>> = Vec::new(), /// All non-determined imports. - indeterminate_imports: Vec<Import<'ra>>, + indeterminate_imports: Vec<Import<'ra>> = Vec::new(), // Spans for local variables found during pattern resolution. // Used for suggestions during error reporting. @@ -1126,19 +1142,19 @@ pub struct Resolver<'ra, 'tcx> { /// Maps glob imports to the names of items actually imported. glob_map: FxIndexMap<LocalDefId, FxIndexSet<Symbol>>, - glob_error: Option<ErrorGuaranteed>, - visibilities_for_hashing: Vec<(LocalDefId, Visibility)>, + glob_error: Option<ErrorGuaranteed> = None, + visibilities_for_hashing: Vec<(LocalDefId, Visibility)> = Vec::new(), used_imports: FxHashSet<NodeId>, maybe_unused_trait_imports: FxIndexSet<LocalDefId>, /// Privacy errors are delayed until the end in order to deduplicate them. - privacy_errors: Vec<PrivacyError<'ra>>, + privacy_errors: Vec<PrivacyError<'ra>> = Vec::new(), /// Ambiguity errors are delayed for deduplication. - ambiguity_errors: Vec<AmbiguityError<'ra>>, + ambiguity_errors: Vec<AmbiguityError<'ra>> = Vec::new(), /// `use` injections are delayed for better placement and deduplication. - use_injections: Vec<UseError<'tcx>>, + use_injections: Vec<UseError<'tcx>> = Vec::new(), /// Crate-local macro expanded `macro_export` referred to by a module-relative path. - macro_expanded_macro_export_errors: BTreeSet<(Span, Span)>, + macro_expanded_macro_export_errors: BTreeSet<(Span, Span)> = BTreeSet::new(), arenas: &'ra ResolverArenas<'ra>, dummy_binding: NameBinding<'ra>, @@ -1190,9 +1206,9 @@ pub struct Resolver<'ra, 'tcx> { /// Avoid duplicated errors for "name already defined". name_already_seen: FxHashMap<Symbol, Span>, - potentially_unused_imports: Vec<Import<'ra>>, + potentially_unused_imports: Vec<Import<'ra>> = Vec::new(), - potentially_unnecessary_qualifications: Vec<UnnecessaryQualification<'ra>>, + potentially_unnecessary_qualifications: Vec<UnnecessaryQualification<'ra>> = Vec::new(), /// Table for mapping struct IDs into struct constructor IDs, /// it's not used during normal resolution, only for better error reporting. @@ -1201,7 +1217,7 @@ pub struct Resolver<'ra, 'tcx> { lint_buffer: LintBuffer, - next_node_id: NodeId, + next_node_id: NodeId = CRATE_NODE_ID, node_id_to_def_id: NodeMap<Feed<'tcx, LocalDefId>>, @@ -1219,17 +1235,17 @@ pub struct Resolver<'ra, 'tcx> { item_generics_num_lifetimes: FxHashMap<LocalDefId, usize>, delegation_fn_sigs: LocalDefIdMap<DelegationFnSig>, - main_def: Option<MainDefinition>, + main_def: Option<MainDefinition> = None, trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>, /// A list of proc macro LocalDefIds, written out in the order in which /// they are declared in the static array generated by proc_macro_harness. - proc_macros: Vec<LocalDefId>, + proc_macros: Vec<LocalDefId> = Vec::new(), confused_type_with_std_module: FxIndexMap<Span, Span>, /// Whether lifetime elision was successful. lifetime_elision_allowed: FxHashSet<NodeId>, /// Names of items that were stripped out via cfg with their corresponding cfg meta item. - stripped_cfg_items: Vec<StrippedCfgItem<NodeId>>, + stripped_cfg_items: Vec<StrippedCfgItem<NodeId>> = Vec::new(), effective_visibilities: EffectiveVisibilities, doc_link_resolutions: FxIndexMap<LocalDefId, DocLinkResMap>, @@ -1543,9 +1559,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { field_defaults: Default::default(), field_visibility_spans: FxHashMap::default(), - determined_imports: Vec::new(), - indeterminate_imports: Vec::new(), - pat_span_map: Default::default(), partial_res_map: Default::default(), import_res_map: Default::default(), @@ -1564,16 +1577,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ast_transform_scopes: FxHashMap::default(), glob_map: Default::default(), - glob_error: None, - visibilities_for_hashing: Default::default(), used_imports: FxHashSet::default(), maybe_unused_trait_imports: Default::default(), - privacy_errors: Vec::new(), - ambiguity_errors: Vec::new(), - use_injections: Vec::new(), - macro_expanded_macro_export_errors: BTreeSet::new(), - arenas, dummy_binding: arenas.new_pub_res_binding(Res::Err, DUMMY_SP, LocalExpnId::ROOT), builtin_types_bindings: PrimTy::ALL @@ -1617,8 +1623,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { derive_data: Default::default(), local_macro_def_scopes: FxHashMap::default(), name_already_seen: FxHashMap::default(), - potentially_unused_imports: Vec::new(), - potentially_unnecessary_qualifications: Default::default(), struct_constructors: Default::default(), unused_macros: Default::default(), unused_macro_rules: Default::default(), @@ -1628,16 +1632,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { builtin_attrs: Default::default(), containers_deriving_copy: Default::default(), lint_buffer: LintBuffer::default(), - next_node_id: CRATE_NODE_ID, node_id_to_def_id, disambiguator: DisambiguatorState::new(), placeholder_field_indices: Default::default(), invocation_parents, legacy_const_generic_args: Default::default(), item_generics_num_lifetimes: Default::default(), - main_def: Default::default(), trait_impls: Default::default(), - proc_macros: Default::default(), confused_type_with_std_module: Default::default(), lifetime_elision_allowed: Default::default(), stripped_cfg_items: Default::default(), @@ -1652,6 +1653,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { current_crate_outer_attr_insert_span, mods_with_parse_errors: Default::default(), impl_trait_names: Default::default(), + .. }; let root_parent_scope = ParentScope::module(graph_root, resolver.arenas); @@ -1889,7 +1891,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { this.get_mut().traits_in_module(module, assoc_item, &mut found_traits); } } - Scope::ExternPrelude | Scope::ToolPrelude | Scope::BuiltinTypes => {} + Scope::ExternPreludeItems + | Scope::ExternPreludeFlags + | Scope::ToolPrelude + | Scope::BuiltinTypes => {} _ => unreachable!(), } None::<()> @@ -2054,7 +2059,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // but not introduce it, as used if they are accessed from lexical scope. if used == Used::Scope { if let Some(entry) = self.extern_prelude.get(&Macros20NormalizedIdent::new(ident)) { - if !entry.introduced_by_item && entry.binding.get() == Some(used_binding) { + if !entry.introduced_by_item && entry.item_binding == Some(used_binding) { return; } } @@ -2210,26 +2215,30 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } - fn extern_prelude_get<'r>( + fn extern_prelude_get_item<'r>( mut self: CmResolver<'r, 'ra, 'tcx>, ident: Ident, finalize: bool, ) -> Option<NameBinding<'ra>> { - let mut record_use = None; let entry = self.extern_prelude.get(&Macros20NormalizedIdent::new(ident)); - let binding = entry.and_then(|entry| match entry.binding.get() { - Some(binding) if binding.is_import() => { - if finalize { - record_use = Some(binding); - } - Some(binding) + entry.and_then(|entry| entry.item_binding).map(|binding| { + if finalize { + self.get_mut().record_use(ident, binding, Used::Scope); } + binding + }) + } + + fn extern_prelude_get_flag(&self, ident: Ident, finalize: bool) -> Option<NameBinding<'ra>> { + let entry = self.extern_prelude.get(&Macros20NormalizedIdent::new(ident)); + entry.and_then(|entry| match entry.flag_binding.get() { Some(binding) => { if finalize { self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span); } Some(binding) } + None if entry.only_item => None, None => { let crate_id = if finalize { self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span) @@ -2241,19 +2250,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let res = Res::Def(DefKind::Mod, crate_id.as_def_id()); let binding = self.arenas.new_pub_res_binding(res, DUMMY_SP, LocalExpnId::ROOT); - entry.binding.set(Some(binding)); + entry.flag_binding.set(Some(binding)); Some(binding) } None => finalize.then_some(self.dummy_binding), } } - }); - - if let Some(binding) = record_use { - self.get_mut().record_use(ident, binding, Used::Scope); - } - - binding + }) } /// Rustdoc uses this to resolve doc link paths in a recoverable way. `PathResult<'a>` diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 9173d0d3ea5..72ed8990241 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -1,7 +1,6 @@ //! A bunch of methods and structures more or less related to resolving macros and //! interface provided by `Resolver` to macro expander. -use std::any::Any; use std::cell::Cell; use std::mem; use std::sync::Arc; @@ -13,13 +12,13 @@ use rustc_expand::base::{ Annotatable, DeriveResolution, Indeterminate, ResolverExpand, SyntaxExtension, SyntaxExtensionKind, }; +use rustc_expand::compile_declarative_macro; use rustc_expand::expand::{ AstFragment, AstFragmentKind, Invocation, InvocationKind, SupportsMacroExpansion, }; -use rustc_expand::{MacroRulesMacroExpander, compile_declarative_macro}; use rustc_hir::StabilityLevel; use rustc_hir::attrs::{CfgEntry, StrippedCfgItem}; -use rustc_hir::def::{self, DefKind, Namespace, NonMacroAttrKind}; +use rustc_hir::def::{self, DefKind, MacroKinds, Namespace, NonMacroAttrKind}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_middle::middle::stability; use rustc_middle::ty::{RegisteredTools, TyCtxt}; @@ -86,22 +85,19 @@ pub(crate) type MacroRulesScopeRef<'ra> = &'ra Cell<MacroRulesScope<'ra>>; /// one for attribute-like macros (attributes, derives). /// We ignore resolutions from one sub-namespace when searching names in scope for another. pub(crate) fn sub_namespace_match( - candidate: Option<MacroKind>, + candidate: Option<MacroKinds>, requirement: Option<MacroKind>, ) -> bool { - #[derive(PartialEq)] - enum SubNS { - Bang, - AttrLike, - } - let sub_ns = |kind| match kind { - MacroKind::Bang => SubNS::Bang, - MacroKind::Attr | MacroKind::Derive => SubNS::AttrLike, - }; - let candidate = candidate.map(sub_ns); - let requirement = requirement.map(sub_ns); // "No specific sub-namespace" means "matches anything" for both requirements and candidates. - candidate.is_none() || requirement.is_none() || candidate == requirement + let (Some(candidate), Some(requirement)) = (candidate, requirement) else { + return true; + }; + match requirement { + MacroKind::Bang => candidate.contains(MacroKinds::BANG), + MacroKind::Attr | MacroKind::Derive => { + candidate.intersects(MacroKinds::ATTR | MacroKinds::DERIVE) + } + } } // We don't want to format a path using pretty-printing, @@ -323,6 +319,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { parent_scope.expansion, span, fast_print_path(path), + kind, def_id, def_id.map(|def_id| self.macro_def_scope(def_id).nearest_parent_mod()), ), @@ -356,11 +353,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { } let def_id = self.local_def_id(node_id); let m = &self.local_macro_map[&def_id]; - let SyntaxExtensionKind::LegacyBang(ref ext) = m.ext.kind else { - continue; - }; - let ext: &dyn Any = ext.as_ref(); - let Some(m) = ext.downcast_ref::<MacroRulesMacroExpander>() else { + let SyntaxExtensionKind::MacroRules(ref m) = m.ext.kind else { continue; }; for arm_i in unused_arms.iter() { @@ -405,7 +398,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { resolution.exts = Some( match self.cm().resolve_macro_path( &resolution.path, - Some(MacroKind::Derive), + MacroKind::Derive, &parent_scope, true, force, @@ -570,7 +563,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ) -> Result<(Arc<SyntaxExtension>, Res), Indeterminate> { let (ext, res) = match self.cm().resolve_macro_or_delegation_path( path, - Some(kind), + kind, parent_scope, true, force, @@ -633,7 +626,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { self.check_stability_and_deprecation(&ext, path, node_id); - let unexpected_res = if ext.macro_kind() != kind { + let unexpected_res = if !ext.macro_kinds().contains(kind.into()) { Some((kind.article(), kind.descr_expected())) } else if matches!(res, Res::Def(..)) { match supports_macro_expansion { @@ -665,7 +658,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Suggest moving the macro out of the derive() if the macro isn't Derive if !path.span.from_expansion() && kind == MacroKind::Derive - && ext.macro_kind() != MacroKind::Derive + && !ext.macro_kinds().contains(MacroKinds::DERIVE) + && ext.macro_kinds().contains(MacroKinds::ATTR) { err.remove_surrounding_derive = Some(RemoveSurroundingDerive { span: path.span }); err.add_as_non_derive = Some(AddAsNonDerive { macro_path: &path_str }); @@ -716,7 +710,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { pub(crate) fn resolve_macro_path<'r>( self: CmResolver<'r, 'ra, 'tcx>, path: &ast::Path, - kind: Option<MacroKind>, + kind: MacroKind, parent_scope: &ParentScope<'ra>, trace: bool, force: bool, @@ -739,7 +733,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { fn resolve_macro_or_delegation_path<'r>( mut self: CmResolver<'r, 'ra, 'tcx>, ast_path: &ast::Path, - kind: Option<MacroKind>, + kind: MacroKind, parent_scope: &ParentScope<'ra>, trace: bool, force: bool, @@ -753,7 +747,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Possibly apply the macro helper hack if deleg_impl.is_none() - && kind == Some(MacroKind::Bang) + && kind == MacroKind::Bang && let [segment] = path.as_slice() && segment.ident.span.ctxt().outer_expn_data().local_inner_macros { @@ -781,7 +775,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }; if trace { - let kind = kind.expect("macro kind must be specified if tracing is enabled"); // FIXME: Should be an output of Speculative Resolution. self.multi_segment_macro_resolutions.borrow_mut().push(( path, @@ -796,10 +789,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { self.prohibit_imported_non_macro_attrs(None, res.ok(), path_span); res } else { - let scope_set = kind.map_or(ScopeSet::All(MacroNS), ScopeSet::Macro); let binding = self.reborrow().early_resolve_ident_in_lexical_scope( path[0].ident, - scope_set, + ScopeSet::Macro(kind), parent_scope, None, force, @@ -811,7 +803,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } if trace { - let kind = kind.expect("macro kind must be specified if tracing is enabled"); // FIXME: Should be an output of Speculative Resolution. self.single_segment_macro_resolutions.borrow_mut().push(( path[0].ident, @@ -842,10 +833,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } _ => None, }, - None => self.get_macro(res).map(|macro_data| match kind { - Some(MacroKind::Attr) if let Some(ref ext) = macro_data.attr_ext => Arc::clone(ext), - _ => Arc::clone(¯o_data.ext), - }), + None => self.get_macro(res).map(|macro_data| Arc::clone(¯o_data.ext)), }; Ok((ext, res)) } @@ -1114,7 +1102,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { && let Some(binding) = binding // This is a `macro_rules` itself, not some import. && let NameBindingKind::Res(res) = binding.kind - && let Res::Def(DefKind::Macro(MacroKind::Bang), def_id) = res + && let Res::Def(DefKind::Macro(kinds), def_id) = res + && kinds.contains(MacroKinds::BANG) // And the `macro_rules` is defined inside the attribute's module, // so it cannot be in scope unless imported. && self.tcx.is_descendant_of(def_id, mod_def_id.to_def_id()) @@ -1161,8 +1150,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Reserve some names that are not quite covered by the general check // performed on `Resolver::builtin_attrs`. if ident.name == sym::cfg || ident.name == sym::cfg_attr { - let macro_kind = self.get_macro(res).map(|macro_data| macro_data.ext.macro_kind()); - if macro_kind.is_some() && sub_namespace_match(macro_kind, Some(MacroKind::Attr)) { + let macro_kinds = self.get_macro(res).map(|macro_data| macro_data.ext.macro_kinds()); + if macro_kinds.is_some() && sub_namespace_match(macro_kinds, Some(MacroKind::Attr)) { self.dcx() .emit_err(errors::NameReservedInAttributeNamespace { span: ident.span, ident }); } @@ -1181,7 +1170,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { node_id: NodeId, edition: Edition, ) -> MacroData { - let (mut ext, mut attr_ext, mut nrules) = compile_declarative_macro( + let (mut ext, mut nrules) = compile_declarative_macro( self.tcx.sess, self.tcx.features(), macro_def, @@ -1198,14 +1187,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // The macro is a built-in, replace its expander function // while still taking everything else from the source code. ext.kind = builtin_ext_kind.clone(); - attr_ext = None; nrules = 0; } else { self.dcx().emit_err(errors::CannotFindBuiltinMacroWithName { span, ident }); } } - MacroData { ext: Arc::new(ext), attr_ext, nrules, macro_rules: macro_def.macro_rules } + MacroData { ext: Arc::new(ext), nrules, macro_rules: macro_def.macro_rules } } fn path_accessible( diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 7c18fd89098..0e112edc733 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2165,6 +2165,8 @@ options! { "hash algorithm of source files used to check freshness in cargo (`blake3` or `sha256`)"), codegen_backend: Option<String> = (None, parse_opt_string, [TRACKED], "the backend to use"), + codegen_source_order: bool = (false, parse_bool, [UNTRACKED], + "emit mono items in the order of spans in source files (default: no)"), contract_checks: Option<bool> = (None, parse_opt_bool, [TRACKED], "emit runtime checks for contract pre- and post-conditions (default: no)"), coverage_options: CoverageOptions = (CoverageOptions::default(), parse_coverage_options, [TRACKED], diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index acbed7a9eed..416ce27367e 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -545,6 +545,7 @@ symbols! { autodiff_forward, autodiff_reverse, automatically_derived, + available_externally, avx, avx10_target_feature, avx512_target_feature, @@ -676,6 +677,7 @@ symbols! { cold_path, collapse_debuginfo, column, + common, compare_bytes, compare_exchange, compare_exchange_weak, @@ -956,6 +958,7 @@ symbols! { extern_prelude, extern_system_varargs, extern_types, + extern_weak, external, external_doc, f, @@ -1213,6 +1216,7 @@ symbols! { instruction_set, integer_: "integer", // underscore to avoid clashing with the function `sym::integer` below integral, + internal, internal_features, into_async_iter_into_iter, into_future, @@ -1287,6 +1291,8 @@ symbols! { linkage, linker, linker_messages, + linkonce, + linkonce_odr, lint_reasons, literal, load, @@ -2360,6 +2366,8 @@ symbols! { wasm_abi, wasm_import_module, wasm_target_feature, + weak, + weak_odr, where_clause_attrs, while_let, width, diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index a7f64085bd9..025fa299826 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -58,7 +58,7 @@ pub(super) fn mangle<'tcx>( let hash = get_symbol_hash(tcx, instance, instance_ty, instantiating_crate); - let mut p = SymbolPrinter { tcx, path: SymbolPath::new(), keep_within_component: false }; + let mut p = LegacySymbolMangler { tcx, path: SymbolPath::new(), keep_within_component: false }; p.print_def_path( def_id, if let ty::InstanceKind::DropGlue(_, _) @@ -213,13 +213,13 @@ impl SymbolPath { } } -struct SymbolPrinter<'tcx> { +struct LegacySymbolMangler<'tcx> { tcx: TyCtxt<'tcx>, path: SymbolPath, // When `true`, `finalize_pending_component` isn't used. - // This is needed when recursing into `path_qualified`, - // or `path_generic_args`, as any nested paths are + // This is needed when recursing into `print_path_with_qualified`, + // or `print_path_with_generic_args`, as any nested paths are // logically within one component. keep_within_component: bool, } @@ -228,7 +228,7 @@ struct SymbolPrinter<'tcx> { // `PrettyPrinter` aka pretty printing of e.g. types in paths, // symbol names should have their own printing machinery. -impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> { +impl<'tcx> Printer<'tcx> for LegacySymbolMangler<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -305,16 +305,17 @@ impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> { Ok(()) } - fn path_crate(&mut self, cnum: CrateNum) -> Result<(), PrintError> { + fn print_crate_name(&mut self, cnum: CrateNum) -> Result<(), PrintError> { self.write_str(self.tcx.crate_name(cnum).as_str())?; Ok(()) } - fn path_qualified( + + fn print_path_with_qualified( &mut self, self_ty: Ty<'tcx>, trait_ref: Option<ty::TraitRef<'tcx>>, ) -> Result<(), PrintError> { - // Similar to `pretty_path_qualified`, but for the other + // Similar to `pretty_print_path_with_qualified`, but for the other // types that are printed as paths (see `print_type` above). match self_ty.kind() { ty::FnDef(..) @@ -327,17 +328,17 @@ impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> { self.print_type(self_ty) } - _ => self.pretty_path_qualified(self_ty, trait_ref), + _ => self.pretty_print_path_with_qualified(self_ty, trait_ref), } } - fn path_append_impl( + fn print_path_with_impl( &mut self, print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, self_ty: Ty<'tcx>, trait_ref: Option<ty::TraitRef<'tcx>>, ) -> Result<(), PrintError> { - self.pretty_path_append_impl( + self.pretty_print_path_with_impl( |cx| { print_prefix(cx)?; @@ -354,7 +355,8 @@ impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> { trait_ref, ) } - fn path_append( + + fn print_path_with_simple( &mut self, print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, disambiguated_data: &DisambiguatedDefPathData, @@ -377,7 +379,8 @@ impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> { Ok(()) } - fn path_generic_args( + + fn print_path_with_generic_args( &mut self, print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, args: &[GenericArg<'tcx>], @@ -455,7 +458,7 @@ impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> { } } -impl<'tcx> PrettyPrinter<'tcx> for SymbolPrinter<'tcx> { +impl<'tcx> PrettyPrinter<'tcx> for LegacySymbolMangler<'tcx> { fn should_print_region(&self, _region: ty::Region<'_>) -> bool { false } @@ -491,7 +494,7 @@ impl<'tcx> PrettyPrinter<'tcx> for SymbolPrinter<'tcx> { } } -impl fmt::Write for SymbolPrinter<'_> { +impl fmt::Write for LegacySymbolMangler<'_> { fn write_str(&mut self, s: &str) -> fmt::Result { // Name sanitation. LLVM will happily accept identifiers with weird names, but // gas doesn't! diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index f3c96f64190..96a501fb0ea 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -193,13 +193,12 @@ fn compute_symbol_name<'tcx>( // defining crate. // Weak lang items automatically get #[rustc_std_internal_symbol] // applied by the code computing the CodegenFnAttrs. - // We are mangling all #[rustc_std_internal_symbol] items that don't - // also have #[no_mangle] as a combination of the rustc version and the - // unmangled linkage name. This is to ensure that if we link against a - // staticlib compiled by a different rustc version, we don't get symbol - // conflicts or even UB due to a different implementation/ABI. Rust - // staticlibs currently export all symbols, including those that are - // hidden in cdylibs. + // We are mangling all #[rustc_std_internal_symbol] items as a + // combination of the rustc version and the unmangled linkage name. + // This is to ensure that if we link against a staticlib compiled by a + // different rustc version, we don't get symbol conflicts or even UB + // due to a different implementation/ABI. Rust staticlibs currently + // export all symbols, including those that are hidden in cdylibs. // We are using the v0 symbol mangling scheme here as we need to be // consistent across all crates and in some contexts the legacy symbol // mangling scheme can't be used. For example both the GCC backend and @@ -211,11 +210,7 @@ fn compute_symbol_name<'tcx>( if let Some(name) = attrs.export_name { name } else { tcx.item_name(def_id) } }; - if attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE) { - return name.to_string(); - } else { return v0::mangle_internal_symbol(tcx, name.as_str()); - } } let wasm_import_module_exception_force_mangling = { diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index c2458ae814b..0cbd48ba08c 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -33,7 +33,7 @@ pub(super) fn mangle<'tcx>( let args = tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), instance.args); let prefix = "_R"; - let mut p: SymbolMangler<'_> = SymbolMangler { + let mut p: V0SymbolMangler<'_> = V0SymbolMangler { tcx, start_offset: prefix.len(), is_exportable, @@ -88,7 +88,7 @@ pub fn mangle_internal_symbol<'tcx>(tcx: TyCtxt<'tcx>, item_name: &str) -> Strin } let prefix = "_R"; - let mut p: SymbolMangler<'_> = SymbolMangler { + let mut p: V0SymbolMangler<'_> = V0SymbolMangler { tcx, start_offset: prefix.len(), is_exportable: false, @@ -131,7 +131,7 @@ pub(super) fn mangle_typeid_for_trait_ref<'tcx>( trait_ref: ty::ExistentialTraitRef<'tcx>, ) -> String { // FIXME(flip1995): See comment in `mangle_typeid_for_fnabi`. - let mut p = SymbolMangler { + let mut p = V0SymbolMangler { tcx, start_offset: 0, is_exportable: false, @@ -159,7 +159,7 @@ struct BinderLevel { lifetime_depths: Range<u32>, } -struct SymbolMangler<'tcx> { +struct V0SymbolMangler<'tcx> { tcx: TyCtxt<'tcx>, binders: Vec<BinderLevel>, out: String, @@ -173,7 +173,7 @@ struct SymbolMangler<'tcx> { consts: FxHashMap<ty::Const<'tcx>, usize>, } -impl<'tcx> SymbolMangler<'tcx> { +impl<'tcx> V0SymbolMangler<'tcx> { fn push(&mut self, s: &str) { self.out.push_str(s); } @@ -272,7 +272,7 @@ impl<'tcx> SymbolMangler<'tcx> { } } -impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { +impl<'tcx> Printer<'tcx> for V0SymbolMangler<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } @@ -365,7 +365,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { // Encode impl generic params if the generic parameters contain non-region parameters // and this isn't an inherent impl. if impl_trait_ref.is_some() && args.iter().any(|a| a.has_non_region_param()) { - self.path_generic_args( + self.print_path_with_generic_args( |this| { this.path_append_ns( |p| p.print_def_path(parent_def_id, &[]), @@ -786,7 +786,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { None => { self.push("S"); for (field_def, field) in iter::zip(&variant_def.fields, fields) { - // HACK(eddyb) this mimics `path_append`, + // HACK(eddyb) this mimics `print_path_with_simple`, // instead of simply using `field_def.ident`, // just to be able to handle disambiguators. let disambiguated_field = @@ -819,7 +819,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { Ok(()) } - fn path_crate(&mut self, cnum: CrateNum) -> Result<(), PrintError> { + fn print_crate_name(&mut self, cnum: CrateNum) -> Result<(), PrintError> { self.push("C"); if !self.is_exportable { let stable_crate_id = self.tcx.def_path_hash(cnum.as_def_id()).stable_crate_id(); @@ -830,7 +830,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { Ok(()) } - fn path_qualified( + fn print_path_with_qualified( &mut self, self_ty: Ty<'tcx>, trait_ref: Option<ty::TraitRef<'tcx>>, @@ -843,7 +843,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { self.print_def_path(trait_ref.def_id, trait_ref.args) } - fn path_append_impl( + fn print_path_with_impl( &mut self, _: impl FnOnce(&mut Self) -> Result<(), PrintError>, _: Ty<'tcx>, @@ -853,7 +853,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { unreachable!() } - fn path_append( + fn print_path_with_simple( &mut self, print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, disambiguated_data: &DisambiguatedDefPathData, @@ -873,7 +873,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { DefPathData::SyntheticCoroutineBody => 's', DefPathData::NestedStatic => 'n', - // These should never show up as `path_append` arguments. + // These should never show up as `print_path_with_simple` arguments. DefPathData::CrateRoot | DefPathData::Use | DefPathData::GlobalAsm @@ -896,7 +896,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { ) } - fn path_generic_args( + fn print_path_with_generic_args( &mut self, print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, args: &[GenericArg<'tcx>], diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index b9fbff8db05..ee408c76006 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2147,6 +2147,7 @@ supported_targets! { ("aarch64-unknown-none", aarch64_unknown_none), ("aarch64-unknown-none-softfloat", aarch64_unknown_none_softfloat), + ("aarch64_be-unknown-none-softfloat", aarch64_be_unknown_none_softfloat), ("aarch64-unknown-nuttx", aarch64_unknown_nuttx), ("x86_64-fortanix-unknown-sgx", x86_64_fortanix_unknown_sgx), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_none_softfloat.rs new file mode 100644 index 00000000000..7f918e85080 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_none_softfloat.rs @@ -0,0 +1,43 @@ +// Generic big-endian AArch64 target for bare-metal code - Floating point disabled +// +// Can be used in conjunction with the `target-feature` and +// `target-cpu` compiler flags to opt-in more hardware-specific +// features. +// +// For example, `-C target-cpu=cortex-a53`. +use rustc_abi::Endian; + +use crate::spec::{ + Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, SanitizerSet, StackProbeType, Target, + TargetMetadata, TargetOptions, +}; + +pub(crate) fn target() -> Target { + let opts = TargetOptions { + abi: "softfloat".into(), + linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), + linker: Some("rust-lld".into()), + features: "+v8a,+strict-align,-neon,-fp-armv8".into(), + relocation_model: RelocModel::Static, + disable_redzone: true, + max_atomic_width: Some(128), + supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS, + stack_probes: StackProbeType::Inline, + panic_strategy: PanicStrategy::Abort, + endian: Endian::Big, + ..Default::default() + }; + Target { + llvm_target: "aarch64_be-unknown-none".into(), + metadata: TargetMetadata { + description: Some("Bare ARM64 (big-endian), softfloat".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(false), + }, + pointer_width: 64, + data_layout: "E-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + arch: "aarch64".into(), + options: opts, + } +} diff --git a/compiler/rustc_target/src/spec/targets/avr_none.rs b/compiler/rustc_target/src/spec/targets/avr_none.rs index 07ed2a37803..ad056d02326 100644 --- a/compiler/rustc_target/src/spec/targets/avr_none.rs +++ b/compiler/rustc_target/src/spec/targets/avr_none.rs @@ -9,7 +9,7 @@ pub(crate) fn target() -> Target { host_tools: None, std: None, }, - data_layout: "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8".into(), + data_layout: "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8:16-a:8".into(), llvm_target: "avr-unknown-unknown".into(), pointer_width: 16, options: TargetOptions { diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 297d9ed84c5..507e938d5cc 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -248,6 +248,10 @@ static AARCH64_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("mte", Stable, &[]), // FEAT_AdvSimd & FEAT_FP ("neon", Stable, &[]), + // Backend option to turn atomic operations into an intrinsic call when `lse` is not known to be + // available, so the intrinsic can do runtime LSE feature detection rather than unconditionally + // using slower non-LSE operations. Unstable since it doesn't need to user-togglable. + ("outline-atomics", Unstable(sym::aarch64_unstable_target_feature), &[]), // FEAT_PAUTH (address authentication) ("paca", Stable, &[]), // FEAT_PAUTH (generic authentication) @@ -471,9 +475,9 @@ static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("sse3", Stable, &["sse2"]), ("sse4.1", Stable, &["ssse3"]), ("sse4.2", Stable, &["sse4.1"]), - ("sse4a", Unstable(sym::sse4a_target_feature), &["sse3"]), + ("sse4a", Stable, &["sse3"]), ("ssse3", Stable, &["sse3"]), - ("tbm", Unstable(sym::tbm_target_feature), &[]), + ("tbm", Stable, &[]), ("vaes", Stable, &["avx2", "aes"]), ("vpclmulqdq", Stable, &["avx", "pclmulqdq"]), ("widekl", Stable, &["kl"]), diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index 8551780bcd5..20e425bfad1 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -224,12 +224,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { use ty::GenericArg; use ty::print::Printer; - struct AbsolutePathPrinter<'tcx> { + struct ConflictingPathPrinter<'tcx> { tcx: TyCtxt<'tcx>, segments: Vec<Symbol>, } - impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { + impl<'tcx> Printer<'tcx> for ConflictingPathPrinter<'tcx> { fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { self.tcx } @@ -253,12 +253,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { unreachable!(); // because `path_generic_args` ignores the `GenericArgs` } - fn path_crate(&mut self, cnum: CrateNum) -> Result<(), PrintError> { + fn print_crate_name(&mut self, cnum: CrateNum) -> Result<(), PrintError> { self.segments = vec![self.tcx.crate_name(cnum)]; Ok(()) } - fn path_qualified( + fn print_path_with_qualified( &mut self, _self_ty: Ty<'tcx>, _trait_ref: Option<ty::TraitRef<'tcx>>, @@ -266,7 +266,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { Err(fmt::Error) } - fn path_append_impl( + fn print_path_with_impl( &mut self, _print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, _self_ty: Ty<'tcx>, @@ -275,7 +275,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { Err(fmt::Error) } - fn path_append( + fn print_path_with_simple( &mut self, print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, disambiguated_data: &DisambiguatedDefPathData, @@ -285,7 +285,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { Ok(()) } - fn path_generic_args( + fn print_path_with_generic_args( &mut self, print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>, _args: &[GenericArg<'tcx>], @@ -300,28 +300,27 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // let _ = [{struct Foo; Foo}, {struct Foo; Foo}]; if did1.krate != did2.krate { let abs_path = |def_id| { - let mut p = AbsolutePathPrinter { tcx: self.tcx, segments: vec![] }; + let mut p = ConflictingPathPrinter { tcx: self.tcx, segments: vec![] }; p.print_def_path(def_id, &[]).map(|_| p.segments) }; - // We compare strings because DefPath can be different - // for imported and non-imported crates + // We compare strings because DefPath can be different for imported and + // non-imported crates. let expected_str = self.tcx.def_path_str(did1); let found_str = self.tcx.def_path_str(did2); let Ok(expected_abs) = abs_path(did1) else { return false }; let Ok(found_abs) = abs_path(did2) else { return false }; - let same_path = || -> Result<_, PrintError> { - Ok(expected_str == found_str || expected_abs == found_abs) - }; - // We want to use as unique a type path as possible. If both types are "locally - // known" by the same name, we use the "absolute path" which uses the original - // crate name instead. - let (expected, found) = if expected_str == found_str { - (join_path_syms(&expected_abs), join_path_syms(&found_abs)) - } else { - (expected_str.clone(), found_str.clone()) - }; - if same_path().unwrap_or(false) { + let same_path = expected_str == found_str || expected_abs == found_abs; + if same_path { + // We want to use as unique a type path as possible. If both types are "locally + // known" by the same name, we use the "absolute path" which uses the original + // crate name instead. + let (expected, found) = if expected_str == found_str { + (join_path_syms(&expected_abs), join_path_syms(&found_abs)) + } else { + (expected_str.clone(), found_str.clone()) + }; + // We've displayed "expected `a::b`, found `a::b`". We add context to // differentiate the different cases where that might happen. let expected_crate_name = self.tcx.crate_name(did1.krate); diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs index 8f0f6d0bf26..f31a85ec07a 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs @@ -946,7 +946,7 @@ fn foo(&self) -> Self::T { String::new() } pub fn format_generic_args(&self, args: &[ty::GenericArg<'tcx>]) -> String { FmtPrinter::print_string(self.tcx, hir::def::Namespace::TypeNS, |p| { - p.path_generic_args(|_| Ok(()), args) + p.print_path_with_generic_args(|_| Ok(()), args) }) .expect("could not write to `String`.") } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 581191b2036..884d53732fe 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1507,7 +1507,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>( let tcx = selcx.tcx(); let self_ty = obligation.predicate.self_ty(); let item_def_id = obligation.predicate.def_id; - let trait_def_id = tcx.trait_of_assoc(item_def_id).unwrap(); + let trait_def_id = tcx.parent(item_def_id); let args = tcx.mk_args(&[self_ty.into()]); let (term, obligations) = if tcx.is_lang_item(trait_def_id, LangItem::DiscriminantKind) { let discriminant_def_id = diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs index daacb4a3e44..24094eeea8d 100644 --- a/compiler/rustc_type_ir/src/search_graph/mod.rs +++ b/compiler/rustc_type_ir/src/search_graph/mod.rs @@ -12,10 +12,11 @@ //! The global cache has to be completely unobservable, while the per-cycle cache may impact //! behavior as long as the resulting behavior is still correct. use std::cmp::Ordering; -use std::collections::BTreeMap; use std::collections::hash_map::Entry; +use std::collections::{BTreeMap, btree_map}; use std::fmt::Debug; use std::hash::Hash; +use std::iter; use std::marker::PhantomData; use derive_where::derive_where; @@ -230,13 +231,19 @@ impl AvailableDepth { } } +#[derive(Clone, Copy, Debug)] +struct CycleHead { + paths_to_head: PathsToNested, + usage_kind: UsageKind, +} + /// All cycle heads a given goal depends on, ordered by their stack depth. /// /// We also track all paths from this goal to that head. This is necessary /// when rebasing provisional cache results. #[derive(Clone, Debug, Default)] struct CycleHeads { - heads: BTreeMap<StackDepth, PathsToNested>, + heads: BTreeMap<StackDepth, CycleHead>, } impl CycleHeads { @@ -256,32 +263,32 @@ impl CycleHeads { self.heads.first_key_value().map(|(k, _)| *k) } - fn remove_highest_cycle_head(&mut self) -> PathsToNested { + fn remove_highest_cycle_head(&mut self) -> CycleHead { let last = self.heads.pop_last(); last.unwrap().1 } - fn insert(&mut self, head: StackDepth, path_from_entry: impl Into<PathsToNested> + Copy) { - *self.heads.entry(head).or_insert(path_from_entry.into()) |= path_from_entry.into(); + fn insert( + &mut self, + head_index: StackDepth, + path_from_entry: impl Into<PathsToNested> + Copy, + usage_kind: UsageKind, + ) { + match self.heads.entry(head_index) { + btree_map::Entry::Vacant(entry) => { + entry.insert(CycleHead { paths_to_head: path_from_entry.into(), usage_kind }); + } + btree_map::Entry::Occupied(entry) => { + let head = entry.into_mut(); + head.paths_to_head |= path_from_entry.into(); + head.usage_kind = head.usage_kind.merge(usage_kind); + } + } } - fn iter(&self) -> impl Iterator<Item = (StackDepth, PathsToNested)> + '_ { + fn iter(&self) -> impl Iterator<Item = (StackDepth, CycleHead)> + '_ { self.heads.iter().map(|(k, v)| (*k, *v)) } - - /// Update the cycle heads of a goal at depth `this` given the cycle heads - /// of a nested goal. This merges the heads after filtering the parent goal - /// itself. - fn extend_from_child(&mut self, this: StackDepth, step_kind: PathKind, child: &CycleHeads) { - for (&head, &path_from_entry) in child.heads.iter() { - match head.cmp(&this) { - Ordering::Less => {} - Ordering::Equal => continue, - Ordering::Greater => unreachable!(), - } - self.insert(head, path_from_entry.extend_with(step_kind)); - } - } } bitflags::bitflags! { @@ -487,9 +494,6 @@ impl<X: Cx> EvaluationResult<X> { pub struct SearchGraph<D: Delegate<Cx = X>, X: Cx = <D as Delegate>::Cx> { root_depth: AvailableDepth, - /// The stack of goals currently being computed. - /// - /// An element is *deeper* in the stack if its index is *lower*. stack: Stack<X>, /// The provisional cache contains entries for already computed goals which /// still depend on goals higher-up in the stack. We don't move them to the @@ -511,6 +515,7 @@ pub struct SearchGraph<D: Delegate<Cx = X>, X: Cx = <D as Delegate>::Cx> { /// cache entry. enum UpdateParentGoalCtxt<'a, X: Cx> { Ordinary(&'a NestedGoals<X>), + CycleOnStack(X::Input), ProvisionalCacheHit, } @@ -532,21 +537,42 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> { stack: &mut Stack<X>, step_kind_from_parent: PathKind, required_depth_for_nested: usize, - heads: &CycleHeads, + heads: impl Iterator<Item = (StackDepth, CycleHead)>, encountered_overflow: bool, context: UpdateParentGoalCtxt<'_, X>, ) { - if let Some(parent_index) = stack.last_index() { - let parent = &mut stack[parent_index]; + if let Some((parent_index, parent)) = stack.last_mut_with_index() { parent.required_depth = parent.required_depth.max(required_depth_for_nested + 1); parent.encountered_overflow |= encountered_overflow; - parent.heads.extend_from_child(parent_index, step_kind_from_parent, heads); + for (head_index, head) in heads { + match head_index.cmp(&parent_index) { + Ordering::Less => parent.heads.insert( + head_index, + head.paths_to_head.extend_with(step_kind_from_parent), + head.usage_kind, + ), + Ordering::Equal => { + let usage_kind = parent + .has_been_used + .map_or(head.usage_kind, |prev| prev.merge(head.usage_kind)); + parent.has_been_used = Some(usage_kind); + } + Ordering::Greater => unreachable!(), + } + } let parent_depends_on_cycle = match context { UpdateParentGoalCtxt::Ordinary(nested_goals) => { parent.nested_goals.extend_from_child(step_kind_from_parent, nested_goals); !nested_goals.is_empty() } + UpdateParentGoalCtxt::CycleOnStack(head) => { + // We lookup provisional cache entries before detecting cycles. + // We therefore can't use a global cache entry if it contains a cycle + // whose head is in the provisional cache. + parent.nested_goals.insert(head, step_kind_from_parent.into()); + true + } UpdateParentGoalCtxt::ProvisionalCacheHit => true, }; // Once we've got goals which encountered overflow or a cycle, @@ -674,7 +700,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> { &mut self.stack, step_kind_from_parent, evaluation_result.required_depth, - &evaluation_result.heads, + evaluation_result.heads.iter(), evaluation_result.encountered_overflow, UpdateParentGoalCtxt::Ordinary(&evaluation_result.nested_goals), ); @@ -772,7 +798,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> { stack_entry: &StackEntry<X>, mut mutate_result: impl FnMut(X::Input, X::Result) -> X::Result, ) { - let popped_head = self.stack.next_index(); + let popped_head_index = self.stack.next_index(); #[allow(rustc::potential_query_instability)] self.provisional_cache.retain(|&input, entries| { entries.retain_mut(|entry| { @@ -782,7 +808,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> { path_from_head, result, } = entry; - let ep = if heads.highest_cycle_head() == popped_head { + let popped_head = if heads.highest_cycle_head() == popped_head_index { heads.remove_highest_cycle_head() } else { return true; @@ -795,9 +821,14 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> { // // After rebasing the cycles `hph` will go through `e`. We need to make // sure that forall possible paths `hep`, `heph` is equal to `hph.` - for (h, ph) in stack_entry.heads.iter() { - let hp = - Self::cycle_path_kind(&self.stack, stack_entry.step_kind_from_parent, h); + let ep = popped_head.paths_to_head; + for (head_index, head) in stack_entry.heads.iter() { + let ph = head.paths_to_head; + let hp = Self::cycle_path_kind( + &self.stack, + stack_entry.step_kind_from_parent, + head_index, + ); // We first validate that all cycles while computing `p` would stay // the same if we were to recompute it as a nested goal of `e`. @@ -817,7 +848,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> { // the heads of `e` to make sure that rebasing `e` again also considers // them. let eph = ep.extend_with_paths(ph); - heads.insert(h, eph); + heads.insert(head_index, eph, head.usage_kind); } let Some(head) = heads.opt_highest_cycle_head() else { @@ -877,11 +908,10 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> { &mut self.stack, step_kind_from_parent, 0, - heads, + heads.iter(), encountered_overflow, UpdateParentGoalCtxt::ProvisionalCacheHit, ); - debug_assert!(self.stack[head].has_been_used.is_some()); debug!(?head, ?path_from_head, "provisional cache hit"); return Some(result); } @@ -993,12 +1023,12 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> { // We don't move cycle participants to the global cache, so the // cycle heads are always empty. - let heads = Default::default(); + let heads = iter::empty(); Self::update_parent_goal( &mut self.stack, step_kind_from_parent, required_depth, - &heads, + heads, encountered_overflow, UpdateParentGoalCtxt::Ordinary(nested_goals), ); @@ -1014,34 +1044,31 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> { input: X::Input, step_kind_from_parent: PathKind, ) -> Option<X::Result> { - let head = self.stack.find(input)?; + let head_index = self.stack.find(input)?; // We have a nested goal which directly relies on a goal deeper in the stack. // // We start by tagging all cycle participants, as that's necessary for caching. // // Finally we can return either the provisional response or the initial response // in case we're in the first fixpoint iteration for this goal. - let path_kind = Self::cycle_path_kind(&self.stack, step_kind_from_parent, head); - debug!(?path_kind, "encountered cycle with depth {head:?}"); - let usage_kind = UsageKind::Single(path_kind); - self.stack[head].has_been_used = - Some(self.stack[head].has_been_used.map_or(usage_kind, |prev| prev.merge(usage_kind))); - - // Subtle: when encountering a cyclic goal, we still first checked for overflow, - // so we have to update the reached depth. - let last_index = self.stack.last_index().unwrap(); - let last = &mut self.stack[last_index]; - last.required_depth = last.required_depth.max(1); - - last.nested_goals.insert(input, step_kind_from_parent.into()); - last.nested_goals.insert(last.input, PathsToNested::EMPTY); - if last_index != head { - last.heads.insert(head, step_kind_from_parent); - } + let path_kind = Self::cycle_path_kind(&self.stack, step_kind_from_parent, head_index); + debug!(?path_kind, "encountered cycle with depth {head_index:?}"); + let head = CycleHead { + paths_to_head: step_kind_from_parent.into(), + usage_kind: UsageKind::Single(path_kind), + }; + Self::update_parent_goal( + &mut self.stack, + step_kind_from_parent, + 0, + iter::once((head_index, head)), + false, + UpdateParentGoalCtxt::CycleOnStack(input), + ); // Return the provisional result or, if we're in the first iteration, // start with no constraints. - if let Some(result) = self.stack[head].provisional_result { + if let Some(result) = self.stack[head_index].provisional_result { Some(result) } else { Some(D::initial_provisional_result(cx, path_kind, input)) diff --git a/compiler/rustc_type_ir/src/search_graph/stack.rs b/compiler/rustc_type_ir/src/search_graph/stack.rs index a58cd82b023..ea99dc6e7fd 100644 --- a/compiler/rustc_type_ir/src/search_graph/stack.rs +++ b/compiler/rustc_type_ir/src/search_graph/stack.rs @@ -1,4 +1,4 @@ -use std::ops::{Index, IndexMut}; +use std::ops::Index; use derive_where::derive_where; use rustc_index::IndexVec; @@ -48,6 +48,12 @@ pub(super) struct StackEntry<X: Cx> { pub nested_goals: NestedGoals<X>, } +/// The stack of goals currently being computed. +/// +/// An element is *deeper* in the stack if its index is *lower*. +/// +/// Only the last entry of the stack is mutable. All other entries get +/// lazily updated in `update_parent_goal`. #[derive_where(Default; X: Cx)] pub(super) struct Stack<X: Cx> { entries: IndexVec<StackDepth, StackEntry<X>>, @@ -62,10 +68,6 @@ impl<X: Cx> Stack<X> { self.entries.len() } - pub(super) fn last_index(&self) -> Option<StackDepth> { - self.entries.last_index() - } - pub(super) fn last(&self) -> Option<&StackEntry<X>> { self.entries.raw.last() } @@ -74,6 +76,10 @@ impl<X: Cx> Stack<X> { self.entries.raw.last_mut() } + pub(super) fn last_mut_with_index(&mut self) -> Option<(StackDepth, &mut StackEntry<X>)> { + self.entries.last_index().map(|idx| (idx, &mut self.entries[idx])) + } + pub(super) fn next_index(&self) -> StackDepth { self.entries.next_index() } @@ -108,9 +114,3 @@ impl<X: Cx> Index<StackDepth> for Stack<X> { &self.entries[index] } } - -impl<X: Cx> IndexMut<StackDepth> for Stack<X> { - fn index_mut(&mut self, index: StackDepth) -> &mut Self::Output { - &mut self.entries[index] - } -} diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index c091e496c50..639c5d4c930 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -102,6 +102,7 @@ #![feature(async_iterator)] #![feature(bstr)] #![feature(bstr_internals)] +#![feature(cast_maybe_uninit)] #![feature(char_internals)] #![feature(char_max_len)] #![feature(clone_to_uninit)] diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 8001faf9d20..2e40227a058 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -3176,7 +3176,7 @@ impl<T, A: Allocator> Vec<T, A> { // - but the allocation extends out to `self.buf.capacity()` elements, possibly // uninitialized let spare_ptr = unsafe { ptr.add(self.len) }; - let spare_ptr = spare_ptr.cast::<MaybeUninit<T>>(); + let spare_ptr = spare_ptr.cast_uninit(); let spare_len = self.buf.capacity() - self.len; // SAFETY: diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index 49275975f04..cd5fd77f865 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -226,10 +226,10 @@ impl Layout { /// Creates a `NonNull` that is dangling, but well-aligned for this Layout. /// - /// Note that the pointer value may potentially represent a valid pointer, - /// which means this must not be used as a "not yet initialized" - /// sentinel value. Types that lazily allocate must track initialization by - /// some other means. + /// Note that the address of the returned pointer may potentially + /// be that of a valid pointer, which means this must not be used + /// as a "not yet initialized" sentinel value. + /// Types that lazily allocate must track initialization by some other means. #[unstable(feature = "alloc_layout_extra", issue = "55724")] #[must_use] #[inline] diff --git a/library/core/src/ascii/ascii_char.rs b/library/core/src/ascii/ascii_char.rs index 054ddf84470..419e4694594 100644 --- a/library/core/src/ascii/ascii_char.rs +++ b/library/core/src/ascii/ascii_char.rs @@ -445,7 +445,15 @@ pub enum AsciiChar { } impl AsciiChar { - /// Creates an ascii character from the byte `b`, + /// The character with the lowest ASCII code. + #[unstable(feature = "ascii_char", issue = "110998")] + pub const MIN: Self = Self::Null; + + /// The character with the highest ASCII code. + #[unstable(feature = "ascii_char", issue = "110998")] + pub const MAX: Self = Self::Delete; + + /// Creates an ASCII character from the byte `b`, /// or returns `None` if it's too large. #[unstable(feature = "ascii_char", issue = "110998")] #[inline] @@ -540,6 +548,608 @@ impl AsciiChar { pub const fn as_str(&self) -> &str { crate::slice::from_ref(self).as_str() } + + /// Makes a copy of the value in its upper case equivalent. + /// + /// Letters 'a' to 'z' are mapped to 'A' to 'Z'. + /// + /// To uppercase the value in-place, use [`make_uppercase`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(ascii_char, ascii_char_variants)] + /// use std::ascii; + /// + /// let lowercase_a = ascii::Char::SmallA; + /// + /// assert_eq!( + /// ascii::Char::CapitalA, + /// lowercase_a.to_uppercase(), + /// ); + /// ``` + /// + /// [`make_uppercase`]: Self::make_uppercase + #[must_use = "to uppercase the value in-place, use `make_uppercase()`"] + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn to_uppercase(self) -> Self { + let uppercase_byte = self.to_u8().to_ascii_uppercase(); + // SAFETY: Toggling the 6th bit won't convert ASCII to non-ASCII. + unsafe { Self::from_u8_unchecked(uppercase_byte) } + } + + /// Makes a copy of the value in its lower case equivalent. + /// + /// Letters 'A' to 'Z' are mapped to 'a' to 'z'. + /// + /// To lowercase the value in-place, use [`make_lowercase`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(ascii_char, ascii_char_variants)] + /// use std::ascii; + /// + /// let uppercase_a = ascii::Char::CapitalA; + /// + /// assert_eq!( + /// ascii::Char::SmallA, + /// uppercase_a.to_lowercase(), + /// ); + /// ``` + /// + /// [`make_lowercase`]: Self::make_lowercase + #[must_use = "to lowercase the value in-place, use `make_lowercase()`"] + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn to_lowercase(self) -> Self { + let lowercase_byte = self.to_u8().to_ascii_lowercase(); + // SAFETY: Setting the 6th bit won't convert ASCII to non-ASCII. + unsafe { Self::from_u8_unchecked(lowercase_byte) } + } + + /// Checks that two values are a case-insensitive match. + /// + /// This is equivalent to `to_lowercase(a) == to_lowercase(b)`. + /// + /// # Examples + /// + /// ``` + /// #![feature(ascii_char, ascii_char_variants)] + /// use std::ascii; + /// + /// let lowercase_a = ascii::Char::SmallA; + /// let uppercase_a = ascii::Char::CapitalA; + /// + /// assert!(lowercase_a.eq_ignore_case(uppercase_a)); + /// ``` + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn eq_ignore_case(self, other: Self) -> bool { + // FIXME(const-hack) `arg.to_u8().to_ascii_lowercase()` -> `arg.to_lowercase()` + // once `PartialEq` is const for `Self`. + self.to_u8().to_ascii_lowercase() == other.to_u8().to_ascii_lowercase() + } + + /// Converts this value to its upper case equivalent in-place. + /// + /// Letters 'a' to 'z' are mapped to 'A' to 'Z'. + /// + /// To return a new uppercased value without modifying the existing one, use + /// [`to_uppercase`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(ascii_char, ascii_char_variants)] + /// use std::ascii; + /// + /// let mut letter_a = ascii::Char::SmallA; + /// + /// letter_a.make_uppercase(); + /// + /// assert_eq!(ascii::Char::CapitalA, letter_a); + /// ``` + /// + /// [`to_uppercase`]: Self::to_uppercase + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn make_uppercase(&mut self) { + *self = self.to_uppercase(); + } + + /// Converts this value to its lower case equivalent in-place. + /// + /// Letters 'A' to 'Z' are mapped to 'a' to 'z'. + /// + /// To return a new lowercased value without modifying the existing one, use + /// [`to_lowercase`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(ascii_char, ascii_char_variants)] + /// use std::ascii; + /// + /// let mut letter_a = ascii::Char::CapitalA; + /// + /// letter_a.make_lowercase(); + /// + /// assert_eq!(ascii::Char::SmallA, letter_a); + /// ``` + /// + /// [`to_lowercase`]: Self::to_lowercase + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn make_lowercase(&mut self) { + *self = self.to_lowercase(); + } + + /// Checks if the value is an alphabetic character: + /// + /// - 0x41 'A' ..= 0x5A 'Z', or + /// - 0x61 'a' ..= 0x7A 'z'. + /// + /// # Examples + /// + /// ``` + /// #![feature(ascii_char, ascii_char_variants)] + /// use std::ascii; + /// + /// let uppercase_a = ascii::Char::CapitalA; + /// let uppercase_g = ascii::Char::CapitalG; + /// let a = ascii::Char::SmallA; + /// let g = ascii::Char::SmallG; + /// let zero = ascii::Char::Digit0; + /// let percent = ascii::Char::PercentSign; + /// let space = ascii::Char::Space; + /// let lf = ascii::Char::LineFeed; + /// let esc = ascii::Char::Escape; + /// + /// assert!(uppercase_a.is_alphabetic()); + /// assert!(uppercase_g.is_alphabetic()); + /// assert!(a.is_alphabetic()); + /// assert!(g.is_alphabetic()); + /// assert!(!zero.is_alphabetic()); + /// assert!(!percent.is_alphabetic()); + /// assert!(!space.is_alphabetic()); + /// assert!(!lf.is_alphabetic()); + /// assert!(!esc.is_alphabetic()); + /// ``` + #[must_use] + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn is_alphabetic(self) -> bool { + self.to_u8().is_ascii_alphabetic() + } + + /// Checks if the value is an uppercase character: + /// 0x41 'A' ..= 0x5A 'Z'. + /// + /// # Examples + /// + /// ``` + /// #![feature(ascii_char, ascii_char_variants)] + /// use std::ascii; + /// + /// let uppercase_a = ascii::Char::CapitalA; + /// let uppercase_g = ascii::Char::CapitalG; + /// let a = ascii::Char::SmallA; + /// let g = ascii::Char::SmallG; + /// let zero = ascii::Char::Digit0; + /// let percent = ascii::Char::PercentSign; + /// let space = ascii::Char::Space; + /// let lf = ascii::Char::LineFeed; + /// let esc = ascii::Char::Escape; + /// + /// assert!(uppercase_a.is_uppercase()); + /// assert!(uppercase_g.is_uppercase()); + /// assert!(!a.is_uppercase()); + /// assert!(!g.is_uppercase()); + /// assert!(!zero.is_uppercase()); + /// assert!(!percent.is_uppercase()); + /// assert!(!space.is_uppercase()); + /// assert!(!lf.is_uppercase()); + /// assert!(!esc.is_uppercase()); + /// ``` + #[must_use] + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn is_uppercase(self) -> bool { + self.to_u8().is_ascii_uppercase() + } + + /// Checks if the value is a lowercase character: + /// 0x61 'a' ..= 0x7A 'z'. + /// + /// # Examples + /// + /// ``` + /// #![feature(ascii_char, ascii_char_variants)] + /// use std::ascii; + /// + /// let uppercase_a = ascii::Char::CapitalA; + /// let uppercase_g = ascii::Char::CapitalG; + /// let a = ascii::Char::SmallA; + /// let g = ascii::Char::SmallG; + /// let zero = ascii::Char::Digit0; + /// let percent = ascii::Char::PercentSign; + /// let space = ascii::Char::Space; + /// let lf = ascii::Char::LineFeed; + /// let esc = ascii::Char::Escape; + /// + /// assert!(!uppercase_a.is_lowercase()); + /// assert!(!uppercase_g.is_lowercase()); + /// assert!(a.is_lowercase()); + /// assert!(g.is_lowercase()); + /// assert!(!zero.is_lowercase()); + /// assert!(!percent.is_lowercase()); + /// assert!(!space.is_lowercase()); + /// assert!(!lf.is_lowercase()); + /// assert!(!esc.is_lowercase()); + /// ``` + #[must_use] + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn is_lowercase(self) -> bool { + self.to_u8().is_ascii_lowercase() + } + + /// Checks if the value is an alphanumeric character: + /// + /// - 0x41 'A' ..= 0x5A 'Z', or + /// - 0x61 'a' ..= 0x7A 'z', or + /// - 0x30 '0' ..= 0x39 '9'. + /// + /// # Examples + /// + /// ``` + /// #![feature(ascii_char, ascii_char_variants)] + /// use std::ascii; + /// + /// let uppercase_a = ascii::Char::CapitalA; + /// let uppercase_g = ascii::Char::CapitalG; + /// let a = ascii::Char::SmallA; + /// let g = ascii::Char::SmallG; + /// let zero = ascii::Char::Digit0; + /// let percent = ascii::Char::PercentSign; + /// let space = ascii::Char::Space; + /// let lf = ascii::Char::LineFeed; + /// let esc = ascii::Char::Escape; + /// + /// assert!(uppercase_a.is_alphanumeric()); + /// assert!(uppercase_g.is_alphanumeric()); + /// assert!(a.is_alphanumeric()); + /// assert!(g.is_alphanumeric()); + /// assert!(zero.is_alphanumeric()); + /// assert!(!percent.is_alphanumeric()); + /// assert!(!space.is_alphanumeric()); + /// assert!(!lf.is_alphanumeric()); + /// assert!(!esc.is_alphanumeric()); + /// ``` + #[must_use] + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn is_alphanumeric(self) -> bool { + self.to_u8().is_ascii_alphanumeric() + } + + /// Checks if the value is a decimal digit: + /// 0x30 '0' ..= 0x39 '9'. + /// + /// # Examples + /// + /// ``` + /// #![feature(ascii_char, ascii_char_variants)] + /// use std::ascii; + /// + /// let uppercase_a = ascii::Char::CapitalA; + /// let uppercase_g = ascii::Char::CapitalG; + /// let a = ascii::Char::SmallA; + /// let g = ascii::Char::SmallG; + /// let zero = ascii::Char::Digit0; + /// let percent = ascii::Char::PercentSign; + /// let space = ascii::Char::Space; + /// let lf = ascii::Char::LineFeed; + /// let esc = ascii::Char::Escape; + /// + /// assert!(!uppercase_a.is_digit()); + /// assert!(!uppercase_g.is_digit()); + /// assert!(!a.is_digit()); + /// assert!(!g.is_digit()); + /// assert!(zero.is_digit()); + /// assert!(!percent.is_digit()); + /// assert!(!space.is_digit()); + /// assert!(!lf.is_digit()); + /// assert!(!esc.is_digit()); + /// ``` + #[must_use] + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn is_digit(self) -> bool { + self.to_u8().is_ascii_digit() + } + + /// Checks if the value is an octal digit: + /// 0x30 '0' ..= 0x37 '7'. + /// + /// # Examples + /// + /// ``` + /// #![feature(ascii_char, ascii_char_variants, is_ascii_octdigit)] + /// + /// use std::ascii; + /// + /// let uppercase_a = ascii::Char::CapitalA; + /// let a = ascii::Char::SmallA; + /// let zero = ascii::Char::Digit0; + /// let seven = ascii::Char::Digit7; + /// let eight = ascii::Char::Digit8; + /// let percent = ascii::Char::PercentSign; + /// let lf = ascii::Char::LineFeed; + /// let esc = ascii::Char::Escape; + /// + /// assert!(!uppercase_a.is_octdigit()); + /// assert!(!a.is_octdigit()); + /// assert!(zero.is_octdigit()); + /// assert!(seven.is_octdigit()); + /// assert!(!eight.is_octdigit()); + /// assert!(!percent.is_octdigit()); + /// assert!(!lf.is_octdigit()); + /// assert!(!esc.is_octdigit()); + /// ``` + #[must_use] + // This is blocked on two unstable features. Please ensure both are + // stabilized before marking this method as stable. + #[unstable(feature = "ascii_char", issue = "110998")] + // #[unstable(feature = "is_ascii_octdigit", issue = "101288")] + #[inline] + pub const fn is_octdigit(self) -> bool { + self.to_u8().is_ascii_octdigit() + } + + /// Checks if the value is a hexadecimal digit: + /// + /// - 0x30 '0' ..= 0x39 '9', or + /// - 0x41 'A' ..= 0x46 'F', or + /// - 0x61 'a' ..= 0x66 'f'. + /// + /// # Examples + /// + /// ``` + /// #![feature(ascii_char, ascii_char_variants)] + /// use std::ascii; + /// + /// let uppercase_a = ascii::Char::CapitalA; + /// let uppercase_g = ascii::Char::CapitalG; + /// let a = ascii::Char::SmallA; + /// let g = ascii::Char::SmallG; + /// let zero = ascii::Char::Digit0; + /// let percent = ascii::Char::PercentSign; + /// let space = ascii::Char::Space; + /// let lf = ascii::Char::LineFeed; + /// let esc = ascii::Char::Escape; + /// + /// assert!(uppercase_a.is_hexdigit()); + /// assert!(!uppercase_g.is_hexdigit()); + /// assert!(a.is_hexdigit()); + /// assert!(!g.is_hexdigit()); + /// assert!(zero.is_hexdigit()); + /// assert!(!percent.is_hexdigit()); + /// assert!(!space.is_hexdigit()); + /// assert!(!lf.is_hexdigit()); + /// assert!(!esc.is_hexdigit()); + /// ``` + #[must_use] + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn is_hexdigit(self) -> bool { + self.to_u8().is_ascii_hexdigit() + } + + /// Checks if the value is a punctuation character: + /// + /// - 0x21 ..= 0x2F `! " # $ % & ' ( ) * + , - . /`, or + /// - 0x3A ..= 0x40 `: ; < = > ? @`, or + /// - 0x5B ..= 0x60 `` [ \ ] ^ _ ` ``, or + /// - 0x7B ..= 0x7E `{ | } ~` + /// + /// # Examples + /// + /// ``` + /// #![feature(ascii_char, ascii_char_variants)] + /// use std::ascii; + /// + /// let uppercase_a = ascii::Char::CapitalA; + /// let uppercase_g = ascii::Char::CapitalG; + /// let a = ascii::Char::SmallA; + /// let g = ascii::Char::SmallG; + /// let zero = ascii::Char::Digit0; + /// let percent = ascii::Char::PercentSign; + /// let space = ascii::Char::Space; + /// let lf = ascii::Char::LineFeed; + /// let esc = ascii::Char::Escape; + /// + /// assert!(!uppercase_a.is_punctuation()); + /// assert!(!uppercase_g.is_punctuation()); + /// assert!(!a.is_punctuation()); + /// assert!(!g.is_punctuation()); + /// assert!(!zero.is_punctuation()); + /// assert!(percent.is_punctuation()); + /// assert!(!space.is_punctuation()); + /// assert!(!lf.is_punctuation()); + /// assert!(!esc.is_punctuation()); + /// ``` + #[must_use] + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn is_punctuation(self) -> bool { + self.to_u8().is_ascii_punctuation() + } + + /// Checks if the value is a graphic character: + /// 0x21 '!' ..= 0x7E '~'. + /// + /// # Examples + /// + /// ``` + /// #![feature(ascii_char, ascii_char_variants)] + /// use std::ascii; + /// + /// let uppercase_a = ascii::Char::CapitalA; + /// let uppercase_g = ascii::Char::CapitalG; + /// let a = ascii::Char::SmallA; + /// let g = ascii::Char::SmallG; + /// let zero = ascii::Char::Digit0; + /// let percent = ascii::Char::PercentSign; + /// let space = ascii::Char::Space; + /// let lf = ascii::Char::LineFeed; + /// let esc = ascii::Char::Escape; + /// + /// assert!(uppercase_a.is_graphic()); + /// assert!(uppercase_g.is_graphic()); + /// assert!(a.is_graphic()); + /// assert!(g.is_graphic()); + /// assert!(zero.is_graphic()); + /// assert!(percent.is_graphic()); + /// assert!(!space.is_graphic()); + /// assert!(!lf.is_graphic()); + /// assert!(!esc.is_graphic()); + /// ``` + #[must_use] + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn is_graphic(self) -> bool { + self.to_u8().is_ascii_graphic() + } + + /// Checks if the value is a whitespace character: + /// 0x20 SPACE, 0x09 HORIZONTAL TAB, 0x0A LINE FEED, + /// 0x0C FORM FEED, or 0x0D CARRIAGE RETURN. + /// + /// Rust uses the WhatWG Infra Standard's [definition of ASCII + /// whitespace][infra-aw]. There are several other definitions in + /// wide use. For instance, [the POSIX locale][pct] includes + /// 0x0B VERTICAL TAB as well as all the above characters, + /// but—from the very same specification—[the default rule for + /// "field splitting" in the Bourne shell][bfs] considers *only* + /// SPACE, HORIZONTAL TAB, and LINE FEED as whitespace. + /// + /// If you are writing a program that will process an existing + /// file format, check what that format's definition of whitespace is + /// before using this function. + /// + /// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace + /// [pct]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01 + /// [bfs]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05 + /// + /// # Examples + /// + /// ``` + /// #![feature(ascii_char, ascii_char_variants)] + /// use std::ascii; + /// + /// let uppercase_a = ascii::Char::CapitalA; + /// let uppercase_g = ascii::Char::CapitalG; + /// let a = ascii::Char::SmallA; + /// let g = ascii::Char::SmallG; + /// let zero = ascii::Char::Digit0; + /// let percent = ascii::Char::PercentSign; + /// let space = ascii::Char::Space; + /// let lf = ascii::Char::LineFeed; + /// let esc = ascii::Char::Escape; + /// + /// assert!(!uppercase_a.is_whitespace()); + /// assert!(!uppercase_g.is_whitespace()); + /// assert!(!a.is_whitespace()); + /// assert!(!g.is_whitespace()); + /// assert!(!zero.is_whitespace()); + /// assert!(!percent.is_whitespace()); + /// assert!(space.is_whitespace()); + /// assert!(lf.is_whitespace()); + /// assert!(!esc.is_whitespace()); + /// ``` + #[must_use] + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn is_whitespace(self) -> bool { + self.to_u8().is_ascii_whitespace() + } + + /// Checks if the value is a control character: + /// 0x00 NUL ..= 0x1F UNIT SEPARATOR, or 0x7F DELETE. + /// Note that most whitespace characters are control + /// characters, but SPACE is not. + /// + /// # Examples + /// + /// ``` + /// #![feature(ascii_char, ascii_char_variants)] + /// use std::ascii; + /// + /// let uppercase_a = ascii::Char::CapitalA; + /// let uppercase_g = ascii::Char::CapitalG; + /// let a = ascii::Char::SmallA; + /// let g = ascii::Char::SmallG; + /// let zero = ascii::Char::Digit0; + /// let percent = ascii::Char::PercentSign; + /// let space = ascii::Char::Space; + /// let lf = ascii::Char::LineFeed; + /// let esc = ascii::Char::Escape; + /// + /// assert!(!uppercase_a.is_control()); + /// assert!(!uppercase_g.is_control()); + /// assert!(!a.is_control()); + /// assert!(!g.is_control()); + /// assert!(!zero.is_control()); + /// assert!(!percent.is_control()); + /// assert!(!space.is_control()); + /// assert!(lf.is_control()); + /// assert!(esc.is_control()); + /// ``` + #[must_use] + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub const fn is_control(self) -> bool { + self.to_u8().is_ascii_control() + } + + /// Returns an iterator that produces an escaped version of a + /// character. + /// + /// The behavior is identical to + /// [`ascii::escape_default`](crate::ascii::escape_default). + /// + /// # Examples + /// + /// ``` + /// #![feature(ascii_char, ascii_char_variants)] + /// use std::ascii; + /// + /// let zero = ascii::Char::Digit0; + /// let tab = ascii::Char::CharacterTabulation; + /// let cr = ascii::Char::CarriageReturn; + /// let lf = ascii::Char::LineFeed; + /// let apostrophe = ascii::Char::Apostrophe; + /// let double_quote = ascii::Char::QuotationMark; + /// let backslash = ascii::Char::ReverseSolidus; + /// + /// assert_eq!("0", zero.escape_ascii().to_string()); + /// assert_eq!("\\t", tab.escape_ascii().to_string()); + /// assert_eq!("\\r", cr.escape_ascii().to_string()); + /// assert_eq!("\\n", lf.escape_ascii().to_string()); + /// assert_eq!("\\'", apostrophe.escape_ascii().to_string()); + /// assert_eq!("\\\"", double_quote.escape_ascii().to_string()); + /// assert_eq!("\\\\", backslash.escape_ascii().to_string()); + /// ``` + #[must_use = "this returns the escaped character as an iterator, \ + without modifying the original"] + #[unstable(feature = "ascii_char", issue = "110998")] + #[inline] + pub fn escape_ascii(self) -> super::EscapeDefault { + super::escape_default(self.to_u8()) + } } macro_rules! into_int_impl { diff --git a/library/core/src/iter/adapters/map_windows.rs b/library/core/src/iter/adapters/map_windows.rs index a9c07fee2a9..0dada9eb6aa 100644 --- a/library/core/src/iter/adapters/map_windows.rs +++ b/library/core/src/iter/adapters/map_windows.rs @@ -195,7 +195,7 @@ impl<T, const N: usize> Buffer<T, N> { // SAFETY: the index is valid and this is element `a` in the // diagram above and has not been dropped yet. - unsafe { ptr::drop_in_place(to_drop.cast::<T>()) }; + unsafe { ptr::drop_in_place(to_drop.cast_init()) }; } } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index d5bce6ad233..a6825b4be68 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -200,8 +200,6 @@ #![feature(riscv_target_feature)] #![feature(rtm_target_feature)] #![feature(s390x_target_feature)] -#![feature(sse4a_target_feature)] -#![feature(tbm_target_feature)] #![feature(wasm_target_feature)] #![feature(x86_amx_intrinsics)] // tidy-alphabetical-end diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index c59290a757b..db8b527d593 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -223,13 +223,14 @@ pub macro assert_matches { /// } /// ``` /// -/// The `cfg_select!` macro can also be used in expression position: +/// The `cfg_select!` macro can also be used in expression position, with or without braces on the +/// right-hand side: /// /// ``` /// #![feature(cfg_select)] /// /// let _some_string = cfg_select! { -/// unix => { "With great power comes great electricity bills" } +/// unix => "With great power comes great electricity bills", /// _ => { "Behind every successful diet is an unwatched pizza" } /// }; /// ``` diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 8b3703bd4b3..c5f0cb8016e 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -1430,6 +1430,28 @@ impl<T: PointeeSized> *const T { } } +impl<T> *const T { + /// Casts from a type to its maybe-uninitialized version. + #[must_use] + #[inline(always)] + #[unstable(feature = "cast_maybe_uninit", issue = "145036")] + pub const fn cast_uninit(self) -> *const MaybeUninit<T> { + self as _ + } +} +impl<T> *const MaybeUninit<T> { + /// Casts from a maybe-uninitialized type to its initialized version. + /// + /// This is always safe, since UB can only occur if the pointer is read + /// before being initialized. + #[must_use] + #[inline(always)] + #[unstable(feature = "cast_maybe_uninit", issue = "145036")] + pub const fn cast_init(self) -> *const T { + self as _ + } +} + impl<T> *const [T] { /// Returns the length of a raw slice. /// @@ -1547,6 +1569,15 @@ impl<T> *const [T] { } } +impl<T> *const T { + /// Casts from a pointer-to-`T` to a pointer-to-`[T; N]`. + #[inline] + #[unstable(feature = "ptr_cast_array", issue = "144514")] + pub const fn cast_array<const N: usize>(self) -> *const [T; N] { + self.cast() + } +} + impl<T, const N: usize> *const [T; N] { /// Returns a raw pointer to the array's buffer. /// diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 1a2a5182567..b2607e45324 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -885,10 +885,10 @@ pub const fn without_provenance<T>(addr: usize) -> *const T { /// This is useful for initializing types which lazily allocate, like /// `Vec::new` does. /// -/// Note that the pointer value may potentially represent a valid pointer to -/// a `T`, which means this must not be used as a "not yet initialized" -/// sentinel value. Types that lazily allocate must track initialization by -/// some other means. +/// Note that the address of the returned pointer may potentially +/// be that of a valid pointer, which means this must not be used +/// as a "not yet initialized" sentinel value. +/// Types that lazily allocate must track initialization by some other means. #[inline(always)] #[must_use] #[stable(feature = "strict_provenance", since = "1.84.0")] @@ -928,10 +928,10 @@ pub const fn without_provenance_mut<T>(addr: usize) -> *mut T { /// This is useful for initializing types which lazily allocate, like /// `Vec::new` does. /// -/// Note that the pointer value may potentially represent a valid pointer to -/// a `T`, which means this must not be used as a "not yet initialized" -/// sentinel value. Types that lazily allocate must track initialization by -/// some other means. +/// Note that the address of the returned pointer may potentially +/// be that of a valid pointer, which means this must not be used +/// as a "not yet initialized" sentinel value. +/// Types that lazily allocate must track initialization by some other means. #[inline(always)] #[must_use] #[stable(feature = "strict_provenance", since = "1.84.0")] diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index af39ec86d7a..3fe4b08d459 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1687,6 +1687,31 @@ impl<T: PointeeSized> *mut T { } } +impl<T> *mut T { + /// Casts from a type to its maybe-uninitialized version. + /// + /// This is always safe, since UB can only occur if the pointer is read + /// before being initialized. + #[must_use] + #[inline(always)] + #[unstable(feature = "cast_maybe_uninit", issue = "145036")] + pub const fn cast_uninit(self) -> *mut MaybeUninit<T> { + self as _ + } +} +impl<T> *mut MaybeUninit<T> { + /// Casts from a maybe-uninitialized type to its initialized version. + /// + /// This is always safe, since UB can only occur if the pointer is read + /// before being initialized. + #[must_use] + #[inline(always)] + #[unstable(feature = "cast_maybe_uninit", issue = "145036")] + pub const fn cast_init(self) -> *mut T { + self as _ + } +} + impl<T> *mut [T] { /// Returns the length of a raw slice. /// @@ -1965,6 +1990,15 @@ impl<T> *mut [T] { } } +impl<T> *mut T { + /// Casts from a pointer-to-`T` to a pointer-to-`[T; N]`. + #[inline] + #[unstable(feature = "ptr_cast_array", issue = "144514")] + pub const fn cast_array<const N: usize>(self) -> *mut [T; N] { + self.cast() + } +} + impl<T, const N: usize> *mut [T; N] { /// Returns a raw pointer to the array's buffer. /// diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 8667361fecc..117eb18826e 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -109,10 +109,10 @@ impl<T: Sized> NonNull<T> { /// This is useful for initializing types which lazily allocate, like /// `Vec::new` does. /// - /// Note that the pointer value may potentially represent a valid pointer to - /// a `T`, which means this must not be used as a "not yet initialized" - /// sentinel value. Types that lazily allocate must track initialization by - /// some other means. + /// Note that the address of the returned pointer may potentially + /// be that of a valid pointer, which means this must not be used + /// as a "not yet initialized" sentinel value. + /// Types that lazily allocate must track initialization by some other means. /// /// # Examples /// @@ -193,6 +193,13 @@ impl<T: Sized> NonNull<T> { // requirements for a reference. unsafe { &mut *self.cast().as_ptr() } } + + /// Casts from a pointer-to-`T` to a pointer-to-`[T; N]`. + #[inline] + #[unstable(feature = "ptr_cast_array", issue = "144514")] + pub const fn cast_array<const N: usize>(self) -> NonNull<[T; N]> { + self.cast() + } } impl<T: PointeeSized> NonNull<T> { @@ -1357,6 +1364,28 @@ impl<T: PointeeSized> NonNull<T> { } } +impl<T> NonNull<T> { + /// Casts from a type to its maybe-uninitialized version. + #[must_use] + #[inline(always)] + #[unstable(feature = "cast_maybe_uninit", issue = "145036")] + pub const fn cast_uninit(self) -> NonNull<MaybeUninit<T>> { + self.cast() + } +} +impl<T> NonNull<MaybeUninit<T>> { + /// Casts from a maybe-uninitialized type to its initialized version. + /// + /// This is always safe, since UB can only occur if the pointer is read + /// before being initialized. + #[must_use] + #[inline(always)] + #[unstable(feature = "cast_maybe_uninit", issue = "145036")] + pub const fn cast_init(self) -> NonNull<T> { + self.cast() + } +} + impl<T> NonNull<[T]> { /// Creates a non-null raw slice from a thin pointer and a length. /// diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs index e9e13f9e97f..4302c1b1e44 100644 --- a/library/core/src/ptr/unique.rs +++ b/library/core/src/ptr/unique.rs @@ -63,10 +63,10 @@ impl<T: Sized> Unique<T> { /// This is useful for initializing types which lazily allocate, like /// `Vec::new` does. /// - /// Note that the pointer value may potentially represent a valid pointer to - /// a `T`, which means this must not be used as a "not yet initialized" - /// sentinel value. Types that lazily allocate must track initialization by - /// some other means. + /// Note that the address of the returned pointer may potentially + /// be that of a valid pointer, which means this must not be used + /// as a "not yet initialized" sentinel value. + /// Types that lazily allocate must track initialization by some other means. #[must_use] #[inline] pub const fn dangling() -> Self { diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 64f5b5dd831..dfbb3628350 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -328,7 +328,7 @@ impl<T> [T] { } else { // SAFETY: We explicitly check for the correct number of elements, // and do not let the reference outlive the slice. - Some(unsafe { &*(self.as_ptr().cast::<[T; N]>()) }) + Some(unsafe { &*(self.as_ptr().cast_array()) }) } } @@ -359,7 +359,7 @@ impl<T> [T] { // SAFETY: We explicitly check for the correct number of elements, // do not let the reference outlive the slice, // and require exclusive access to the entire slice to mutate the chunk. - Some(unsafe { &mut *(self.as_mut_ptr().cast::<[T; N]>()) }) + Some(unsafe { &mut *(self.as_mut_ptr().cast_array()) }) } } @@ -387,7 +387,7 @@ impl<T> [T] { // SAFETY: We explicitly check for the correct number of elements, // and do not let the references outlive the slice. - Some((unsafe { &*(first.as_ptr().cast::<[T; N]>()) }, tail)) + Some((unsafe { &*(first.as_ptr().cast_array()) }, tail)) } /// Returns a mutable array reference to the first `N` items in the slice and the remaining @@ -420,7 +420,7 @@ impl<T> [T] { // SAFETY: We explicitly check for the correct number of elements, // do not let the reference outlive the slice, // and enforce exclusive mutability of the chunk by the split. - Some((unsafe { &mut *(first.as_mut_ptr().cast::<[T; N]>()) }, tail)) + Some((unsafe { &mut *(first.as_mut_ptr().cast_array()) }, tail)) } /// Returns an array reference to the last `N` items in the slice and the remaining slice. @@ -448,7 +448,7 @@ impl<T> [T] { // SAFETY: We explicitly check for the correct number of elements, // and do not let the references outlive the slice. - Some((init, unsafe { &*(last.as_ptr().cast::<[T; N]>()) })) + Some((init, unsafe { &*(last.as_ptr().cast_array()) })) } /// Returns a mutable array reference to the last `N` items in the slice and the remaining @@ -482,7 +482,7 @@ impl<T> [T] { // SAFETY: We explicitly check for the correct number of elements, // do not let the reference outlive the slice, // and enforce exclusive mutability of the chunk by the split. - Some((init, unsafe { &mut *(last.as_mut_ptr().cast::<[T; N]>()) })) + Some((init, unsafe { &mut *(last.as_mut_ptr().cast_array()) })) } /// Returns an array reference to the last `N` items in the slice. @@ -511,7 +511,7 @@ impl<T> [T] { // SAFETY: We explicitly check for the correct number of elements, // and do not let the references outlive the slice. - Some(unsafe { &*(last.as_ptr().cast::<[T; N]>()) }) + Some(unsafe { &*(last.as_ptr().cast_array()) }) } /// Returns a mutable array reference to the last `N` items in the slice. @@ -542,7 +542,7 @@ impl<T> [T] { // SAFETY: We explicitly check for the correct number of elements, // do not let the reference outlive the slice, // and require exclusive access to the entire slice to mutate the chunk. - Some(unsafe { &mut *(last.as_mut_ptr().cast::<[T; N]>()) }) + Some(unsafe { &mut *(last.as_mut_ptr().cast_array()) }) } /// Returns a reference to an element or subslice depending on the type of @@ -846,7 +846,7 @@ impl<T> [T] { #[must_use] pub const fn as_array<const N: usize>(&self) -> Option<&[T; N]> { if self.len() == N { - let ptr = self.as_ptr() as *const [T; N]; + let ptr = self.as_ptr().cast_array(); // SAFETY: The underlying array of a slice can be reinterpreted as an actual array `[T; N]` if `N` is not greater than the slice's length. let me = unsafe { &*ptr }; @@ -864,7 +864,7 @@ impl<T> [T] { #[must_use] pub const fn as_mut_array<const N: usize>(&mut self) -> Option<&mut [T; N]> { if self.len() == N { - let ptr = self.as_mut_ptr() as *mut [T; N]; + let ptr = self.as_mut_ptr().cast_array(); // SAFETY: The underlying array of a slice can be reinterpreted as an actual array `[T; N]` if `N` is not greater than the slice's length. let me = unsafe { &mut *ptr }; diff --git a/library/coretests/tests/io/borrowed_buf.rs b/library/coretests/tests/io/borrowed_buf.rs index 4074148436c..aaa98d26ff8 100644 --- a/library/coretests/tests/io/borrowed_buf.rs +++ b/library/coretests/tests/io/borrowed_buf.rs @@ -66,7 +66,7 @@ fn clear() { #[test] fn set_init() { - let buf: &mut [_] = &mut [MaybeUninit::uninit(); 16]; + let buf: &mut [_] = &mut [MaybeUninit::zeroed(); 16]; let mut rbuf: BorrowedBuf<'_> = buf.into(); unsafe { @@ -134,7 +134,7 @@ fn reborrow_written() { #[test] fn cursor_set_init() { - let buf: &mut [_] = &mut [MaybeUninit::uninit(); 16]; + let buf: &mut [_] = &mut [MaybeUninit::zeroed(); 16]; let mut rbuf: BorrowedBuf<'_> = buf.into(); unsafe { diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 0c537530647..07b38c65898 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -281,9 +281,11 @@ #![feature(cfg_target_thread_local)] #![feature(cfi_encoding)] #![feature(char_max_len)] +#![feature(const_trait_impl)] #![feature(core_float_math)] #![feature(decl_macro)] #![feature(deprecated_suggestion)] +#![feature(derive_const)] #![feature(doc_cfg)] #![feature(doc_cfg_hide)] #![feature(doc_masked)] @@ -327,8 +329,13 @@ // tidy-alphabetical-start #![feature(bstr)] #![feature(bstr_internals)] +#![feature(cast_maybe_uninit)] #![feature(char_internals)] #![feature(clone_to_uninit)] +#![feature(const_cmp)] +#![feature(const_ops)] +#![feature(const_option_ops)] +#![feature(const_try)] #![feature(core_intrinsics)] #![feature(core_io_borrowed_buf)] #![feature(drop_guard)] diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index cff4f20b5a8..5e8d2f8e78e 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -60,6 +60,7 @@ impl<'a> PanicHookInfo<'a> { /// Returns the payload associated with the panic. /// /// This will commonly, but not always, be a `&'static str` or [`String`]. + /// If you only care about such payloads, use [`payload_as_str`] instead. /// /// A invocation of the `panic!()` macro in Rust 2021 or later will always result in a /// panic payload of type `&'static str` or `String`. @@ -69,6 +70,7 @@ impl<'a> PanicHookInfo<'a> { /// can result in a panic payload other than a `&'static str` or `String`. /// /// [`String`]: ../../std/string/struct.String.html + /// [`payload_as_str`]: PanicHookInfo::payload_as_str /// /// # Examples /// diff --git a/library/std/src/path.rs b/library/std/src/path.rs index e7ba6936435..3b52804d6be 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -2678,7 +2678,6 @@ impl Path { /// # Examples /// /// ``` - /// # #![feature(path_file_prefix)] /// use std::path::Path; /// /// assert_eq!("foo", Path::new("foo.rs").file_prefix().unwrap()); @@ -2693,7 +2692,7 @@ impl Path { /// /// [`Path::file_stem`]: Path::file_stem /// - #[unstable(feature = "path_file_prefix", issue = "86319")] + #[stable(feature = "path_file_prefix", since = "CURRENT_RUSTC_VERSION")] #[must_use] pub fn file_prefix(&self) -> Option<&OsStr> { self.file_name().map(split_file_at_dot).and_then(|(before, _after)| Some(before)) diff --git a/library/std/src/sync/mpsc.rs b/library/std/src/sync/mpsc.rs index 41d1dd3ce67..03d7fddc2fa 100644 --- a/library/std/src/sync/mpsc.rs +++ b/library/std/src/sync/mpsc.rs @@ -697,14 +697,14 @@ impl<T> SyncSender<T> { /// let sync_sender2 = sync_sender.clone(); /// /// // First thread owns sync_sender - /// thread::spawn(move || { + /// let handle1 = thread::spawn(move || { /// sync_sender.send(1).unwrap(); /// sync_sender.send(2).unwrap(); /// // Thread blocked /// }); /// /// // Second thread owns sync_sender2 - /// thread::spawn(move || { + /// let handle2 = thread::spawn(move || { /// // This will return an error and send /// // no message if the buffer is full /// let _ = sync_sender2.try_send(3); @@ -722,6 +722,10 @@ impl<T> SyncSender<T> { /// Ok(msg) => println!("message {msg} received"), /// Err(_) => println!("the third message was never sent"), /// } + /// + /// // Wait for threads to complete + /// handle1.join().unwrap(); + /// handle2.join().unwrap(); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn try_send(&self, t: T) -> Result<(), TrySendError<T>> { diff --git a/library/std/src/sys/fs/windows.rs b/library/std/src/sys/fs/windows.rs index 09feddd0be9..bb3e4bc30ca 100644 --- a/library/std/src/sys/fs/windows.rs +++ b/library/std/src/sys/fs/windows.rs @@ -1606,7 +1606,7 @@ pub fn junction_point(original: &Path, link: &Path) -> io::Result<()> { }; unsafe { let ptr = header.PathBuffer.as_mut_ptr(); - ptr.copy_from(abs_path.as_ptr().cast::<MaybeUninit<u16>>(), abs_path.len()); + ptr.copy_from(abs_path.as_ptr().cast_uninit(), abs_path.len()); let mut ret = 0; cvt(c::DeviceIoControl( diff --git a/library/std/src/sys/pal/hermit/time.rs b/library/std/src/sys/pal/hermit/time.rs index f76a5f96c87..89a427ab88b 100644 --- a/library/std/src/sys/pal/hermit/time.rs +++ b/library/std/src/sys/pal/hermit/time.rs @@ -25,8 +25,15 @@ impl Timespec { Timespec { t: timespec { tv_sec, tv_nsec } } } - fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> { - if self >= other { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + const fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> { + // FIXME: const PartialOrd + let mut cmp = self.t.tv_sec - other.t.tv_sec; + if cmp == 0 { + cmp = self.t.tv_nsec as i64 - other.t.tv_nsec as i64; + } + + if cmp >= 0 { Ok(if self.t.tv_nsec >= other.t.tv_nsec { Duration::new( (self.t.tv_sec - other.t.tv_sec) as u64, @@ -46,20 +53,22 @@ impl Timespec { } } - fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + const fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> { let mut secs = self.t.tv_sec.checked_add_unsigned(other.as_secs())?; // Nano calculations can't overflow because nanos are <1B which fit // in a u32. - let mut nsec = other.subsec_nanos() + u32::try_from(self.t.tv_nsec).unwrap(); - if nsec >= NSEC_PER_SEC.try_into().unwrap() { - nsec -= u32::try_from(NSEC_PER_SEC).unwrap(); + let mut nsec = other.subsec_nanos() + self.t.tv_nsec as u32; + if nsec >= NSEC_PER_SEC as u32 { + nsec -= NSEC_PER_SEC as u32; secs = secs.checked_add(1)?; } Some(Timespec { t: timespec { tv_sec: secs, tv_nsec: nsec as _ } }) } - fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + const fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> { let mut secs = self.t.tv_sec.checked_sub_unsigned(other.as_secs())?; // Similar to above, nanos can't overflow. @@ -213,15 +222,18 @@ impl SystemTime { SystemTime(time) } - pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { self.0.sub_timespec(&other.0) } - pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { Some(SystemTime(self.0.checked_add_duration(other)?)) } - pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { Some(SystemTime(self.0.checked_sub_duration(other)?)) } } diff --git a/library/std/src/sys/pal/sgx/time.rs b/library/std/src/sys/pal/sgx/time.rs index db4cf2804bf..603dae952ab 100644 --- a/library/std/src/sys/pal/sgx/time.rs +++ b/library/std/src/sys/pal/sgx/time.rs @@ -32,15 +32,22 @@ impl SystemTime { SystemTime(usercalls::insecure_time()) } - pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { - self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0) + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { + // FIXME: ok_or_else with const closures + match self.0.checked_sub(other.0) { + Some(duration) => Ok(duration), + None => Err(other.0 - self.0), + } } - pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { Some(SystemTime(self.0.checked_add(*other)?)) } - pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { Some(SystemTime(self.0.checked_sub(*other)?)) } } diff --git a/library/std/src/sys/pal/solid/time.rs b/library/std/src/sys/pal/solid/time.rs index c39d715c6a6..e35e60df1a0 100644 --- a/library/std/src/sys/pal/solid/time.rs +++ b/library/std/src/sys/pal/solid/time.rs @@ -39,7 +39,8 @@ impl SystemTime { Self(t) } - pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { if self.0 >= other.0 { Ok(Duration::from_secs((self.0 as u64).wrapping_sub(other.0 as u64))) } else { @@ -47,11 +48,13 @@ impl SystemTime { } } - pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { Some(SystemTime(self.0.checked_add_unsigned(other.as_secs())?)) } - pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { Some(SystemTime(self.0.checked_sub_unsigned(other.as_secs())?)) } } diff --git a/library/std/src/sys/pal/uefi/time.rs b/library/std/src/sys/pal/uefi/time.rs index a5ab7690327..df5611b2ddd 100644 --- a/library/std/src/sys/pal/uefi/time.rs +++ b/library/std/src/sys/pal/uefi/time.rs @@ -80,19 +80,32 @@ impl SystemTime { .unwrap_or_else(|| panic!("time not implemented on this platform")) } - pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { - self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0) + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { + // FIXME: ok_or_else with const closures + match self.0.checked_sub(other.0) { + Some(duration) => Ok(duration), + None => Err(other.0 - self.0), + } } - pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { - let temp = Self(self.0.checked_add(*other)?); + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { + let temp = self.0.checked_add(*other)?; // Check if can be represented in UEFI - if temp <= MAX_UEFI_TIME { Some(temp) } else { None } + // FIXME: const PartialOrd + let mut cmp = temp.as_secs() - MAX_UEFI_TIME.0.as_secs(); + if cmp == 0 { + cmp = temp.subsec_nanos() as u64 - MAX_UEFI_TIME.0.subsec_nanos() as u64; + } + + if cmp <= 0 { Some(SystemTime(temp)) } else { None } } - pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { - self.0.checked_sub(*other).map(Self) + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { + Some(SystemTime(self.0.checked_sub(*other)?)) } } diff --git a/library/std/src/sys/pal/unix/time.rs b/library/std/src/sys/pal/unix/time.rs index bd7f74fea6a..328fe0bc960 100644 --- a/library/std/src/sys/pal/unix/time.rs +++ b/library/std/src/sys/pal/unix/time.rs @@ -38,15 +38,18 @@ impl SystemTime { SystemTime { t: Timespec::now(libc::CLOCK_REALTIME) } } - pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { self.t.sub_timespec(&other.t) } - pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { Some(SystemTime { t: self.t.checked_add_duration(other)? }) } - pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { Some(SystemTime { t: self.t.checked_sub_duration(other)? }) } } @@ -133,8 +136,15 @@ impl Timespec { Timespec::new(t.tv_sec as i64, t.tv_nsec as i64).unwrap() } - pub fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> { - if self >= other { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> { + // FIXME: const PartialOrd + let mut cmp = self.tv_sec - other.tv_sec; + if cmp == 0 { + cmp = self.tv_nsec.as_inner() as i64 - other.tv_nsec.as_inner() as i64; + } + + if cmp >= 0 { // NOTE(eddyb) two aspects of this `if`-`else` are required for LLVM // to optimize it into a branchless form (see also #75545): // @@ -169,7 +179,8 @@ impl Timespec { } } - pub fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> { let mut secs = self.tv_sec.checked_add_unsigned(other.as_secs())?; // Nano calculations can't overflow because nanos are <1B which fit @@ -179,10 +190,11 @@ impl Timespec { nsec -= NSEC_PER_SEC as u32; secs = secs.checked_add(1)?; } - Some(unsafe { Timespec::new_unchecked(secs, nsec.into()) }) + Some(unsafe { Timespec::new_unchecked(secs, nsec as i64) }) } - pub fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> { let mut secs = self.tv_sec.checked_sub_unsigned(other.as_secs())?; // Similar to above, nanos can't overflow. @@ -191,7 +203,7 @@ impl Timespec { nsec += NSEC_PER_SEC as i32; secs = secs.checked_sub(1)?; } - Some(unsafe { Timespec::new_unchecked(secs, nsec.into()) }) + Some(unsafe { Timespec::new_unchecked(secs, nsec as i64) }) } #[allow(dead_code)] diff --git a/library/std/src/sys/pal/unsupported/time.rs b/library/std/src/sys/pal/unsupported/time.rs index 6d67b538a96..0c387917044 100644 --- a/library/std/src/sys/pal/unsupported/time.rs +++ b/library/std/src/sys/pal/unsupported/time.rs @@ -31,15 +31,22 @@ impl SystemTime { panic!("time not implemented on this platform") } - pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { - self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0) + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { + // FIXME: ok_or_else with const closures + match self.0.checked_sub(other.0) { + Some(duration) => Ok(duration), + None => Err(other.0 - self.0), + } } - pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { Some(SystemTime(self.0.checked_add(*other)?)) } - pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { Some(SystemTime(self.0.checked_sub(*other)?)) } } diff --git a/library/std/src/sys/pal/wasi/time.rs b/library/std/src/sys/pal/wasi/time.rs index 0d8d0b59ac1..892661b312b 100644 --- a/library/std/src/sys/pal/wasi/time.rs +++ b/library/std/src/sys/pal/wasi/time.rs @@ -43,23 +43,34 @@ impl SystemTime { SystemTime(current_time(wasi::CLOCKID_REALTIME)) } - pub fn from_wasi_timestamp(ts: wasi::Timestamp) -> SystemTime { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn from_wasi_timestamp(ts: wasi::Timestamp) -> SystemTime { SystemTime(Duration::from_nanos(ts)) } - pub fn to_wasi_timestamp(&self) -> Option<wasi::Timestamp> { - self.0.as_nanos().try_into().ok() + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn to_wasi_timestamp(&self) -> Option<wasi::Timestamp> { + // FIXME: const TryInto + let ns = self.0.as_nanos(); + if ns <= u64::MAX as u128 { Some(ns as u64) } else { None } } - pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { - self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0) + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { + // FIXME: ok_or_else with const closures + match self.0.checked_sub(other.0) { + Some(duration) => Ok(duration), + None => Err(other.0 - self.0), + } } - pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { Some(SystemTime(self.0.checked_add(*other)?)) } - pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { Some(SystemTime(self.0.checked_sub(*other)?)) } } diff --git a/library/std/src/sys/pal/windows/time.rs b/library/std/src/sys/pal/windows/time.rs index 68126bd8d2f..a948c07e0a3 100644 --- a/library/std/src/sys/pal/windows/time.rs +++ b/library/std/src/sys/pal/windows/time.rs @@ -72,7 +72,8 @@ impl SystemTime { } } - fn from_intervals(intervals: i64) -> SystemTime { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + const fn from_intervals(intervals: i64) -> SystemTime { SystemTime { t: c::FILETIME { dwLowDateTime: intervals as u32, @@ -81,11 +82,13 @@ impl SystemTime { } } - fn intervals(&self) -> i64 { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + const fn intervals(&self) -> i64 { (self.t.dwLowDateTime as i64) | ((self.t.dwHighDateTime as i64) << 32) } - pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { let me = self.intervals(); let other = other.intervals(); if me >= other { @@ -95,12 +98,14 @@ impl SystemTime { } } - pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { let intervals = self.intervals().checked_add(checked_dur2intervals(other)?)?; Some(SystemTime::from_intervals(intervals)) } - pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { let intervals = self.intervals().checked_sub(checked_dur2intervals(other)?)?; Some(SystemTime::from_intervals(intervals)) } @@ -150,15 +155,18 @@ impl Hash for SystemTime { } } -fn checked_dur2intervals(dur: &Duration) -> Option<i64> { - dur.as_secs() +#[rustc_const_unstable(feature = "const_system_time", issue = "144517")] +const fn checked_dur2intervals(dur: &Duration) -> Option<i64> { + // FIXME: const TryInto + let secs = dur + .as_secs() .checked_mul(INTERVALS_PER_SEC)? - .checked_add(dur.subsec_nanos() as u64 / 100)? - .try_into() - .ok() + .checked_add(dur.subsec_nanos() as u64 / 100)?; + if secs <= i64::MAX as u64 { Some(secs.cast_signed()) } else { None } } -fn intervals2dur(intervals: u64) -> Duration { +#[rustc_const_unstable(feature = "const_system_time", issue = "144517")] +const fn intervals2dur(intervals: u64) -> Duration { Duration::new(intervals / INTERVALS_PER_SEC, ((intervals % INTERVALS_PER_SEC) * 100) as u32) } diff --git a/library/std/src/sys/pal/xous/time.rs b/library/std/src/sys/pal/xous/time.rs index ae8be81c0b7..d737416436e 100644 --- a/library/std/src/sys/pal/xous/time.rs +++ b/library/std/src/sys/pal/xous/time.rs @@ -43,15 +43,22 @@ impl SystemTime { SystemTime { 0: Duration::from_millis((upper as u64) << 32 | lower as u64) } } - pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { - self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0) + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { + // FIXME: ok_or_else with const closures + match self.0.checked_sub(other.0) { + Some(duration) => Ok(duration), + None => Err(other.0 - self.0), + } } - pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { Some(SystemTime(self.0.checked_add(*other)?)) } - pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { Some(SystemTime(self.0.checked_sub(*other)?)) } } diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs index cce88d936b7..24b6cff1309 100644 --- a/library/std/src/sys_common/mod.rs +++ b/library/std/src/sys_common/mod.rs @@ -51,17 +51,16 @@ pub trait FromInner<Inner> { fn from_inner(inner: Inner) -> Self; } -// Computes (value*numer)/denom without overflow, as long as both -// (numer*denom) and the overall result fit into i64 (which is the case -// for our time conversions). +// Computes (value*numerator)/denom without overflow, as long as both (numerator*denom) and the +// overall result fit into i64 (which is the case for our time conversions). #[allow(dead_code)] // not used on all platforms -pub fn mul_div_u64(value: u64, numer: u64, denom: u64) -> u64 { +pub fn mul_div_u64(value: u64, numerator: u64, denom: u64) -> u64 { let q = value / denom; let r = value % denom; // Decompose value as (value/denom*denom + value%denom), - // substitute into (value*numer)/denom and simplify. - // r < denom, so (denom*numer) is the upper bound of (r*numer) - q * numer + r * numer / denom + // substitute into (value*numerator)/denom and simplify. + // r < denom, so (denom*numerator) is the upper bound of (r*numerator) + q * numerator + r * numerator / denom } pub fn ignore_notfound<T>(result: crate::io::Result<T>) -> crate::io::Result<()> { diff --git a/library/std/src/time.rs b/library/std/src/time.rs index cd0683f44c9..07bb41f1496 100644 --- a/library/std/src/time.rs +++ b/library/std/src/time.rs @@ -551,8 +551,13 @@ impl SystemTime { /// println!("{difference:?}"); /// ``` #[stable(feature = "time2", since = "1.8.0")] - pub fn duration_since(&self, earlier: SystemTime) -> Result<Duration, SystemTimeError> { - self.0.sub_time(&earlier.0).map_err(SystemTimeError) + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn duration_since(&self, earlier: SystemTime) -> Result<Duration, SystemTimeError> { + // FIXME: map_err in const + match self.0.sub_time(&earlier.0) { + Ok(time) => Ok(time), + Err(err) => Err(SystemTimeError(err)), + } } /// Returns the difference from this system time to the @@ -589,7 +594,8 @@ impl SystemTime { /// `SystemTime` (which means it's inside the bounds of the underlying data structure), `None` /// otherwise. #[stable(feature = "time_checked_add", since = "1.34.0")] - pub fn checked_add(&self, duration: Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_add(&self, duration: Duration) -> Option<SystemTime> { self.0.checked_add_duration(&duration).map(SystemTime) } @@ -597,13 +603,15 @@ impl SystemTime { /// `SystemTime` (which means it's inside the bounds of the underlying data structure), `None` /// otherwise. #[stable(feature = "time_checked_add", since = "1.34.0")] - pub fn checked_sub(&self, duration: Duration) -> Option<SystemTime> { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn checked_sub(&self, duration: Duration) -> Option<SystemTime> { self.0.checked_sub_duration(&duration).map(SystemTime) } } #[stable(feature = "time2", since = "1.8.0")] -impl Add<Duration> for SystemTime { +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] +impl const Add<Duration> for SystemTime { type Output = SystemTime; /// # Panics @@ -616,14 +624,16 @@ impl Add<Duration> for SystemTime { } #[stable(feature = "time_augmented_assignment", since = "1.9.0")] -impl AddAssign<Duration> for SystemTime { +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] +impl const AddAssign<Duration> for SystemTime { fn add_assign(&mut self, other: Duration) { *self = *self + other; } } #[stable(feature = "time2", since = "1.8.0")] -impl Sub<Duration> for SystemTime { +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] +impl const Sub<Duration> for SystemTime { type Output = SystemTime; fn sub(self, dur: Duration) -> SystemTime { @@ -632,7 +642,8 @@ impl Sub<Duration> for SystemTime { } #[stable(feature = "time_augmented_assignment", since = "1.9.0")] -impl SubAssign<Duration> for SystemTime { +#[rustc_const_unstable(feature = "const_ops", issue = "143802")] +impl const SubAssign<Duration> for SystemTime { fn sub_assign(&mut self, other: Duration) { *self = *self - other; } @@ -699,7 +710,8 @@ impl SystemTimeError { /// ``` #[must_use] #[stable(feature = "time2", since = "1.8.0")] - pub fn duration(&self) -> Duration { + #[rustc_const_unstable(feature = "const_system_time", issue = "144517")] + pub const fn duration(&self) -> Duration { self.0 } } diff --git a/library/std/tests/path.rs b/library/std/tests/path.rs index 901d2770f20..e1576a0d423 100644 --- a/library/std/tests/path.rs +++ b/library/std/tests/path.rs @@ -1,10 +1,4 @@ -#![feature( - clone_to_uninit, - path_add_extension, - path_file_prefix, - maybe_uninit_slice, - normalize_lexically -)] +#![feature(clone_to_uninit, path_add_extension, maybe_uninit_slice, normalize_lexically)] use std::clone::CloneToUninit; use std::ffi::OsStr; diff --git a/library/stdarch/crates/core_arch/src/lib.rs b/library/stdarch/crates/core_arch/src/lib.rs index c58580f6417..7d3cbd55ad8 100644 --- a/library/stdarch/crates/core_arch/src/lib.rs +++ b/library/stdarch/crates/core_arch/src/lib.rs @@ -18,8 +18,6 @@ rustc_attrs, staged_api, doc_cfg, - tbm_target_feature, - sse4a_target_feature, riscv_target_feature, arm_target_feature, mips_target_feature, diff --git a/library/test/src/cli.rs b/library/test/src/cli.rs index 8840714a662..1b3f9e2564c 100644 --- a/library/test/src/cli.rs +++ b/library/test/src/cli.rs @@ -162,18 +162,17 @@ tests whose names contain the filter are run. Multiple filter strings may be passed, which will run all tests matching any of the filters. By default, all tests are run in parallel. This can be altered with the ---test-threads flag or the RUST_TEST_THREADS environment variable when running -tests (set it to 1). +--test-threads flag when running tests (set it to 1). -By default, the tests are run in alphabetical order. Use --shuffle or set -RUST_TEST_SHUFFLE to run the tests in random order. Pass the generated -"shuffle seed" to --shuffle-seed (or set RUST_TEST_SHUFFLE_SEED) to run the -tests in the same order again. Note that --shuffle and --shuffle-seed do not -affect whether the tests are run in parallel. +By default, the tests are run in alphabetical order. Use --shuffle to run +the tests in random order. Pass the generated "shuffle seed" to +--shuffle-seed to run the tests in the same order again. Note that +--shuffle and --shuffle-seed do not affect whether the tests are run in +parallel. All tests have their standard output and standard error captured by default. -This can be overridden with the --no-capture flag or setting RUST_TEST_NOCAPTURE -environment variable to a value other than "0". Logging is not captured by default. +This can be overridden with the --no-capture flag to a value other than "0". +Logging is not captured by default. Test Attributes: diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index 044d360ac37..537f4b6184f 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -12,21 +12,18 @@ dependencies = [ ] [[package]] -name = "ansi_term" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" -dependencies = [ - "winapi", -] - -[[package]] name = "anstyle" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] name = "bitflags" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -47,6 +44,7 @@ version = "0.0.0" dependencies = [ "build_helper", "cc", + "chrono", "clap", "clap_complete", "cmake", @@ -71,7 +69,6 @@ dependencies = [ "toml", "tracing", "tracing-chrome", - "tracing-forest", "tracing-subscriber", "walkdir", "windows", @@ -113,6 +110,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] +name = "chrono" +version = "0.4.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" +dependencies = [ + "num-traits", +] + +[[package]] name = "clap" version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -459,6 +465,15 @@ dependencies = [ ] [[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] name = "objc2-core-foundation" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -776,26 +791,6 @@ dependencies = [ ] [[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] name = "thread_local" version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -858,19 +853,6 @@ dependencies = [ ] [[package]] -name = "tracing-forest" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee40835db14ddd1e3ba414292272eddde9dad04d3d4b65509656414d1c42592f" -dependencies = [ - "ansi_term", - "smallvec", - "thiserror", - "tracing", - "tracing-subscriber", -] - -[[package]] name = "tracing-log" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 60d4976b934..bdf0b42255e 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -7,7 +7,7 @@ default-run = "bootstrap" [features] build-metrics = ["sysinfo"] -tracing = ["dep:tracing", "dep:tracing-chrome", "dep:tracing-subscriber", "dep:tracing-forest"] +tracing = ["dep:tracing", "dep:tracing-chrome", "dep:tracing-subscriber", "dep:chrono", "dep:tempfile"] [lib] path = "src/lib.rs" @@ -61,10 +61,11 @@ xz2 = "0.1" sysinfo = { version = "0.37.0", default-features = false, optional = true, features = ["system"] } # Dependencies needed by the `tracing` feature +chrono = { version = "0.4", default-features = false, optional = true, features = ["now", "std"] } tracing = { version = "0.1", optional = true, features = ["attributes"] } tracing-chrome = { version = "0.7", optional = true } tracing-subscriber = { version = "0.3", optional = true, features = ["env-filter", "fmt", "registry", "std"] } -tracing-forest = { version = "0.1.6", optional = true, default-features = false, features = ["smallvec", "ansi", "env-filter"] } +tempfile = { version = "3.15.0", optional = true } [target.'cfg(windows)'.dependencies.junction] version = "1.0.0" diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs index cf24fedaebb..8b2d67266a7 100644 --- a/src/bootstrap/src/bin/main.rs +++ b/src/bootstrap/src/bin/main.rs @@ -7,6 +7,7 @@ use std::fs::{self, OpenOptions}; use std::io::{self, BufRead, BufReader, IsTerminal, Write}; +use std::path::Path; use std::str::FromStr; use std::time::Instant; use std::{env, process}; @@ -15,19 +16,16 @@ use bootstrap::{ Build, CONFIG_CHANGE_HISTORY, ChangeId, Config, Flags, Subcommand, debug, find_recent_config_change_ids, human_readable_changes, t, }; -#[cfg(feature = "tracing")] -use tracing::instrument; -fn is_bootstrap_profiling_enabled() -> bool { - env::var("BOOTSTRAP_PROFILE").is_ok_and(|v| v == "1") +fn is_tracing_enabled() -> bool { + cfg!(feature = "tracing") } -#[cfg_attr(feature = "tracing", instrument(level = "trace", name = "main"))] fn main() { #[cfg(feature = "tracing")] - let _guard = setup_tracing(); + let guard = bootstrap::setup_tracing("BOOTSTRAP_TRACING"); - let start_time = Instant::now(); + let _start_time = Instant::now(); let args = env::args().skip(1).collect::<Vec<_>>(); @@ -102,6 +100,35 @@ fn main() { let dump_bootstrap_shims = config.dump_bootstrap_shims; let out_dir = config.out.clone(); + let tracing_enabled = is_tracing_enabled(); + + // Prepare a directory for tracing output + // Also store a symlink named "latest" to point to the latest tracing directory. + let tracing_dir = out_dir.join("bootstrap-trace").join(std::process::id().to_string()); + let latest_trace_dir = tracing_dir.parent().unwrap().join("latest"); + if tracing_enabled { + let _ = std::fs::remove_dir_all(&tracing_dir); + std::fs::create_dir_all(&tracing_dir).unwrap(); + + #[cfg(windows)] + let _ = std::fs::remove_dir(&latest_trace_dir); + #[cfg(not(windows))] + let _ = std::fs::remove_file(&latest_trace_dir); + + #[cfg(not(windows))] + fn symlink_dir_inner(original: &Path, link: &Path) -> io::Result<()> { + use std::os::unix::fs; + fs::symlink(original, link) + } + + #[cfg(windows)] + fn symlink_dir_inner(target: &Path, junction: &Path) -> io::Result<()> { + junction::create(target, junction) + } + + t!(symlink_dir_inner(&tracing_dir, &latest_trace_dir)); + } + debug!("creating new build based on config"); let mut build = Build::new(config); build.build(); @@ -156,12 +183,13 @@ fn main() { } } - if is_bootstrap_profiling_enabled() { - build.report_summary(start_time); - } - #[cfg(feature = "tracing")] - build.report_step_graph(); + { + build.report_summary(&tracing_dir.join("command-stats.txt"), _start_time); + build.report_step_graph(&tracing_dir); + guard.copy_to_dir(&tracing_dir); + eprintln!("Tracing/profiling output has been written to {}", latest_trace_dir.display()); + } } fn check_version(config: &Config) -> Option<String> { @@ -219,37 +247,3 @@ fn check_version(config: &Config) -> Option<String> { Some(msg) } - -// # Note on `tracing` usage in bootstrap -// -// Due to the conditional compilation via the `tracing` cargo feature, this means that `tracing` -// usages in bootstrap need to be also gated behind the `tracing` feature: -// -// - `tracing` macros with log levels (`trace!`, `debug!`, `warn!`, `info`, `error`) should not be -// used *directly*. You should use the wrapped `tracing` macros which gate the actual invocations -// behind `feature = "tracing"`. -// - `tracing`'s `#[instrument(..)]` macro will need to be gated like `#![cfg_attr(feature = -// "tracing", instrument(..))]`. -#[cfg(feature = "tracing")] -fn setup_tracing() -> impl Drop { - use tracing_forest::ForestLayer; - use tracing_subscriber::EnvFilter; - use tracing_subscriber::layer::SubscriberExt; - - let filter = EnvFilter::from_env("BOOTSTRAP_TRACING"); - - let mut chrome_layer = tracing_chrome::ChromeLayerBuilder::new().include_args(true); - - // Writes the Chrome profile to trace-<unix-timestamp>.json if enabled - if !is_bootstrap_profiling_enabled() { - chrome_layer = chrome_layer.writer(io::sink()); - } - - let (chrome_layer, _guard) = chrome_layer.build(); - - let registry = - tracing_subscriber::registry().with(filter).with(ForestLayer::default()).with(chrome_layer); - - tracing::subscriber::set_global_default(registry).unwrap(); - _guard -} diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs index 0cbf8f55e99..1e08e8547dc 100644 --- a/src/bootstrap/src/core/build_steps/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -30,10 +30,6 @@ pub struct Std { impl Std { const CRATE_OR_DEPS: &[&str] = &["sysroot", "coretests", "alloctests"]; - - pub fn new(build_compiler: Compiler, target: TargetSelection) -> Self { - Self { build_compiler, target, crates: vec![] } - } } impl Step for Std { @@ -168,19 +164,15 @@ pub struct Rustc { } impl Rustc { - pub fn new(builder: &Builder<'_>, build_compiler: Compiler, target: TargetSelection) -> Self { - let crates = builder - .in_tree_crates("rustc-main", Some(target)) - .into_iter() - .map(|krate| krate.name.to_string()) - .collect(); + pub fn new(builder: &Builder<'_>, target: TargetSelection, crates: Vec<String>) -> Self { + let build_compiler = prepare_compiler_for_check(builder, target, Mode::Rustc); Self { build_compiler, target, crates } } } impl Step for Rustc { type Output = (); - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -189,11 +181,7 @@ impl Step for Rustc { fn make_run(run: RunConfig<'_>) { let crates = run.make_run_crates(Alias::Compiler); - run.builder.ensure(Rustc { - target: run.target, - build_compiler: prepare_compiler_for_check(run.builder, run.target, Mode::Rustc), - crates, - }); + run.builder.ensure(Rustc::new(run.builder, run.target, crates)); } /// Check the compiler. @@ -207,15 +195,6 @@ impl Step for Rustc { let build_compiler = self.build_compiler; let target = self.target; - // Build host std for compiling build scripts - builder.std(build_compiler, build_compiler.host); - - // Build target std so that the checked rustc can link to it during the check - // FIXME: maybe we can a way to only do a check of std here? - // But for that we would have to copy the stdlib rmetas to the sysroot of the build - // compiler, which conflicts with std rlibs, if we also build std. - builder.std(build_compiler, target); - let mut cargo = builder::Cargo::new( builder, build_compiler, @@ -253,12 +232,18 @@ impl Step for Rustc { } fn metadata(&self) -> Option<StepMetadata> { - Some(StepMetadata::check("rustc", self.target).built_by(self.build_compiler)) + let metadata = StepMetadata::check("rustc", self.target).built_by(self.build_compiler); + let metadata = if self.crates.is_empty() { + metadata + } else { + metadata.with_metadata(format!("({} crates)", self.crates.len())) + }; + Some(metadata) } } /// Prepares a compiler that will check something with the given `mode`. -fn prepare_compiler_for_check( +pub fn prepare_compiler_for_check( builder: &Builder<'_>, target: TargetSelection, mode: Mode, @@ -289,11 +274,13 @@ fn prepare_compiler_for_check( build_compiler } Mode::ToolRustc | Mode::Codegen => { - // FIXME: this is a hack, see description of Mode::Rustc below - let stage = if host == target { builder.top_stage - 1 } else { builder.top_stage }; - // When checking tool stage N, we check it with compiler stage N-1 - let build_compiler = builder.compiler(stage, host); - builder.ensure(Rustc::new(builder, build_compiler, target)); + // Check Rustc to produce the required rmeta artifacts for rustc_private, and then + // return the build compiler that was used to check rustc. + // We do not need to check examples/tests/etc. of Rustc for rustc_private, so we pass + // an empty set of crates, which will avoid using `cargo -p`. + let check = Rustc::new(builder, target, vec![]); + let build_compiler = check.build_compiler; + builder.ensure(check); build_compiler } Mode::Rustc => { @@ -305,7 +292,18 @@ fn prepare_compiler_for_check( // FIXME: remove this and either fix cross-compilation check on stage 2 (which has a // myriad of other problems) or disable cross-checking on stage 1. let stage = if host == target { builder.top_stage - 1 } else { builder.top_stage }; - builder.compiler(stage, host) + let build_compiler = builder.compiler(stage, host); + + // Build host std for compiling build scripts + builder.std(build_compiler, build_compiler.host); + + // Build target std so that the checked rustc can link to it during the check + // FIXME: maybe we can a way to only do a check of std here? + // But for that we would have to copy the stdlib rmetas to the sysroot of the build + // compiler, which conflicts with std rlibs, if we also build std. + builder.std(build_compiler, target); + + build_compiler } Mode::Std => { // When checking std stage N, we want to do it with the stage N compiler @@ -326,7 +324,7 @@ pub struct CodegenBackend { impl Step for CodegenBackend { type Output = (); - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -412,7 +410,7 @@ macro_rules! tool_check_step { impl Step for $name { type Output = (); - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; /// Most of the tool-checks using this macro are run by default. const DEFAULT: bool = true $( && $default )?; diff --git a/src/bootstrap/src/core/build_steps/clippy.rs b/src/bootstrap/src/core/build_steps/clippy.rs index 4d734fe5c66..3c4aa0886c2 100644 --- a/src/bootstrap/src/core/build_steps/clippy.rs +++ b/src/bootstrap/src/core/build_steps/clippy.rs @@ -1,14 +1,29 @@ //! Implementation of running clippy on the compiler, standard library and various tools. +//! +//! This serves a double purpose: +//! - The first is to run Clippy itself on in-tree code, in order to test and dogfood it. +//! - The second is to actually lint the in-tree codebase on CI, with a hard-coded set of rules, +//! which is performed by the `x clippy ci` command. +//! +//! In order to prepare a build compiler for running clippy, use the +//! [prepare_compiler_for_check] function. That prepares a +//! compiler and a standard library +//! for running Clippy. The second part (actually building Clippy) is performed inside +//! [Builder::cargo_clippy_cmd]. It would be nice if this was more explicit, and we actually had +//! to pass a prebuilt Clippy from the outside when running `cargo clippy`, but that would be +//! (as usual) a massive undertaking/refactoring. + +use build_helper::exit; -use super::check; use super::compile::{run_cargo, rustc_cargo, std_cargo}; use super::tool::{SourceType, prepare_tool_cargo}; use crate::builder::{Builder, ShouldRun}; +use crate::core::build_steps::check::prepare_compiler_for_check; use crate::core::build_steps::compile::std_crates_for_run_make; use crate::core::builder; -use crate::core::builder::{Alias, Kind, RunConfig, Step, crate_description}; +use crate::core::builder::{Alias, Kind, RunConfig, Step, StepMetadata, crate_description}; use crate::utils::build_stamp::{self, BuildStamp}; -use crate::{Mode, Subcommand, TargetSelection}; +use crate::{Compiler, Mode, Subcommand, TargetSelection}; /// Disable the most spammy clippy lints const IGNORED_RULES_FOR_STD_AND_RUSTC: &[&str] = &[ @@ -121,12 +136,38 @@ impl LintConfig { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Std { - pub target: TargetSelection, + build_compiler: Compiler, + target: TargetSelection, config: LintConfig, /// Whether to lint only a subset of crates. crates: Vec<String>, } +impl Std { + fn new( + builder: &Builder<'_>, + target: TargetSelection, + config: LintConfig, + crates: Vec<String>, + ) -> Self { + Self { + build_compiler: builder.compiler(builder.top_stage, builder.host_target), + target, + config, + crates, + } + } + + fn from_build_compiler( + build_compiler: Compiler, + target: TargetSelection, + config: LintConfig, + crates: Vec<String>, + ) -> Self { + Self { build_compiler, target, config, crates } + } +} + impl Step for Std { type Output = (); const DEFAULT: bool = true; @@ -138,12 +179,12 @@ impl Step for Std { fn make_run(run: RunConfig<'_>) { let crates = std_crates_for_run_make(&run); let config = LintConfig::new(run.builder); - run.builder.ensure(Std { target: run.target, config, crates }); + run.builder.ensure(Std::new(run.builder, run.target, config, crates)); } fn run(self, builder: &Builder<'_>) { let target = self.target; - let build_compiler = builder.compiler(builder.top_stage, builder.config.host_target); + let build_compiler = self.build_compiler; let mut cargo = builder::Cargo::new( builder, @@ -178,19 +219,44 @@ impl Step for Std { false, ); } + + fn metadata(&self) -> Option<StepMetadata> { + Some(StepMetadata::clippy("std", self.target).built_by(self.build_compiler)) + } } +/// Lints the compiler. +/// +/// This will build Clippy with the `build_compiler` and use it to lint +/// in-tree rustc. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Rustc { - pub target: TargetSelection, + build_compiler: Compiler, + target: TargetSelection, config: LintConfig, /// Whether to lint only a subset of crates. crates: Vec<String>, } +impl Rustc { + fn new( + builder: &Builder<'_>, + target: TargetSelection, + config: LintConfig, + crates: Vec<String>, + ) -> Self { + Self { + build_compiler: prepare_compiler_for_check(builder, target, Mode::Rustc), + target, + config, + crates, + } + } +} + impl Step for Rustc { type Output = (); - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -198,33 +264,16 @@ impl Step for Rustc { } fn make_run(run: RunConfig<'_>) { + let builder = run.builder; let crates = run.make_run_crates(Alias::Compiler); let config = LintConfig::new(run.builder); - run.builder.ensure(Rustc { target: run.target, config, crates }); + run.builder.ensure(Rustc::new(builder, run.target, config, crates)); } - /// Lints the compiler. - /// - /// This will lint the compiler for a particular stage of the build using - /// the `compiler` targeting the `target` architecture. fn run(self, builder: &Builder<'_>) { - let build_compiler = builder.compiler(builder.top_stage, builder.config.host_target); + let build_compiler = self.build_compiler; let target = self.target; - if !builder.download_rustc() { - if build_compiler.stage != 0 { - // If we're not in stage 0, then we won't have a std from the beta - // compiler around. That means we need to make sure there's one in - // the sysroot for the compiler to find. Otherwise, we're going to - // fail when building crates that need to generate code (e.g., build - // scripts and their dependencies). - builder.std(build_compiler, build_compiler.host); - builder.std(build_compiler, target); - } else { - builder.ensure(check::Std::new(build_compiler, target)); - } - } - let mut cargo = builder::Cargo::new( builder, build_compiler, @@ -261,11 +310,85 @@ impl Step for Rustc { false, ); } + + fn metadata(&self) -> Option<StepMetadata> { + Some(StepMetadata::clippy("rustc", self.target).built_by(self.build_compiler)) + } +} + +#[derive(Debug, Clone, Hash, PartialEq, Eq)] +pub struct CodegenGcc { + build_compiler: Compiler, + target: TargetSelection, + config: LintConfig, +} + +impl CodegenGcc { + fn new(builder: &Builder<'_>, target: TargetSelection, config: LintConfig) -> Self { + Self { + build_compiler: prepare_compiler_for_check(builder, target, Mode::Codegen), + target, + config, + } + } +} + +impl Step for CodegenGcc { + type Output = (); + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.alias("rustc_codegen_gcc") + } + + fn make_run(run: RunConfig<'_>) { + let builder = run.builder; + let config = LintConfig::new(builder); + builder.ensure(CodegenGcc::new(builder, run.target, config)); + } + + fn run(self, builder: &Builder<'_>) -> Self::Output { + let build_compiler = self.build_compiler; + let target = self.target; + + let cargo = prepare_tool_cargo( + builder, + build_compiler, + Mode::Codegen, + target, + Kind::Clippy, + "compiler/rustc_codegen_gcc", + SourceType::InTree, + &[], + ); + + let _guard = + builder.msg(Kind::Clippy, "rustc_codegen_gcc", Mode::ToolRustc, build_compiler, target); + + let stamp = BuildStamp::new(&builder.cargo_out(build_compiler, Mode::Codegen, target)) + .with_prefix("rustc_codegen_gcc-check"); + + run_cargo( + builder, + cargo, + lint_args(builder, &self.config, &[]), + &stamp, + vec![], + true, + false, + ); + } + + fn metadata(&self) -> Option<StepMetadata> { + Some(StepMetadata::clippy("rustc_codegen_gcc", self.target).built_by(self.build_compiler)) + } } macro_rules! lint_any { ($( - $name:ident, $path:expr, $readable_name:expr + $name:ident, + $path:expr, + $readable_name:expr, + $mode:expr $(,lint_by_default = $lint_by_default:expr)* ; )+) => { @@ -273,7 +396,8 @@ macro_rules! lint_any { #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct $name { - pub target: TargetSelection, + build_compiler: Compiler, + target: TargetSelection, config: LintConfig, } @@ -288,23 +412,19 @@ macro_rules! lint_any { fn make_run(run: RunConfig<'_>) { let config = LintConfig::new(run.builder); run.builder.ensure($name { + build_compiler: prepare_compiler_for_check(run.builder, run.target, $mode), target: run.target, config, }); } fn run(self, builder: &Builder<'_>) -> Self::Output { - let build_compiler = builder.compiler(builder.top_stage, builder.config.host_target); + let build_compiler = self.build_compiler; let target = self.target; - - if !builder.download_rustc() { - builder.ensure(check::Rustc::new(builder, build_compiler, target)); - }; - let cargo = prepare_tool_cargo( builder, build_compiler, - Mode::ToolRustc, + $mode, target, Kind::Clippy, $path, @@ -315,13 +435,13 @@ macro_rules! lint_any { let _guard = builder.msg( Kind::Clippy, $readable_name, - Mode::ToolRustc, + $mode, build_compiler, target, ); let stringified_name = stringify!($name).to_lowercase(); - let stamp = BuildStamp::new(&builder.cargo_out(build_compiler, Mode::ToolRustc, target)) + let stamp = BuildStamp::new(&builder.cargo_out(build_compiler, $mode, target)) .with_prefix(&format!("{}-check", stringified_name)); run_cargo( @@ -334,38 +454,44 @@ macro_rules! lint_any { false, ); } + + fn metadata(&self) -> Option<StepMetadata> { + Some(StepMetadata::clippy($readable_name, self.target).built_by(self.build_compiler)) + } } )+ } } +// Note: we use ToolTarget instead of ToolBootstrap here, to allow linting in-tree host tools +// using the in-tree Clippy. Because Mode::ToolBootstrap would always use stage 0 rustc/Clippy. lint_any!( - Bootstrap, "src/bootstrap", "bootstrap"; - BuildHelper, "src/build_helper", "build_helper"; - BuildManifest, "src/tools/build-manifest", "build-manifest"; - CargoMiri, "src/tools/miri/cargo-miri", "cargo-miri"; - Clippy, "src/tools/clippy", "clippy"; - CollectLicenseMetadata, "src/tools/collect-license-metadata", "collect-license-metadata"; - CodegenGcc, "compiler/rustc_codegen_gcc", "rustc-codegen-gcc"; - Compiletest, "src/tools/compiletest", "compiletest"; - CoverageDump, "src/tools/coverage-dump", "coverage-dump"; - Jsondocck, "src/tools/jsondocck", "jsondocck"; - Jsondoclint, "src/tools/jsondoclint", "jsondoclint"; - LintDocs, "src/tools/lint-docs", "lint-docs"; - LlvmBitcodeLinker, "src/tools/llvm-bitcode-linker", "llvm-bitcode-linker"; - Miri, "src/tools/miri", "miri"; - MiroptTestTools, "src/tools/miropt-test-tools", "miropt-test-tools"; - OptDist, "src/tools/opt-dist", "opt-dist"; - RemoteTestClient, "src/tools/remote-test-client", "remote-test-client"; - RemoteTestServer, "src/tools/remote-test-server", "remote-test-server"; - RustAnalyzer, "src/tools/rust-analyzer", "rust-analyzer"; - Rustdoc, "src/librustdoc", "clippy"; - Rustfmt, "src/tools/rustfmt", "rustfmt"; - RustInstaller, "src/tools/rust-installer", "rust-installer"; - Tidy, "src/tools/tidy", "tidy"; - TestFloatParse, "src/tools/test-float-parse", "test-float-parse"; + Bootstrap, "src/bootstrap", "bootstrap", Mode::ToolTarget; + BuildHelper, "src/build_helper", "build_helper", Mode::ToolTarget; + BuildManifest, "src/tools/build-manifest", "build-manifest", Mode::ToolTarget; + CargoMiri, "src/tools/miri/cargo-miri", "cargo-miri", Mode::ToolRustc; + Clippy, "src/tools/clippy", "clippy", Mode::ToolRustc; + CollectLicenseMetadata, "src/tools/collect-license-metadata", "collect-license-metadata", Mode::ToolTarget; + Compiletest, "src/tools/compiletest", "compiletest", Mode::ToolTarget; + CoverageDump, "src/tools/coverage-dump", "coverage-dump", Mode::ToolTarget; + Jsondocck, "src/tools/jsondocck", "jsondocck", Mode::ToolTarget; + Jsondoclint, "src/tools/jsondoclint", "jsondoclint", Mode::ToolTarget; + LintDocs, "src/tools/lint-docs", "lint-docs", Mode::ToolTarget; + LlvmBitcodeLinker, "src/tools/llvm-bitcode-linker", "llvm-bitcode-linker", Mode::ToolTarget; + Miri, "src/tools/miri", "miri", Mode::ToolRustc; + MiroptTestTools, "src/tools/miropt-test-tools", "miropt-test-tools", Mode::ToolTarget; + OptDist, "src/tools/opt-dist", "opt-dist", Mode::ToolTarget; + RemoteTestClient, "src/tools/remote-test-client", "remote-test-client", Mode::ToolTarget; + RemoteTestServer, "src/tools/remote-test-server", "remote-test-server", Mode::ToolTarget; + RustAnalyzer, "src/tools/rust-analyzer", "rust-analyzer", Mode::ToolRustc; + Rustdoc, "src/librustdoc", "clippy", Mode::ToolRustc; + Rustfmt, "src/tools/rustfmt", "rustfmt", Mode::ToolRustc; + RustInstaller, "src/tools/rust-installer", "rust-installer", Mode::ToolTarget; + Tidy, "src/tools/tidy", "tidy", Mode::ToolTarget; + TestFloatParse, "src/tools/test-float-parse", "test-float-parse", Mode::ToolStd; ); +/// Runs Clippy on in-tree sources of selected projects using in-tree CLippy. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct CI { target: TargetSelection, @@ -386,7 +512,21 @@ impl Step for CI { } fn run(self, builder: &Builder<'_>) -> Self::Output { + if builder.top_stage != 2 { + eprintln!("ERROR: `x clippy ci` should always be executed with --stage 2"); + exit!(1); + } + + // We want to check in-tree source using in-tree clippy. However, if we naively did + // a stage 2 `x clippy ci`, it would *build* a stage 2 rustc, in order to lint stage 2 + // std, which is wasteful. + // So we want to lint stage 2 [bootstrap/rustc/...], but only stage 1 std rustc_codegen_gcc. + // We thus construct the compilers in this step manually, to optimize the number of + // steps that get built. + builder.ensure(Bootstrap { + // This will be the stage 1 compiler + build_compiler: prepare_compiler_for_check(builder, self.target, Mode::ToolTarget), target: self.target, config: self.config.merge(&LintConfig { allow: vec![], @@ -395,6 +535,7 @@ impl Step for CI { forbid: vec![], }), }); + let library_clippy_cfg = LintConfig { allow: vec!["clippy::all".into()], warn: vec![], @@ -412,11 +553,13 @@ impl Step for CI { ], forbid: vec![], }; - builder.ensure(Std { - target: self.target, - config: self.config.merge(&library_clippy_cfg), - crates: vec![], - }); + builder.ensure(Std::from_build_compiler( + // This will be the stage 1 compiler, to avoid building rustc stage 2 just to lint std + builder.compiler(1, self.target), + self.target, + self.config.merge(&library_clippy_cfg), + vec![], + )); let compiler_clippy_cfg = LintConfig { allow: vec!["clippy::all".into()], @@ -437,11 +580,13 @@ impl Step for CI { ], forbid: vec![], }; - builder.ensure(Rustc { - target: self.target, - config: self.config.merge(&compiler_clippy_cfg), - crates: vec![], - }); + // This will lint stage 2 rustc using stage 1 Clippy + builder.ensure(Rustc::new( + builder, + self.target, + self.config.merge(&compiler_clippy_cfg), + vec![], + )); let rustc_codegen_gcc = LintConfig { allow: vec![], @@ -449,9 +594,11 @@ impl Step for CI { deny: vec!["warnings".into()], forbid: vec![], }; - builder.ensure(CodegenGcc { - target: self.target, - config: self.config.merge(&rustc_codegen_gcc), - }); + // This will check stage 2 rustc + builder.ensure(CodegenGcc::new( + builder, + self.target, + self.config.merge(&rustc_codegen_gcc), + )); } } diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index c8feba48d84..d860cafa1c0 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -16,9 +16,9 @@ use std::{env, fs, str}; use serde_derive::Deserialize; #[cfg(feature = "tracing")] -use tracing::{instrument, span}; +use tracing::span; -use crate::core::build_steps::gcc::{Gcc, add_cg_gcc_cargo_flags}; +use crate::core::build_steps::gcc::{Gcc, GccOutput, add_cg_gcc_cargo_flags}; use crate::core::build_steps::tool::{RustcPrivateCompilers, SourceType, copy_lld_artifacts}; use crate::core::build_steps::{dist, llvm}; use crate::core::builder; @@ -104,7 +104,6 @@ impl Step for Std { run.crate_or_deps("sysroot").path("library") } - #[cfg_attr(feature = "tracing", instrument(level = "trace", name = "Std::make_run", skip_all))] fn make_run(run: RunConfig<'_>) { let crates = std_crates_for_run_make(&run); let builder = run.builder; @@ -135,19 +134,6 @@ impl Step for Std { /// This will build the standard library for a particular stage of the build /// using the `compiler` targeting the `target` architecture. The artifacts /// created will also be linked into the sysroot directory. - #[cfg_attr( - feature = "tracing", - instrument( - level = "debug", - name = "Std::run", - skip_all, - fields( - target = ?self.target, - compiler = ?self.compiler, - force_recompile = self.force_recompile - ), - ), - )] fn run(self, builder: &Builder<'_>) { let target = self.target; @@ -717,19 +703,6 @@ impl Step for StdLink { /// Note that this assumes that `compiler` has already generated the libstd /// libraries for `target`, and this method will find them in the relevant /// output directory. - #[cfg_attr( - feature = "tracing", - instrument( - level = "trace", - name = "StdLink::run", - skip_all, - fields( - compiler = ?self.compiler, - target_compiler = ?self.target_compiler, - target = ?self.target - ), - ), - )] fn run(self, builder: &Builder<'_>) { let compiler = self.compiler; let target_compiler = self.target_compiler; @@ -895,15 +868,6 @@ impl Step for StartupObjects { /// They don't require any library support as they're just plain old object /// files, so we just use the nightly snapshot compiler to always build them (as /// no other compilers are guaranteed to be available). - #[cfg_attr( - feature = "tracing", - instrument( - level = "trace", - name = "StartupObjects::run", - skip_all, - fields(compiler = ?self.compiler, target = ?self.target), - ), - )] fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> { let for_compiler = self.compiler; let target = self.target; @@ -995,7 +959,7 @@ impl Step for Rustc { /// uplifting it from stage Y, causing the other stage to fail when attempting to link with /// stage X which was never actually built. type Output = u32; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; const DEFAULT: bool = false; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -1033,15 +997,6 @@ impl Step for Rustc { /// This will build the compiler for a particular stage of the build using /// the `build_compiler` targeting the `target` architecture. The artifacts /// created will also be linked into the sysroot directory. - #[cfg_attr( - feature = "tracing", - instrument( - level = "debug", - name = "Rustc::run", - skip_all, - fields(previous_compiler = ?self.build_compiler, target = ?self.target), - ), - )] fn run(self, builder: &Builder<'_>) -> u32 { let build_compiler = self.build_compiler; let target = self.target; @@ -1397,6 +1352,7 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS // Build jemalloc on AArch64 with support for page sizes up to 64K // See: https://github.com/rust-lang/rust/pull/135081 + // See also the "JEMALLOC_SYS_WITH_LG_PAGE" setting in the tool build step. if builder.config.jemalloc(target) && target.starts_with("aarch64") && env::var_os("JEMALLOC_SYS_WITH_LG_PAGE").is_none() @@ -1517,19 +1473,6 @@ impl Step for RustcLink { } /// Same as `std_link`, only for librustc - #[cfg_attr( - feature = "tracing", - instrument( - level = "trace", - name = "RustcLink::run", - skip_all, - fields( - compiler = ?self.compiler, - previous_stage_compiler = ?self.previous_stage_compiler, - target = ?self.target, - ), - ), - )] fn run(self, builder: &Builder<'_>) { let compiler = self.compiler; let previous_stage_compiler = self.previous_stage_compiler; @@ -1543,14 +1486,23 @@ impl Step for RustcLink { } } +/// Output of the `compile::GccCodegenBackend` step. +/// It includes the path to the libgccjit library on which this backend depends. +#[derive(Clone)] +pub struct GccCodegenBackendOutput { + stamp: BuildStamp, + gcc: GccOutput, +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct GccCodegenBackend { compilers: RustcPrivateCompilers, } impl Step for GccCodegenBackend { - type Output = BuildStamp; - const ONLY_HOSTS: bool = true; + type Output = GccCodegenBackendOutput; + + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.alias("rustc_codegen_gcc").alias("cg_gcc") @@ -1562,17 +1514,6 @@ impl Step for GccCodegenBackend { }); } - #[cfg_attr( - feature = "tracing", - instrument( - level = "debug", - name = "GccCodegenBackend::run", - skip_all, - fields( - compilers = ?self.compilers, - ), - ), - )] fn run(self, builder: &Builder<'_>) -> Self::Output { let target = self.compilers.target(); let build_compiler = self.compilers.build_compiler(); @@ -1584,6 +1525,8 @@ impl Step for GccCodegenBackend { &CodegenBackendKind::Gcc, ); + let gcc = builder.ensure(Gcc { target }); + if builder.config.keep_stage.contains(&build_compiler.stage) { trace!("`keep-stage` requested"); builder.info( @@ -1592,7 +1535,7 @@ impl Step for GccCodegenBackend { ); // Codegen backends are linked separately from this step today, so we don't do // anything here. - return stamp; + return GccCodegenBackendOutput { stamp, gcc }; } let mut cargo = builder::Cargo::new( @@ -1606,13 +1549,16 @@ impl Step for GccCodegenBackend { cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml")); rustc_cargo_env(builder, &mut cargo, target); - let gcc = builder.ensure(Gcc { target }); add_cg_gcc_cargo_flags(&mut cargo, &gcc); let _guard = builder.msg(Kind::Build, "codegen backend gcc", Mode::Codegen, build_compiler, target); let files = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false); - write_codegen_backend_stamp(stamp, files, builder.config.dry_run()) + + GccCodegenBackendOutput { + stamp: write_codegen_backend_stamp(stamp, files, builder.config.dry_run()), + gcc, + } } fn metadata(&self) -> Option<StepMetadata> { @@ -1630,7 +1576,7 @@ pub struct CraneliftCodegenBackend { impl Step for CraneliftCodegenBackend { type Output = BuildStamp; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.alias("rustc_codegen_cranelift").alias("cg_clif") @@ -1642,17 +1588,6 @@ impl Step for CraneliftCodegenBackend { }); } - #[cfg_attr( - feature = "tracing", - instrument( - level = "debug", - name = "CraneliftCodegenBackend::run", - skip_all, - fields( - compilers = ?self.compilers, - ), - ), - )] fn run(self, builder: &Builder<'_>) -> Self::Output { let target = self.compilers.target(); let build_compiler = self.compilers.build_compiler(); @@ -1827,15 +1762,6 @@ impl Step for Sysroot { /// Returns the sysroot that `compiler` is supposed to use. /// For the stage0 compiler, this is stage0-sysroot (because of the initial std build). /// For all other stages, it's the same stage directory that the compiler lives in. - #[cfg_attr( - feature = "tracing", - instrument( - level = "debug", - name = "Sysroot::run", - skip_all, - fields(compiler = ?self.compiler), - ), - )] fn run(self, builder: &Builder<'_>) -> PathBuf { let compiler = self.compiler; let host_dir = builder.out.join(compiler.host); @@ -1994,7 +1920,7 @@ pub struct Assemble { impl Step for Assemble { type Output = Compiler; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("compiler/rustc").path("compiler") @@ -2011,15 +1937,6 @@ impl Step for Assemble { /// This will assemble a compiler in `build/$host/stage$stage`. The compiler /// must have been previously produced by the `stage - 1` builder.build /// compiler. - #[cfg_attr( - feature = "tracing", - instrument( - level = "debug", - name = "Assemble::run", - skip_all, - fields(target_compiler = ?self.target_compiler), - ), - )] fn run(self, builder: &Builder<'_>) -> Compiler { let target_compiler = self.target_compiler; @@ -2191,53 +2108,6 @@ impl Step for Assemble { ); build_compiler.stage = actual_stage; - let mut codegen_backend_stamps = vec![]; - { - #[cfg(feature = "tracing")] - let _codegen_backend_span = - span!(tracing::Level::DEBUG, "building requested codegen backends").entered(); - - for backend in builder.config.enabled_codegen_backends(target_compiler.host) { - // FIXME: this is a horrible hack used to make `x check` work when other codegen - // backends are enabled. - // `x check` will check stage 1 rustc, which copies its rmetas to the stage0 sysroot. - // Then it checks codegen backends, which correctly use these rmetas. - // Then it needs to check std, but for that it needs to build stage 1 rustc. - // This copies the build rmetas into the stage0 sysroot, effectively poisoning it, - // because we then have both check and build rmetas in the same sysroot. - // That would be fine on its own. However, when another codegen backend is enabled, - // then building stage 1 rustc implies also building stage 1 codegen backend (even if - // it isn't used for anything). And since that tries to use the poisoned - // rmetas, it fails to build. - // We don't actually need to build rustc-private codegen backends for checking std, - // so instead we skip that. - // Note: this would be also an issue for other rustc-private tools, but that is "solved" - // by check::Std being last in the list of checked things (see - // `Builder::get_step_descriptions`). - if builder.kind == Kind::Check && builder.top_stage == 1 { - continue; - } - - let prepare_compilers = || { - RustcPrivateCompilers::from_build_and_target_compiler( - build_compiler, - target_compiler, - ) - }; - - let stamp = match backend { - CodegenBackendKind::Cranelift => { - builder.ensure(CraneliftCodegenBackend { compilers: prepare_compilers() }) - } - CodegenBackendKind::Gcc => { - builder.ensure(GccCodegenBackend { compilers: prepare_compilers() }) - } - CodegenBackendKind::Llvm | CodegenBackendKind::Custom(_) => continue, - }; - codegen_backend_stamps.push(stamp); - } - } - let stage = target_compiler.stage; let host = target_compiler.host; let (host_info, dir_name) = if build_compiler.host == host { @@ -2296,9 +2166,56 @@ impl Step for Assemble { } } - debug!("copying codegen backends to sysroot"); - for stamp in codegen_backend_stamps { - copy_codegen_backends_to_sysroot(builder, stamp, target_compiler); + { + #[cfg(feature = "tracing")] + let _codegen_backend_span = + span!(tracing::Level::DEBUG, "building requested codegen backends").entered(); + + for backend in builder.config.enabled_codegen_backends(target_compiler.host) { + // FIXME: this is a horrible hack used to make `x check` work when other codegen + // backends are enabled. + // `x check` will check stage 1 rustc, which copies its rmetas to the stage0 sysroot. + // Then it checks codegen backends, which correctly use these rmetas. + // Then it needs to check std, but for that it needs to build stage 1 rustc. + // This copies the build rmetas into the stage0 sysroot, effectively poisoning it, + // because we then have both check and build rmetas in the same sysroot. + // That would be fine on its own. However, when another codegen backend is enabled, + // then building stage 1 rustc implies also building stage 1 codegen backend (even if + // it isn't used for anything). And since that tries to use the poisoned + // rmetas, it fails to build. + // We don't actually need to build rustc-private codegen backends for checking std, + // so instead we skip that. + // Note: this would be also an issue for other rustc-private tools, but that is "solved" + // by check::Std being last in the list of checked things (see + // `Builder::get_step_descriptions`). + if builder.kind == Kind::Check && builder.top_stage == 1 { + continue; + } + + let prepare_compilers = || { + RustcPrivateCompilers::from_build_and_target_compiler( + build_compiler, + target_compiler, + ) + }; + + match backend { + CodegenBackendKind::Cranelift => { + let stamp = builder + .ensure(CraneliftCodegenBackend { compilers: prepare_compilers() }); + copy_codegen_backends_to_sysroot(builder, stamp, target_compiler); + } + CodegenBackendKind::Gcc => { + let output = + builder.ensure(GccCodegenBackend { compilers: prepare_compilers() }); + copy_codegen_backends_to_sysroot(builder, output.stamp, target_compiler); + // Also copy libgccjit to the library sysroot, so that it is available for + // the codegen backend. + output.gcc.install_to(builder, &rustc_libdir); + } + CodegenBackendKind::Llvm | CodegenBackendKind::Custom(_) => continue, + } + } } if builder.config.lld_enabled { @@ -2578,7 +2495,7 @@ pub fn stream_cargo( let mut cmd = cargo.into_cmd(); #[cfg(feature = "tracing")] - let _run_span = crate::trace_cmd!(cmd); + let _run_span = crate::utils::tracing::trace_cmd(&cmd); // Instruct Cargo to give us json messages on stdout, critically leaving // stderr as piped so we can get those pretty colors. diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index f9cb300b68e..64c2cdd2ec7 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -140,7 +140,7 @@ pub struct RustcDocs { impl Step for RustcDocs { type Output = Option<GeneratedTarball>; const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; @@ -402,7 +402,7 @@ pub struct Rustc { impl Step for Rustc { type Output = GeneratedTarball; const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.alias("rustc") @@ -478,7 +478,19 @@ impl Step for Rustc { if libdir_relative.to_str() != Some("bin") { let libdir = builder.rustc_libdir(compiler); for entry in builder.read_dir(&libdir) { - if is_dylib(&entry.path()) { + // A safeguard that we will not ship libgccjit.so from the libdir, in case the + // GCC codegen backend is enabled by default. + // Long-term we should probably split the config options for: + // - Include cg_gcc in the rustc sysroot by default + // - Run dist of a specific codegen backend in `x dist` by default + if is_dylib(&entry.path()) + && !entry + .path() + .file_name() + .and_then(|n| n.to_str()) + .map(|n| n.contains("libgccjit")) + .unwrap_or(false) + { // Don't use custom libdir here because ^lib/ will be resolved again // with installer builder.install(&entry.path(), &image.join("lib"), FileType::NativeLibrary); @@ -782,7 +794,7 @@ pub struct RustcDev { impl Step for RustcDev { type Output = Option<GeneratedTarball>; const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.alias("rustc-dev") @@ -1012,7 +1024,7 @@ impl Step for Src { /// The output path of the src installer tarball type Output = GeneratedTarball; const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.alias("rust-src") @@ -1073,7 +1085,7 @@ impl Step for PlainSourceTarball { /// Produces the location of the tarball generated type Output = GeneratedTarball; const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; @@ -1221,7 +1233,7 @@ pub struct Cargo { impl Step for Cargo { type Output = Option<GeneratedTarball>; const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let default = should_build_extended_tool(run.builder, "cargo"); @@ -1275,7 +1287,7 @@ pub struct RustAnalyzer { impl Step for RustAnalyzer { type Output = Option<GeneratedTarball>; const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let default = should_build_extended_tool(run.builder, "rust-analyzer"); @@ -1318,7 +1330,7 @@ pub struct Clippy { impl Step for Clippy { type Output = Option<GeneratedTarball>; const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let default = should_build_extended_tool(run.builder, "clippy"); @@ -1366,7 +1378,7 @@ pub struct Miri { impl Step for Miri { type Output = Option<GeneratedTarball>; const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let default = should_build_extended_tool(run.builder, "miri"); @@ -1410,12 +1422,13 @@ impl Step for Miri { #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct CraneliftCodegenBackend { pub build_compiler: Compiler, + pub target: TargetSelection, } impl Step for CraneliftCodegenBackend { type Output = Option<GeneratedTarball>; const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { // We only want to build the cranelift backend in `x dist` if the backend was enabled @@ -1437,6 +1450,7 @@ impl Step for CraneliftCodegenBackend { run.builder.config.host_target, run.target, ), + target: run.target, }); } @@ -1448,7 +1462,7 @@ impl Step for CraneliftCodegenBackend { return None; } - let target = self.build_compiler.host; + let target = self.target; let compilers = RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, target); if !target_supports_cranelift_backend(target) { @@ -1505,7 +1519,7 @@ pub struct Rustfmt { impl Step for Rustfmt { type Output = Option<GeneratedTarball>; const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let default = should_build_extended_tool(run.builder, "rustfmt"); @@ -1550,7 +1564,7 @@ pub struct Extended { impl Step for Extended { type Output = (); const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; @@ -1608,6 +1622,7 @@ impl Step for Extended { add_component!("analysis" => Analysis { compiler, target }); add_component!("rustc-codegen-cranelift" => CraneliftCodegenBackend { build_compiler: compiler, + target }); add_component!("llvm-bitcode-linker" => LlvmBitcodeLinker { build_compiler: compiler, @@ -2286,7 +2301,7 @@ pub struct LlvmTools { impl Step for LlvmTools { type Output = Option<GeneratedTarball>; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -2391,7 +2406,7 @@ pub struct LlvmBitcodeLinker { impl Step for LlvmBitcodeLinker { type Output = Option<GeneratedTarball>; const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let default = should_build_extended_tool(run.builder, "llvm-bitcode-linker"); @@ -2443,7 +2458,7 @@ pub struct RustDev { impl Step for RustDev { type Output = Option<GeneratedTarball>; const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.alias("rust-dev") @@ -2546,7 +2561,7 @@ pub struct Bootstrap { impl Step for Bootstrap { type Output = Option<GeneratedTarball>; const DEFAULT: bool = false; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.alias("bootstrap") @@ -2586,7 +2601,7 @@ pub struct BuildManifest { impl Step for BuildManifest { type Output = GeneratedTarball; const DEFAULT: bool = false; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.alias("build-manifest") @@ -2618,7 +2633,7 @@ pub struct ReproducibleArtifacts { impl Step for ReproducibleArtifacts { type Output = Option<GeneratedTarball>; const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.alias("reproducible-artifacts") diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 6f0d5203d11..f6b27d83120 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -830,7 +830,7 @@ impl Rustc { impl Step for Rustc { type Output = (); const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; @@ -975,7 +975,7 @@ macro_rules! tool_doc { impl Step for $tool { type Output = (); const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; @@ -1139,7 +1139,7 @@ pub struct ErrorIndex { impl Step for ErrorIndex { type Output = (); const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; @@ -1181,7 +1181,7 @@ pub struct UnstableBookGen { impl Step for UnstableBookGen { type Output = (); const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; @@ -1248,7 +1248,7 @@ impl RustcBook { impl Step for RustcBook { type Output = (); const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; diff --git a/src/bootstrap/src/core/build_steps/gcc.rs b/src/bootstrap/src/core/build_steps/gcc.rs index d4cbbe60921..2b36b0f2e27 100644 --- a/src/bootstrap/src/core/build_steps/gcc.rs +++ b/src/bootstrap/src/core/build_steps/gcc.rs @@ -12,6 +12,7 @@ use std::fs; use std::path::{Path, PathBuf}; use std::sync::OnceLock; +use crate::FileType; use crate::core::builder::{Builder, Cargo, Kind, RunConfig, ShouldRun, Step}; use crate::core::config::TargetSelection; use crate::utils::build_stamp::{BuildStamp, generate_smart_stamp_hash}; @@ -28,10 +29,25 @@ pub struct GccOutput { pub libgccjit: PathBuf, } +impl GccOutput { + /// Install the required libgccjit library file(s) to the specified `path`. + pub fn install_to(&self, builder: &Builder<'_>, directory: &Path) { + // At build time, cg_gcc has to link to libgccjit.so (the unversioned symbol). + // However, at runtime, it will by default look for libgccjit.so.0. + // So when we install the built libgccjit.so file to the target `directory`, we add it there + // with the `.0` suffix. + let mut target_filename = self.libgccjit.file_name().unwrap().to_str().unwrap().to_string(); + target_filename.push_str(".0"); + + let dst = directory.join(target_filename); + builder.copy_link(&self.libgccjit, &dst, FileType::NativeLibrary); + } +} + impl Step for Gcc { type Output = GccOutput; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/gcc").alias("gcc") @@ -61,7 +77,6 @@ impl Step for Gcc { } build_gcc(&metadata, builder, target); - create_lib_alias(builder, &libgccjit_path); t!(metadata.stamp.write()); @@ -69,15 +84,6 @@ impl Step for Gcc { } } -/// Creates a libgccjit.so.0 alias next to libgccjit.so if it does not -/// already exist -fn create_lib_alias(builder: &Builder<'_>, libgccjit: &PathBuf) { - let lib_alias = libgccjit.parent().unwrap().join("libgccjit.so.0"); - if !lib_alias.exists() { - t!(builder.symlink_file(libgccjit, lib_alias)); - } -} - pub struct Meta { stamp: BuildStamp, out_dir: PathBuf, @@ -124,7 +130,6 @@ fn try_download_gcc(builder: &Builder<'_>, target: TargetSelection) -> Option<Pa } let libgccjit = root.join("lib").join("libgccjit.so"); - create_lib_alias(builder, &libgccjit); Some(libgccjit) } PathFreshness::HasLocalModifications { .. } => { diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs index 6d09e41e646..4457258e9cd 100644 --- a/src/bootstrap/src/core/build_steps/install.rs +++ b/src/bootstrap/src/core/build_steps/install.rs @@ -163,7 +163,7 @@ macro_rules! install { $($name:ident, $condition_name: ident = $path_or_alias: literal, $default_cond:expr, - only_hosts: $only_hosts:expr, + IS_HOST: $IS_HOST:expr, $run_item:block $(, $c:ident)*;)+) => { $( #[derive(Debug, Clone, Hash, PartialEq, Eq)] @@ -183,7 +183,7 @@ macro_rules! install { impl Step for $name { type Output = (); const DEFAULT: bool = true; - const ONLY_HOSTS: bool = $only_hosts; + const IS_HOST: bool = $IS_HOST; $(const $c: bool = true;)* fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -206,11 +206,11 @@ macro_rules! install { } install!((self, builder, _config), - Docs, path = "src/doc", _config.docs, only_hosts: false, { + Docs, path = "src/doc", _config.docs, IS_HOST: false, { let tarball = builder.ensure(dist::Docs { host: self.target }).expect("missing docs"); install_sh(builder, "docs", self.compiler.stage, Some(self.target), &tarball); }; - Std, path = "library/std", true, only_hosts: false, { + Std, path = "library/std", true, IS_HOST: false, { // `expect` should be safe, only None when host != build, but this // only runs when host == build let tarball = builder.ensure(dist::Std { @@ -219,13 +219,13 @@ install!((self, builder, _config), }).expect("missing std"); install_sh(builder, "std", self.compiler.stage, Some(self.target), &tarball); }; - Cargo, alias = "cargo", Self::should_build(_config), only_hosts: true, { + Cargo, alias = "cargo", Self::should_build(_config), IS_HOST: true, { let tarball = builder .ensure(dist::Cargo { build_compiler: self.compiler, target: self.target }) .expect("missing cargo"); install_sh(builder, "cargo", self.compiler.stage, Some(self.target), &tarball); }; - RustAnalyzer, alias = "rust-analyzer", Self::should_build(_config), only_hosts: true, { + RustAnalyzer, alias = "rust-analyzer", Self::should_build(_config), IS_HOST: true, { if let Some(tarball) = builder.ensure(dist::RustAnalyzer { build_compiler: self.compiler, target: self.target }) { @@ -236,13 +236,13 @@ install!((self, builder, _config), ); } }; - Clippy, alias = "clippy", Self::should_build(_config), only_hosts: true, { + Clippy, alias = "clippy", Self::should_build(_config), IS_HOST: true, { let tarball = builder .ensure(dist::Clippy { build_compiler: self.compiler, target: self.target }) .expect("missing clippy"); install_sh(builder, "clippy", self.compiler.stage, Some(self.target), &tarball); }; - Miri, alias = "miri", Self::should_build(_config), only_hosts: true, { + Miri, alias = "miri", Self::should_build(_config), IS_HOST: true, { if let Some(tarball) = builder.ensure(dist::Miri { build_compiler: self.compiler, target: self.target }) { install_sh(builder, "miri", self.compiler.stage, Some(self.target), &tarball); } else { @@ -252,7 +252,7 @@ install!((self, builder, _config), ); } }; - LlvmTools, alias = "llvm-tools", _config.llvm_tools_enabled && _config.llvm_enabled(_config.host_target), only_hosts: true, { + LlvmTools, alias = "llvm-tools", _config.llvm_tools_enabled && _config.llvm_enabled(_config.host_target), IS_HOST: true, { if let Some(tarball) = builder.ensure(dist::LlvmTools { target: self.target }) { install_sh(builder, "llvm-tools", self.compiler.stage, Some(self.target), &tarball); } else { @@ -261,7 +261,7 @@ install!((self, builder, _config), ); } }; - Rustfmt, alias = "rustfmt", Self::should_build(_config), only_hosts: true, { + Rustfmt, alias = "rustfmt", Self::should_build(_config), IS_HOST: true, { if let Some(tarball) = builder.ensure(dist::Rustfmt { build_compiler: self.compiler, target: self.target @@ -273,15 +273,16 @@ install!((self, builder, _config), ); } }; - Rustc, path = "compiler/rustc", true, only_hosts: true, { + Rustc, path = "compiler/rustc", true, IS_HOST: true, { let tarball = builder.ensure(dist::Rustc { compiler: builder.compiler(builder.top_stage, self.target), }); install_sh(builder, "rustc", self.compiler.stage, Some(self.target), &tarball); }; - RustcCodegenCranelift, alias = "rustc-codegen-cranelift", Self::should_build(_config), only_hosts: true, { + RustcCodegenCranelift, alias = "rustc-codegen-cranelift", Self::should_build(_config), IS_HOST: true, { if let Some(tarball) = builder.ensure(dist::CraneliftCodegenBackend { build_compiler: self.compiler, + target: self.target }) { install_sh(builder, "rustc-codegen-cranelift", self.compiler.stage, Some(self.target), &tarball); } else { @@ -291,7 +292,7 @@ install!((self, builder, _config), ); } }; - LlvmBitcodeLinker, alias = "llvm-bitcode-linker", Self::should_build(_config), only_hosts: true, { + LlvmBitcodeLinker, alias = "llvm-bitcode-linker", Self::should_build(_config), IS_HOST: true, { if let Some(tarball) = builder.ensure(dist::LlvmBitcodeLinker { build_compiler: self.compiler, target: self.target }) { install_sh(builder, "llvm-bitcode-linker", self.compiler.stage, Some(self.target), &tarball); } else { @@ -310,7 +311,7 @@ pub struct Src { impl Step for Src { type Output = (); const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let config = &run.builder.config; diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 16941a32bb1..260108292e0 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -15,8 +15,6 @@ use std::sync::OnceLock; use std::{env, fs}; use build_helper::git::PathFreshness; -#[cfg(feature = "tracing")] -use tracing::instrument; use crate::core::builder::{Builder, RunConfig, ShouldRun, Step, StepMetadata}; use crate::core::config::{Config, TargetSelection}; @@ -255,7 +253,7 @@ pub struct Llvm { impl Step for Llvm { type Output = LlvmResult; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/llvm-project").path("src/llvm-project/llvm") @@ -266,15 +264,6 @@ impl Step for Llvm { } /// Compile LLVM for `target`. - #[cfg_attr( - feature = "tracing", - instrument( - level = "debug", - name = "Llvm::run", - skip_all, - fields(target = ?self.target), - ), - )] fn run(self, builder: &Builder<'_>) -> LlvmResult { let target = self.target; let target_native = if self.target.starts_with("riscv") { @@ -908,7 +897,7 @@ pub struct Enzyme { impl Step for Enzyme { type Output = PathBuf; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/tools/enzyme/enzyme") @@ -919,15 +908,6 @@ impl Step for Enzyme { } /// Compile Enzyme for `target`. - #[cfg_attr( - feature = "tracing", - instrument( - level = "debug", - name = "Enzyme::run", - skip_all, - fields(target = ?self.target), - ), - )] fn run(self, builder: &Builder<'_>) -> PathBuf { builder.require_submodule( "src/tools/enzyme", @@ -1013,7 +993,7 @@ pub struct Lld { impl Step for Lld { type Output = PathBuf; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/llvm-project/lld") diff --git a/src/bootstrap/src/core/build_steps/run.rs b/src/bootstrap/src/core/build_steps/run.rs index 962dd372849..7f1a7d00257 100644 --- a/src/bootstrap/src/core/build_steps/run.rs +++ b/src/bootstrap/src/core/build_steps/run.rs @@ -22,7 +22,7 @@ pub struct BuildManifest; impl Step for BuildManifest { type Output = (); - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/tools/build-manifest") @@ -61,7 +61,7 @@ pub struct BumpStage0; impl Step for BumpStage0 { type Output = (); - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/tools/bump-stage0") @@ -83,7 +83,7 @@ pub struct ReplaceVersionPlaceholder; impl Step for ReplaceVersionPlaceholder { type Output = (); - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/tools/replace-version-placeholder") @@ -107,7 +107,6 @@ pub struct Miri { impl Step for Miri { type Output = (); - const ONLY_HOSTS: bool = false; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/tools/miri") @@ -175,7 +174,7 @@ pub struct CollectLicenseMetadata; impl Step for CollectLicenseMetadata { type Output = PathBuf; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/tools/collect-license-metadata") @@ -206,7 +205,7 @@ pub struct GenerateCopyright; impl Step for GenerateCopyright { type Output = Vec<PathBuf>; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/tools/generate-copyright") @@ -270,7 +269,7 @@ pub struct GenerateWindowsSys; impl Step for GenerateWindowsSys { type Output = (); - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/tools/generate-windows-sys") @@ -332,7 +331,7 @@ pub struct UnicodeTableGenerator; impl Step for UnicodeTableGenerator { type Output = (); - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/tools/unicode-table-generator") @@ -354,7 +353,7 @@ pub struct FeaturesStatusDump; impl Step for FeaturesStatusDump { type Output = (); - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/tools/features-status-dump") @@ -416,7 +415,7 @@ impl Step for CoverageDump { type Output = (); const DEFAULT: bool = false; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/tools/coverage-dump") @@ -438,7 +437,7 @@ pub struct Rustfmt; impl Step for Rustfmt { type Output = (); - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/tools/rustfmt") diff --git a/src/bootstrap/src/core/build_steps/synthetic_targets.rs b/src/bootstrap/src/core/build_steps/synthetic_targets.rs index 477ff9553a4..21733c5d9e3 100644 --- a/src/bootstrap/src/core/build_steps/synthetic_targets.rs +++ b/src/bootstrap/src/core/build_steps/synthetic_targets.rs @@ -21,7 +21,6 @@ pub(crate) struct MirOptPanicAbortSyntheticTarget { impl Step for MirOptPanicAbortSyntheticTarget { type Output = TargetSelection; const DEFAULT: bool = true; - const ONLY_HOSTS: bool = false; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.never() diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index f1be0af3183..4006bed4ac5 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -10,8 +10,6 @@ use std::path::{Path, PathBuf}; use std::{env, fs, iter}; use build_helper::exit; -#[cfg(feature = "tracing")] -use tracing::instrument; use crate::core::build_steps::compile::{Std, run_cargo}; use crate::core::build_steps::doc::DocumentationFormat; @@ -51,7 +49,7 @@ pub struct CrateBootstrap { impl Step for CrateBootstrap { type Output = (); - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -109,7 +107,7 @@ pub struct Linkcheck { impl Step for Linkcheck { type Output = (); - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; const DEFAULT: bool = true; /// Runs the `linkchecker` tool as compiled in `stage` by the `host` compiler. @@ -189,7 +187,7 @@ pub struct HtmlCheck { impl Step for HtmlCheck { type Output = (); const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; @@ -236,7 +234,7 @@ pub struct Cargotest { impl Step for Cargotest { type Output = (); - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/tools/cargotest") @@ -313,7 +311,7 @@ impl Cargo { impl Step for Cargo { type Output = (); - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path(Self::CRATE_PATH) @@ -410,7 +408,7 @@ pub struct RustAnalyzer { impl Step for RustAnalyzer { type Output = (); - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -469,7 +467,7 @@ pub struct Rustfmt { impl Step for Rustfmt { type Output = (); - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/tools/rustfmt") @@ -561,7 +559,6 @@ impl Miri { impl Step for Miri { type Output = (); - const ONLY_HOSTS: bool = false; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/tools/miri") @@ -681,7 +678,6 @@ pub struct CargoMiri { impl Step for CargoMiri { type Output = (); - const ONLY_HOSTS: bool = false; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/tools/miri/cargo-miri") @@ -760,10 +756,6 @@ impl Step for CompiletestTest { } /// Runs `cargo test` for compiletest. - #[cfg_attr( - feature = "tracing", - instrument(level = "debug", name = "CompiletestTest::run", skip_all) - )] fn run(self, builder: &Builder<'_>) { let host = self.host; @@ -811,7 +803,7 @@ pub struct Clippy { impl Step for Clippy { type Output = (); - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; const DEFAULT: bool = false; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -911,7 +903,7 @@ pub struct RustdocTheme { impl Step for RustdocTheme { type Output = (); const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/tools/rustdoc-themes") @@ -948,7 +940,7 @@ pub struct RustdocJSStd { impl Step for RustdocJSStd { type Output = (); const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let default = run.builder.config.nodejs.is_some(); @@ -1008,7 +1000,7 @@ pub struct RustdocJSNotStd { impl Step for RustdocJSNotStd { type Output = (); const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let default = run.builder.config.nodejs.is_some(); @@ -1063,7 +1055,7 @@ pub struct RustdocGUI { impl Step for RustdocGUI { type Output = (); const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; @@ -1156,7 +1148,7 @@ pub struct Tidy; impl Step for Tidy { type Output = (); const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; /// Runs the `tidy` tool. /// @@ -1274,7 +1266,7 @@ macro_rules! test { mode: $mode:expr, suite: $suite:expr, default: $default:expr - $( , only_hosts: $only_hosts:expr )? // default: false + $( , IS_HOST: $IS_HOST:expr )? // default: false $( , compare_mode: $compare_mode:expr )? // default: None $( , )? // optional trailing comma } @@ -1289,10 +1281,10 @@ macro_rules! test { impl Step for $name { type Output = (); const DEFAULT: bool = $default; - const ONLY_HOSTS: bool = (const { + const IS_HOST: bool = (const { #[allow(unused_assignments, unused_mut)] let mut value = false; - $( value = $only_hosts; )? + $( value = $IS_HOST; )? value }); @@ -1340,7 +1332,7 @@ pub struct CrateRunMakeSupport { impl Step for CrateRunMakeSupport { type Output = (); - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/tools/run-make-support") @@ -1377,7 +1369,7 @@ pub struct CrateBuildHelper { impl Step for CrateBuildHelper { type Output = (); - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/build_helper") @@ -1445,7 +1437,7 @@ test!(UiFullDeps { mode: "ui", suite: "ui-fulldeps", default: true, - only_hosts: true, + IS_HOST: true, }); test!(Rustdoc { @@ -1453,14 +1445,14 @@ test!(Rustdoc { mode: "rustdoc", suite: "rustdoc", default: true, - only_hosts: true, + IS_HOST: true, }); test!(RustdocUi { path: "tests/rustdoc-ui", mode: "ui", suite: "rustdoc-ui", default: true, - only_hosts: true, + IS_HOST: true, }); test!(RustdocJson { @@ -1468,7 +1460,7 @@ test!(RustdocJson { mode: "rustdoc-json", suite: "rustdoc-json", default: true, - only_hosts: true, + IS_HOST: true, }); test!(Pretty { @@ -1476,7 +1468,7 @@ test!(Pretty { mode: "pretty", suite: "pretty", default: true, - only_hosts: true, + IS_HOST: true, }); test!(RunMake { path: "tests/run-make", mode: "run-make", suite: "run-make", default: true }); @@ -1507,7 +1499,7 @@ impl Step for Coverage { type Output = (); const DEFAULT: bool = true; /// Compiletest will automatically skip the "coverage-run" tests if necessary. - const ONLY_HOSTS: bool = false; + const IS_HOST: bool = false; fn should_run(mut run: ShouldRun<'_>) -> ShouldRun<'_> { // Support various invocation styles, including: @@ -1586,7 +1578,7 @@ test!(CoverageRunRustdoc { mode: "coverage-run", suite: "coverage-run-rustdoc", default: true, - only_hosts: true, + IS_HOST: true, }); // For the mir-opt suite we do not use macros, as we need custom behavior when blessing. @@ -1599,7 +1591,6 @@ pub struct MirOpt { impl Step for MirOpt { type Output = (); const DEFAULT: bool = true; - const ONLY_HOSTS: bool = false; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.suite_path("tests/mir-opt") @@ -2276,7 +2267,7 @@ struct BookTest { impl Step for BookTest { type Output = (); - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.never() @@ -2442,7 +2433,7 @@ macro_rules! test_book { impl Step for $name { type Output = (); const DEFAULT: bool = $default; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path($path) @@ -2502,7 +2493,7 @@ pub struct ErrorIndex { impl Step for ErrorIndex { type Output = (); const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { // Also add `error-index` here since that is what appears in the error message @@ -2598,7 +2589,7 @@ pub struct CrateLibrustc { impl Step for CrateLibrustc { type Output = (); const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.crate_or_deps("rustc-main").path("compiler") @@ -2883,7 +2874,7 @@ pub struct CrateRustdoc { impl Step for CrateRustdoc { type Output = (); const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.paths(&["src/librustdoc", "src/tools/rustdoc"]) @@ -2975,7 +2966,7 @@ pub struct CrateRustdocJsonTypes { impl Step for CrateRustdocJsonTypes { type Output = (); const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/rustdoc-json-types") @@ -3164,7 +3155,7 @@ pub struct Bootstrap; impl Step for Bootstrap { type Output = (); const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; /// Tests the build system itself. fn run(self, builder: &Builder<'_>) { @@ -3234,7 +3225,7 @@ pub struct TierCheck { impl Step for TierCheck { type Output = (); const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/tools/tier-check") @@ -3288,7 +3279,7 @@ pub struct LintDocs { impl Step for LintDocs { type Output = (); const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/tools/lint-docs") @@ -3314,7 +3305,7 @@ pub struct RustInstaller; impl Step for RustInstaller { type Output = (); - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; const DEFAULT: bool = true; /// Ensure the version placeholder replacement tool builds @@ -3434,7 +3425,7 @@ pub struct CodegenCranelift { impl Step for CodegenCranelift { type Output = (); const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.paths(&["compiler/rustc_codegen_cranelift"]) @@ -3562,7 +3553,7 @@ pub struct CodegenGCC { impl Step for CodegenGCC { type Output = (); const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.paths(&["compiler/rustc_codegen_gcc"]) @@ -3695,7 +3686,7 @@ pub struct TestFloatParse { impl Step for TestFloatParse { type Output = (); - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -3761,7 +3752,7 @@ pub struct CollectLicenseMetadata; impl Step for CollectLicenseMetadata { type Output = PathBuf; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/tools/collect-license-metadata") diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 793e6b629c9..b62c9a906b7 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -13,9 +13,6 @@ use std::ffi::OsStr; use std::path::PathBuf; use std::{env, fs}; -#[cfg(feature = "tracing")] -use tracing::instrument; - use crate::core::build_steps::compile::is_lto_stage; use crate::core::build_steps::toolstate::ToolState; use crate::core::build_steps::{compile, llvm}; @@ -229,6 +226,14 @@ pub fn prepare_tool_cargo( // own copy cargo.env("LZMA_API_STATIC", "1"); + // Build jemalloc on AArch64 with support for page sizes up to 64K + // See: https://github.com/rust-lang/rust/pull/135081 + // Note that `miri` always uses jemalloc. As such, there is no checking of the jemalloc build flag. + // See also the "JEMALLOC_SYS_WITH_LG_PAGE" setting in the compile build step. + if target.starts_with("aarch64") && env::var_os("JEMALLOC_SYS_WITH_LG_PAGE").is_none() { + cargo.env("JEMALLOC_SYS_WITH_LG_PAGE", "16"); + } + // CFG_RELEASE is needed by rustfmt (and possibly other tools) which // import rustc-ap-rustc_attr which requires this to be set for the // `#[cfg(version(...))]` attribute. @@ -415,14 +420,6 @@ macro_rules! bootstrap_tool { }); } - #[cfg_attr( - feature = "tracing", - instrument( - level = "debug", - name = $tool_name, - skip_all, - ), - )] fn run(self, builder: &Builder<'_>) -> ToolBuildResult { $( for submodule in $submodules { @@ -687,7 +684,7 @@ impl Step for Rustdoc { type Output = PathBuf; const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/tools/rustdoc").path("src/librustdoc") @@ -809,7 +806,7 @@ impl Cargo { impl Step for Cargo { type Output = ToolBuildResult; const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; @@ -885,7 +882,7 @@ impl LldWrapper { impl Step for LldWrapper { type Output = BuiltLldWrapper; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/tools/lld-wrapper") @@ -901,15 +898,6 @@ impl Step for LldWrapper { }); } - #[cfg_attr( - feature = "tracing", - instrument( - level = "debug", - name = "LldWrapper::run", - skip_all, - fields(build_compiler = ?self.build_compiler), - ), - )] fn run(self, builder: &Builder<'_>) -> Self::Output { let lld_dir = builder.ensure(llvm::Lld { target: self.target }); let tool = builder.ensure(ToolBuild { @@ -986,7 +974,7 @@ impl WasmComponentLd { impl Step for WasmComponentLd { type Output = ToolBuildResult; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/tools/wasm-component-ld") @@ -1002,15 +990,6 @@ impl Step for WasmComponentLd { }); } - #[cfg_attr( - feature = "tracing", - instrument( - level = "debug", - name = "WasmComponentLd::run", - skip_all, - fields(build_compiler = ?self.build_compiler), - ), - )] fn run(self, builder: &Builder<'_>) -> ToolBuildResult { builder.ensure(ToolBuild { build_compiler: self.build_compiler, @@ -1049,7 +1028,7 @@ impl RustAnalyzer { impl Step for RustAnalyzer { type Output = ToolBuildResult; const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; @@ -1102,7 +1081,7 @@ impl Step for RustAnalyzerProcMacroSrv { type Output = ToolBuildResult; const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; @@ -1192,7 +1171,7 @@ impl LlvmBitcodeLinker { impl Step for LlvmBitcodeLinker { type Output = ToolBuildResult; const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; @@ -1207,10 +1186,6 @@ impl Step for LlvmBitcodeLinker { }); } - #[cfg_attr( - feature = "tracing", - instrument(level = "debug", name = "LlvmBitcodeLinker::run", skip_all) - )] fn run(self, builder: &Builder<'_>) -> ToolBuildResult { builder.ensure(ToolBuild { build_compiler: self.build_compiler, @@ -1246,7 +1221,7 @@ pub enum LibcxxVersion { impl Step for LibcxxVersionTool { type Output = LibcxxVersion; const DEFAULT: bool = false; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.never() @@ -1407,7 +1382,7 @@ macro_rules! tool_rustc_extended { impl Step for $name { type Output = ToolBuildResult; const DEFAULT: bool = true; // Overridden by `should_run_tool_build_step` - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { should_run_extended_rustc_tool( @@ -1575,7 +1550,7 @@ impl TestFloatParse { impl Step for TestFloatParse { type Output = ToolBuildResult; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; const DEFAULT: bool = false; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { diff --git a/src/bootstrap/src/core/build_steps/vendor.rs b/src/bootstrap/src/core/build_steps/vendor.rs index 0caeb328811..7b860ceb943 100644 --- a/src/bootstrap/src/core/build_steps/vendor.rs +++ b/src/bootstrap/src/core/build_steps/vendor.rs @@ -53,7 +53,7 @@ pub(crate) struct Vendor { impl Step for Vendor { type Output = VendorOutput; const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; + const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.alias("placeholder").default_condition(true) diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index 757b9277ec6..3ce21eb151c 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -499,6 +499,10 @@ impl Builder<'_> { build_stamp::clear_if_dirty(self, &out_dir, &backend); } + if self.config.cmd.timings() { + cargo.arg("--timings"); + } + if cmd_kind == Kind::Doc { let my_out = match mode { // This is the intended out directory for compiler documentation. diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index de4b941ac90..6226c81a3fd 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -100,8 +100,13 @@ pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash { /// by `Step::should_run`. const DEFAULT: bool = false; - /// If true, then this rule should be skipped if --target was specified, but --host was not - const ONLY_HOSTS: bool = false; + /// If this value is true, then the values of `run.target` passed to the `make_run` function of + /// this Step will be determined based on the `--host` flag. + /// If this value is false, then they will be determined based on the `--target` flag. + /// + /// A corollary of the above is that if this is set to true, then the step will be skipped if + /// `--target` was specified, but `--host` was explicitly set to '' (empty string). + const IS_HOST: bool = false; /// Primary function to implement `Step` logic. /// @@ -160,6 +165,10 @@ impl StepMetadata { Self::new(name, target, Kind::Check) } + pub fn clippy(name: &str, target: TargetSelection) -> Self { + Self::new(name, target, Kind::Clippy) + } + pub fn doc(name: &str, target: TargetSelection) -> Self { Self::new(name, target, Kind::Doc) } @@ -294,7 +303,7 @@ pub fn crate_description(crates: &[impl AsRef<str>]) -> String { struct StepDescription { default: bool, - only_hosts: bool, + is_host: bool, should_run: fn(ShouldRun<'_>) -> ShouldRun<'_>, make_run: fn(RunConfig<'_>), name: &'static str, @@ -496,7 +505,7 @@ impl StepDescription { fn from<S: Step>(kind: Kind) -> StepDescription { StepDescription { default: S::DEFAULT, - only_hosts: S::ONLY_HOSTS, + is_host: S::IS_HOST, should_run: S::should_run, make_run: S::make_run, name: std::any::type_name::<S>(), @@ -512,7 +521,7 @@ impl StepDescription { } // Determine the targets participating in this rule. - let targets = if self.only_hosts { &builder.hosts } else { &builder.targets }; + let targets = if self.is_host { &builder.hosts } else { &builder.targets }; for target in targets { let run = RunConfig { builder, paths: pathsets.clone(), target: *target }; @@ -947,6 +956,9 @@ impl Step for Libdir { } } +#[cfg(feature = "tracing")] +pub const STEP_SPAN_TARGET: &str = "STEP"; + impl<'a> Builder<'a> { fn get_step_descriptions(kind: Kind) -> Vec<StepDescription> { macro_rules! describe { @@ -1267,7 +1279,7 @@ impl<'a> Builder<'a> { pub fn new(build: &Build) -> Builder<'_> { let paths = &build.config.paths; let (kind, paths) = match build.config.cmd { - Subcommand::Build => (Kind::Build, &paths[..]), + Subcommand::Build { .. } => (Kind::Build, &paths[..]), Subcommand::Check { .. } => (Kind::Check, &paths[..]), Subcommand::Clippy { .. } => (Kind::Clippy, &paths[..]), Subcommand::Fix => (Kind::Fix, &paths[..]), @@ -1552,35 +1564,6 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s self.ensure(tool::Rustdoc { target_compiler }) } - pub fn cargo_clippy_cmd(&self, run_compiler: Compiler) -> BootstrapCommand { - if run_compiler.stage == 0 { - let cargo_clippy = self - .config - .initial_cargo_clippy - .clone() - .unwrap_or_else(|| self.build.config.download_clippy()); - - let mut cmd = command(cargo_clippy); - cmd.env("CARGO", &self.initial_cargo); - return cmd; - } - - // FIXME: double check that `run_compiler`'s stage is what we want to use - let compilers = - RustcPrivateCompilers::new(self, run_compiler.stage, self.build.host_target); - assert_eq!(run_compiler, compilers.target_compiler()); - - let _ = self.ensure(tool::Clippy::from_compilers(compilers)); - let cargo_clippy = self.ensure(tool::CargoClippy::from_compilers(compilers)); - let mut dylib_path = helpers::dylib_path(); - dylib_path.insert(0, self.sysroot(run_compiler).join("lib")); - - let mut cmd = command(cargo_clippy.tool_path); - cmd.env(helpers::dylib_path_var(), env::join_paths(&dylib_path).unwrap()); - cmd.env("CARGO", &self.initial_cargo); - cmd - } - pub fn cargo_miri_cmd(&self, run_compiler: Compiler) -> BootstrapCommand { assert!(run_compiler.stage > 0, "miri can not be invoked at stage 0"); @@ -1607,6 +1590,37 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s cmd } + /// Create a Cargo command for running Clippy. + /// The used Clippy is (or in the case of stage 0, already was) built using `build_compiler`. + pub fn cargo_clippy_cmd(&self, build_compiler: Compiler) -> BootstrapCommand { + if build_compiler.stage == 0 { + let cargo_clippy = self + .config + .initial_cargo_clippy + .clone() + .unwrap_or_else(|| self.build.config.download_clippy()); + + let mut cmd = command(cargo_clippy); + cmd.env("CARGO", &self.initial_cargo); + return cmd; + } + + // If we're linting something with build_compiler stage N, we want to build Clippy stage N + // and use that to lint it. That is why we use the `build_compiler` as the target compiler + // for RustcPrivateCompilers. We will use build compiler stage N-1 to build Clippy stage N. + let compilers = RustcPrivateCompilers::from_target_compiler(self, build_compiler); + + let _ = self.ensure(tool::Clippy::from_compilers(compilers)); + let cargo_clippy = self.ensure(tool::CargoClippy::from_compilers(compilers)); + let mut dylib_path = helpers::dylib_path(); + dylib_path.insert(0, self.sysroot(build_compiler).join("lib")); + + let mut cmd = command(cargo_clippy.tool_path); + cmd.env(helpers::dylib_path_var(), env::join_paths(&dylib_path).unwrap()); + cmd.env("CARGO", &self.initial_cargo); + cmd + } + pub fn rustdoc_cmd(&self, compiler: Compiler) -> BootstrapCommand { let mut cmd = command(self.bootstrap_out.join("rustdoc")); cmd.env("RUSTC_STAGE", compiler.stage.to_string()) @@ -1674,8 +1688,6 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s panic!("{}", out); } if let Some(out) = self.cache.get(&step) { - self.verbose_than(1, || println!("{}c {:?}", " ".repeat(stack.len()), step)); - #[cfg(feature = "tracing")] { if let Some(parent) = stack.last() { @@ -1685,7 +1697,6 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s } return out; } - self.verbose_than(1, || println!("{}> {:?}", " ".repeat(stack.len()), step)); #[cfg(feature = "tracing")] { @@ -1700,10 +1711,29 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s #[cfg(feature = "build-metrics")] self.metrics.enter_step(&step, self); + if self.config.print_step_timings && !self.config.dry_run() { + println!("[TIMING:start] {}", pretty_print_step(&step)); + } + let (out, dur) = { let start = Instant::now(); let zero = Duration::new(0, 0); let parent = self.time_spent_on_dependencies.replace(zero); + + #[cfg(feature = "tracing")] + let _span = { + // Keep the target and field names synchronized with `setup_tracing`. + let span = tracing::info_span!( + target: STEP_SPAN_TARGET, + // We cannot use a dynamic name here, so instead we record the actual step name + // in the step_name field. + "step", + step_name = pretty_step_name::<S>(), + args = step_debug_args(&step) + ); + span.entered() + }; + let out = step.clone().run(self); let dur = start.elapsed(); let deps = self.time_spent_on_dependencies.replace(parent + dur); @@ -1711,13 +1741,9 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s }; if self.config.print_step_timings && !self.config.dry_run() { - let step_string = format!("{step:?}"); - let brace_index = step_string.find('{').unwrap_or(0); - let type_string = type_name::<S>(); println!( - "[TIMING] {} {} -- {}.{:03}", - &type_string.strip_prefix("bootstrap::").unwrap_or(type_string), - &step_string[brace_index..], + "[TIMING:end] {} -- {}.{:03}", + pretty_print_step(&step), dur.as_secs(), dur.subsec_millis() ); @@ -1731,7 +1757,6 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s let cur_step = stack.pop().expect("step stack empty"); assert_eq!(cur_step.downcast_ref(), Some(&step)); } - self.verbose_than(1, || println!("{}< {:?}", " ".repeat(self.stack.borrow().len()), step)); self.cache.put(step, out.clone()); out } @@ -1804,6 +1829,25 @@ You have to build a stage1 compiler for `{}` first, and then use it to build a s } } +/// Return qualified step name, e.g. `compile::Rustc`. +pub fn pretty_step_name<S: Step>() -> String { + // Normalize step type path to only keep the module and the type name + let path = type_name::<S>().rsplit("::").take(2).collect::<Vec<_>>(); + path.into_iter().rev().collect::<Vec<_>>().join("::") +} + +/// Renders `step` using its `Debug` implementation and extract the field arguments out of it. +fn step_debug_args<S: Step>(step: &S) -> String { + let step_dbg_repr = format!("{step:?}"); + let brace_start = step_dbg_repr.find('{').unwrap_or(0); + let brace_end = step_dbg_repr.rfind('}').unwrap_or(step_dbg_repr.len()); + step_dbg_repr[brace_start + 1..brace_end - 1].trim().to_string() +} + +fn pretty_print_step<S: Step>(step: &S) -> String { + format!("{} {{ {} }}", pretty_step_name::<S>(), step_debug_args(step)) +} + impl<'a> AsRef<ExecutionContext> for Builder<'a> { fn as_ref(&self) -> &ExecutionContext { self.exec_ctx() diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 32d191c4265..9ba57542549 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -1515,6 +1515,7 @@ mod snapshot { ctx.config("check") .path("compiler") .render_steps(), @r" + [check] rustc 0 <host> -> rustc 1 <host> (73 crates) [check] rustc 0 <host> -> rustc 1 <host> [check] rustc 0 <host> -> rustc_codegen_cranelift 1 <host> [check] rustc 0 <host> -> rustc_codegen_gcc 1 <host> @@ -1527,9 +1528,7 @@ mod snapshot { insta::assert_snapshot!( ctx.config("check") .path("rustc") - .render_steps(), @r" - [check] rustc 0 <host> -> rustc 1 <host> - "); + .render_steps(), @"[check] rustc 0 <host> -> rustc 1 <host> (1 crates)"); } #[test] @@ -1547,6 +1546,7 @@ mod snapshot { .path("compiler") .stage(1) .render_steps(), @r" + [check] rustc 0 <host> -> rustc 1 <host> (73 crates) [check] rustc 0 <host> -> rustc 1 <host> [check] rustc 0 <host> -> rustc_codegen_cranelift 1 <host> [check] rustc 0 <host> -> rustc_codegen_gcc 1 <host> @@ -1564,6 +1564,7 @@ mod snapshot { [build] llvm <host> [build] rustc 0 <host> -> rustc 1 <host> [build] rustc 1 <host> -> std 1 <host> + [check] rustc 1 <host> -> rustc 2 <host> (73 crates) [check] rustc 1 <host> -> rustc 2 <host> [check] rustc 1 <host> -> rustc_codegen_cranelift 2 <host> [check] rustc 1 <host> -> rustc_codegen_gcc 2 <host> @@ -1582,6 +1583,7 @@ mod snapshot { [build] rustc 0 <host> -> rustc 1 <host> [build] rustc 1 <host> -> std 1 <host> [build] rustc 1 <host> -> std 1 <target1> + [check] rustc 1 <host> -> rustc 2 <target1> (73 crates) [check] rustc 1 <host> -> rustc 2 <target1> [check] rustc 1 <host> -> Rustdoc 2 <target1> [check] rustc 1 <host> -> rustc_codegen_cranelift 2 <target1> @@ -1678,6 +1680,7 @@ mod snapshot { .paths(&["library", "compiler"]) .args(&args) .render_steps(), @r" + [check] rustc 0 <host> -> rustc 1 <host> (73 crates) [check] rustc 0 <host> -> rustc 1 <host> [check] rustc 0 <host> -> rustc_codegen_cranelift 1 <host> [check] rustc 0 <host> -> rustc_codegen_gcc 1 <host> @@ -2065,6 +2068,130 @@ mod snapshot { [doc] rustc 1 <host> -> reference (book) 2 <host> "); } + + #[test] + fn clippy_ci() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("clippy") + .path("ci") + .stage(2) + .render_steps(), @r" + [build] llvm <host> + [build] rustc 0 <host> -> rustc 1 <host> + [build] rustc 1 <host> -> std 1 <host> + [build] rustc 0 <host> -> clippy-driver 1 <host> + [build] rustc 0 <host> -> cargo-clippy 1 <host> + [clippy] rustc 1 <host> -> bootstrap 2 <host> + [clippy] rustc 1 <host> -> std 1 <host> + [clippy] rustc 1 <host> -> rustc 2 <host> + [check] rustc 1 <host> -> rustc 2 <host> + [clippy] rustc 1 <host> -> rustc_codegen_gcc 2 <host> + "); + } + + #[test] + fn clippy_compiler_stage1() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("clippy") + .path("compiler") + .render_steps(), @r" + [build] llvm <host> + [clippy] rustc 0 <host> -> rustc 1 <host> + "); + } + + #[test] + fn clippy_compiler_stage2() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("clippy") + .path("compiler") + .stage(2) + .render_steps(), @r" + [build] llvm <host> + [build] rustc 0 <host> -> rustc 1 <host> + [build] rustc 1 <host> -> std 1 <host> + [build] rustc 0 <host> -> clippy-driver 1 <host> + [build] rustc 0 <host> -> cargo-clippy 1 <host> + [clippy] rustc 1 <host> -> rustc 2 <host> + "); + } + + #[test] + fn clippy_std_stage1() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("clippy") + .path("std") + .render_steps(), @r" + [build] llvm <host> + [build] rustc 0 <host> -> rustc 1 <host> + [build] rustc 0 <host> -> clippy-driver 1 <host> + [build] rustc 0 <host> -> cargo-clippy 1 <host> + [clippy] rustc 1 <host> -> std 1 <host> + "); + } + + #[test] + fn clippy_std_stage2() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("clippy") + .path("std") + .stage(2) + .render_steps(), @r" + [build] llvm <host> + [build] rustc 0 <host> -> rustc 1 <host> + [build] rustc 1 <host> -> std 1 <host> + [build] rustc 1 <host> -> rustc 2 <host> + [build] rustc 1 <host> -> clippy-driver 2 <host> + [build] rustc 1 <host> -> cargo-clippy 2 <host> + [clippy] rustc 2 <host> -> std 2 <host> + "); + } + + #[test] + fn clippy_miri_stage1() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("clippy") + .path("miri") + .stage(1) + .render_steps(), @r" + [build] llvm <host> + [check] rustc 0 <host> -> rustc 1 <host> + [clippy] rustc 0 <host> -> miri 1 <host> + "); + } + + #[test] + fn clippy_miri_stage2() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("clippy") + .path("miri") + .stage(2) + .render_steps(), @r" + [build] llvm <host> + [build] rustc 0 <host> -> rustc 1 <host> + [build] rustc 1 <host> -> std 1 <host> + [check] rustc 1 <host> -> rustc 2 <host> + [build] rustc 0 <host> -> clippy-driver 1 <host> + [build] rustc 0 <host> -> cargo-clippy 1 <host> + [clippy] rustc 1 <host> -> miri 2 <host> + "); + } + + #[test] + fn clippy_bootstrap() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("clippy") + .path("bootstrap") + .render_steps(), @"[clippy] rustc 0 <host> -> bootstrap 1 <host>"); + } } struct ExecutedSteps { diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index a656927b1f6..5eea5436023 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1342,7 +1342,7 @@ impl Config { Subcommand::Doc { .. } => { flags_stage.or(build_doc_stage).unwrap_or(if download_rustc { 2 } else { 1 }) } - Subcommand::Build => { + Subcommand::Build { .. } => { flags_stage.or(build_build_stage).unwrap_or(if download_rustc { 2 } else { 1 }) } Subcommand::Test { .. } | Subcommand::Miri { .. } => { @@ -1363,7 +1363,7 @@ impl Config { // Now check that the selected stage makes sense, and if not, print a warning and end match (config.stage, &config.cmd) { - (0, Subcommand::Build) => { + (0, Subcommand::Build { .. }) => { eprintln!("ERROR: cannot build anything on stage 0. Use at least stage 1."); exit!(1); } @@ -1375,6 +1375,10 @@ impl Config { eprintln!("ERROR: cannot document anything on stage 0. Use at least stage 1."); exit!(1); } + (0, Subcommand::Clippy { .. }) => { + eprintln!("ERROR: cannot run clippy on stage 0. Use at least stage 1."); + exit!(1); + } _ => {} } @@ -1392,7 +1396,7 @@ impl Config { Subcommand::Test { .. } | Subcommand::Miri { .. } | Subcommand::Doc { .. } - | Subcommand::Build + | Subcommand::Build { .. } | Subcommand::Bench { .. } | Subcommand::Dist | Subcommand::Install => { diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs index 31a427f9ffa..17bfb388280 100644 --- a/src/bootstrap/src/core/config/flags.rs +++ b/src/bootstrap/src/core/config/flags.rs @@ -241,7 +241,7 @@ fn normalize_args(args: &[String]) -> Vec<String> { it.collect() } -#[derive(Debug, Clone, Default, clap::Subcommand)] +#[derive(Debug, Clone, clap::Subcommand)] pub enum Subcommand { #[command(aliases = ["b"], long_about = "\n Arguments: @@ -256,8 +256,11 @@ pub enum Subcommand { ./x.py build --stage 0 ./x.py build ")] /// Compile either the compiler or libraries - #[default] - Build, + Build { + #[arg(long)] + /// Pass `--timings` to Cargo to get crate build timings + timings: bool, + }, #[command(aliases = ["c"], long_about = "\n Arguments: This subcommand accepts a number of paths to directories to the crates @@ -269,6 +272,9 @@ pub enum Subcommand { #[arg(long)] /// Check all targets all_targets: bool, + #[arg(long)] + /// Pass `--timings` to Cargo to get crate build timings + timings: bool, }, /// Run Clippy (uses rustup/cargo-installed clippy binary) #[command(long_about = "\n @@ -494,11 +500,17 @@ Arguments: Perf(PerfArgs), } +impl Default for Subcommand { + fn default() -> Self { + Subcommand::Build { timings: false } + } +} + impl Subcommand { pub fn kind(&self) -> Kind { match self { Subcommand::Bench { .. } => Kind::Bench, - Subcommand::Build => Kind::Build, + Subcommand::Build { .. } => Kind::Build, Subcommand::Check { .. } => Kind::Check, Subcommand::Clippy { .. } => Kind::Clippy, Subcommand::Doc { .. } => Kind::Doc, @@ -626,6 +638,13 @@ impl Subcommand { } } + pub fn timings(&self) -> bool { + match *self { + Subcommand::Build { timings, .. } | Subcommand::Check { timings, .. } => timings, + _ => false, + } + } + pub fn vendor_versioned_dirs(&self) -> bool { match *self { Subcommand::Vendor { versioned_dirs, .. } => versioned_dirs, diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 3080e641b5b..bd02131b7fe 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -35,6 +35,7 @@ pub struct Finder { const STAGE0_MISSING_TARGETS: &[&str] = &[ "armv7a-vex-v5", // just a dummy comment so the list doesn't get onelined + "aarch64_be-unknown-none-softfloat", ]; /// Minimum version threshold for libstdc++ required when using prebuilt LLVM diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 0b65ebc0671..706a3cbb210 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -37,14 +37,14 @@ use crate::core::builder; use crate::core::builder::Kind; use crate::core::config::{DryRun, LldMode, LlvmLibunwind, TargetSelection, flags}; use crate::utils::exec::{BootstrapCommand, command}; -use crate::utils::helpers::{ - self, dir_is_empty, exe, libdir, set_file_times, split_debuginfo, symlink_dir, -}; +use crate::utils::helpers::{self, dir_is_empty, exe, libdir, set_file_times, split_debuginfo}; mod core; mod utils; pub use core::builder::PathSet; +#[cfg(feature = "tracing")] +pub use core::builder::STEP_SPAN_TARGET; pub use core::config::flags::{Flags, Subcommand}; pub use core::config::{ChangeId, Config}; @@ -53,7 +53,9 @@ use tracing::{instrument, span}; pub use utils::change_tracker::{ CONFIG_CHANGE_HISTORY, find_recent_config_change_ids, human_readable_changes, }; -pub use utils::helpers::PanicTracker; +pub use utils::helpers::{PanicTracker, symlink_dir}; +#[cfg(feature = "tracing")] +pub use utils::tracing::setup_tracing; use crate::core::build_steps::vendor::VENDOR_DIR; @@ -2005,13 +2007,13 @@ to download LLVM rather than building it. &self.config.exec_ctx } - pub fn report_summary(&self, start_time: Instant) { - self.config.exec_ctx.profiler().report_summary(start_time); + pub fn report_summary(&self, path: &Path, start_time: Instant) { + self.config.exec_ctx.profiler().report_summary(path, start_time); } #[cfg(feature = "tracing")] - pub fn report_step_graph(self) { - self.step_graph.into_inner().store_to_dot_files(); + pub fn report_step_graph(self, directory: &Path) { + self.step_graph.into_inner().store_to_dot_files(directory); } } diff --git a/src/bootstrap/src/utils/build_stamp.rs b/src/bootstrap/src/utils/build_stamp.rs index bd4eb790ae5..6c79385190e 100644 --- a/src/bootstrap/src/utils/build_stamp.rs +++ b/src/bootstrap/src/utils/build_stamp.rs @@ -146,13 +146,13 @@ pub fn libstd_stamp( } /// Cargo's output path for librustc in a given stage, compiled by a particular -/// compiler for the specified target. +/// `build_compiler` for the specified target. pub fn librustc_stamp( builder: &Builder<'_>, - compiler: Compiler, + build_compiler: Compiler, target: TargetSelection, ) -> BuildStamp { - BuildStamp::new(&builder.cargo_out(compiler, Mode::Rustc, target)).with_prefix("librustc") + BuildStamp::new(&builder.cargo_out(build_compiler, Mode::Rustc, target)).with_prefix("librustc") } /// Computes a hash representing the state of a repository/submodule and additional input. diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index cd7fba39a84..b454a8ddefb 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -501,4 +501,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Warning, summary: "The names of stageN directories in the build directory have been consolidated with the new (post-stage-0-redesign) staging scheme. Some tools and binaries might be located in a different build directory than before.", }, + ChangeInfo { + change_id: 145131, + severity: ChangeSeverity::Warning, + summary: "It is no longer possible to `x clippy` with stage 0. All clippy commands have to be on stage 1+.", + }, ]; diff --git a/src/bootstrap/src/utils/exec.rs b/src/bootstrap/src/utils/exec.rs index 03760faec69..9a536f75ab7 100644 --- a/src/bootstrap/src/utils/exec.rs +++ b/src/bootstrap/src/utils/exec.rs @@ -15,7 +15,6 @@ use std::hash::Hash; use std::io::{BufWriter, Write}; use std::panic::Location; use std::path::Path; -use std::process; use std::process::{ Child, ChildStderr, ChildStdout, Command, CommandArgs, CommandEnvs, ExitStatus, Output, Stdio, }; @@ -26,10 +25,8 @@ use build_helper::ci::CiEnv; use build_helper::drop_bomb::DropBomb; use build_helper::exit; -use crate::PathBuf; use crate::core::config::DryRun; -#[cfg(feature = "tracing")] -use crate::trace_cmd; +use crate::{PathBuf, t}; /// What should be done when the command fails. #[derive(Debug, Copy, Clone)] @@ -77,9 +74,17 @@ pub struct CommandFingerprint { } impl CommandFingerprint { + #[cfg(feature = "tracing")] + pub(crate) fn program_name(&self) -> String { + Path::new(&self.program) + .file_name() + .map(|p| p.to_string_lossy().to_string()) + .unwrap_or_else(|| "<unknown command>".to_string()) + } + /// Helper method to format both Command and BootstrapCommand as a short execution line, /// without all the other details (e.g. environment variables). - pub fn format_short_cmd(&self) -> String { + pub(crate) fn format_short_cmd(&self) -> String { use std::fmt::Write; let mut cmd = self.program.to_string_lossy().to_string(); @@ -121,17 +126,9 @@ impl CommandProfiler { entry.traces.push(ExecutionTrace::CacheHit); } - pub fn report_summary(&self, start_time: Instant) { - let pid = process::id(); - let filename = format!("bootstrap-profile-{pid}.txt"); - - let file = match File::create(&filename) { - Ok(f) => f, - Err(e) => { - eprintln!("Failed to create profiler output file: {e}"); - return; - } - }; + /// Report summary of executed commands file at the specified `path`. + pub fn report_summary(&self, path: &Path, start_time: Instant) { + let file = t!(File::create(path)); let mut writer = BufWriter::new(file); let stats = self.stats.lock().unwrap(); @@ -221,8 +218,6 @@ impl CommandProfiler { writeln!(writer, "Total cache hits: {total_cache_hits}").unwrap(); writeln!(writer, "Estimated time saved due to cache hits: {total_saved_duration:.2?}") .unwrap(); - - println!("Command profiler report saved to {filename}"); } } @@ -686,9 +681,6 @@ impl ExecutionContext { ) -> DeferredCommand<'a> { let fingerprint = command.fingerprint(); - #[cfg(feature = "tracing")] - let span_guard = trace_cmd!(command); - if let Some(cached_output) = self.command_cache.get(&fingerprint) { command.mark_as_executed(); self.verbose(|| println!("Cache hit: {command:?}")); @@ -696,6 +688,9 @@ impl ExecutionContext { return DeferredCommand { state: CommandState::Cached(cached_output) }; } + #[cfg(feature = "tracing")] + let span_guard = crate::utils::tracing::trace_cmd(command); + let created_at = command.get_created_location(); let executed_at = std::panic::Location::caller(); @@ -779,7 +774,7 @@ impl ExecutionContext { } #[cfg(feature = "tracing")] - let span_guard = trace_cmd!(command); + let span_guard = crate::utils::tracing::trace_cmd(command); let start_time = Instant::now(); let fingerprint = command.fingerprint(); diff --git a/src/bootstrap/src/utils/step_graph.rs b/src/bootstrap/src/utils/step_graph.rs index c45825a4222..cffe0dbb3e3 100644 --- a/src/bootstrap/src/utils/step_graph.rs +++ b/src/bootstrap/src/utils/step_graph.rs @@ -1,8 +1,10 @@ use std::collections::{HashMap, HashSet}; use std::fmt::Debug; use std::io::BufWriter; +use std::path::Path; -use crate::core::builder::{AnyDebug, Step}; +use crate::core::builder::{AnyDebug, Step, pretty_step_name}; +use crate::t; /// Records the executed steps and their dependencies in a directed graph, /// which can then be rendered into a DOT file for visualization. @@ -41,13 +43,7 @@ impl StepGraph { metadata.get_target() ) } else { - let type_name = std::any::type_name::<S>(); - type_name - .strip_prefix("bootstrap::core::") - .unwrap_or(type_name) - .strip_prefix("build_steps::") - .unwrap_or(type_name) - .to_string() + pretty_step_name::<S>() }; let node = Node { label, tooltip: node_key.clone() }; @@ -80,10 +76,10 @@ impl StepGraph { } } - pub fn store_to_dot_files(self) { + pub fn store_to_dot_files(self, directory: &Path) { for (key, graph) in self.graphs.into_iter() { - let filename = format!("bootstrap-steps{key}.dot"); - graph.render(&filename).unwrap(); + let filename = directory.join(format!("step-graph{key}.dot")); + t!(graph.render(&filename)); } } } @@ -147,7 +143,7 @@ impl DotGraph { self.key_to_index.get(key).copied() } - fn render(&self, path: &str) -> std::io::Result<()> { + fn render(&self, path: &Path) -> std::io::Result<()> { use std::io::Write; let mut file = BufWriter::new(std::fs::File::create(path)?); diff --git a/src/bootstrap/src/utils/tracing.rs b/src/bootstrap/src/utils/tracing.rs index 109407bc5f2..428ba013c98 100644 --- a/src/bootstrap/src/utils/tracing.rs +++ b/src/bootstrap/src/utils/tracing.rs @@ -48,17 +48,369 @@ macro_rules! error { } } -#[macro_export] -macro_rules! trace_cmd { - ($cmd:expr) => { +#[cfg(feature = "tracing")] +const COMMAND_SPAN_TARGET: &str = "COMMAND"; + +#[cfg(feature = "tracing")] +pub fn trace_cmd(command: &crate::BootstrapCommand) -> tracing::span::EnteredSpan { + let fingerprint = command.fingerprint(); + let location = command.get_created_location(); + let location = format!("{}:{}", location.file(), location.line()); + + tracing::span!( + target: COMMAND_SPAN_TARGET, + tracing::Level::TRACE, + "cmd", + cmd_name = fingerprint.program_name().to_string(), + cmd = fingerprint.format_short_cmd(), + full_cmd = ?command, + location + ) + .entered() +} + +// # Note on `tracing` usage in bootstrap +// +// Due to the conditional compilation via the `tracing` cargo feature, this means that `tracing` +// usages in bootstrap need to be also gated behind the `tracing` feature: +// +// - `tracing` macros with log levels (`trace!`, `debug!`, `warn!`, `info`, `error`) should not be +// used *directly*. You should use the wrapped `tracing` macros which gate the actual invocations +// behind `feature = "tracing"`. +// - `tracing`'s `#[instrument(..)]` macro will need to be gated like `#![cfg_attr(feature = +// "tracing", instrument(..))]`. +#[cfg(feature = "tracing")] +mod inner { + use std::fmt::Debug; + use std::fs::File; + use std::io::Write; + use std::sync::atomic::Ordering; + + use chrono::{DateTime, Utc}; + use tracing::field::{Field, Visit}; + use tracing::{Event, Id, Level, Subscriber}; + use tracing_subscriber::layer::{Context, SubscriberExt}; + use tracing_subscriber::registry::{LookupSpan, SpanRef}; + use tracing_subscriber::{EnvFilter, Layer}; + + use crate::STEP_SPAN_TARGET; + use crate::utils::tracing::COMMAND_SPAN_TARGET; + + pub fn setup_tracing(env_name: &str) -> TracingGuard { + let filter = EnvFilter::from_env(env_name); + + let registry = tracing_subscriber::registry().with(filter).with(TracingPrinter::default()); + + // When we're creating this layer, we do not yet know the location of the tracing output + // directory, because it is stored in the output directory determined after Config is parsed, + // but we already want to make tracing calls during (and before) config parsing. + // So we store the output into a temporary file, and then move it to the tracing directory + // before bootstrap ends. + let tempdir = tempfile::TempDir::new().expect("Cannot create temporary directory"); + let chrome_tracing_path = tempdir.path().join("bootstrap-trace.json"); + let file = std::io::BufWriter::new(File::create(&chrome_tracing_path).unwrap()); + + let chrome_layer = tracing_chrome::ChromeLayerBuilder::new() + .writer(file) + .include_args(true) + .name_fn(Box::new(|event_or_span| match event_or_span { + tracing_chrome::EventOrSpan::Event(e) => e.metadata().name().to_string(), + tracing_chrome::EventOrSpan::Span(s) => { + if s.metadata().target() == STEP_SPAN_TARGET + && let Some(extension) = s.extensions().get::<StepNameExtension>() + { + extension.0.clone() + } else if s.metadata().target() == COMMAND_SPAN_TARGET + && let Some(extension) = s.extensions().get::<CommandNameExtension>() + { + extension.0.clone() + } else { + s.metadata().name().to_string() + } + } + })); + let (chrome_layer, guard) = chrome_layer.build(); + + tracing::subscriber::set_global_default(registry.with(chrome_layer)).unwrap(); + TracingGuard { guard, _tempdir: tempdir, chrome_tracing_path } + } + + pub struct TracingGuard { + guard: tracing_chrome::FlushGuard, + _tempdir: tempfile::TempDir, + chrome_tracing_path: std::path::PathBuf, + } + + impl TracingGuard { + pub fn copy_to_dir(self, dir: &std::path::Path) { + drop(self.guard); + std::fs::rename(&self.chrome_tracing_path, dir.join("chrome-trace.json")).unwrap(); + } + } + + /// Visitor that extracts both known and unknown field values from events and spans. + #[derive(Default)] + struct FieldValues { + /// Main event message + message: Option<String>, + /// Name of a recorded psna + step_name: Option<String>, + /// Short name of an executed command + cmd_name: Option<String>, + /// The rest of arbitrary event/span fields + fields: Vec<(&'static str, String)>, + } + + impl Visit for FieldValues { + /// Record fields if possible using `record_str`, to avoid rendering simple strings with + /// their `Debug` representation, which adds extra quotes. + fn record_str(&mut self, field: &Field, value: &str) { + match field.name() { + "step_name" => { + self.step_name = Some(value.to_string()); + } + "cmd_name" => { + self.cmd_name = Some(value.to_string()); + } + name => { + self.fields.push((name, value.to_string())); + } + } + } + + fn record_debug(&mut self, field: &Field, value: &dyn Debug) { + let formatted = format!("{value:?}"); + match field.name() { + "message" => { + self.message = Some(formatted); + } + name => { + self.fields.push((name, formatted)); + } + } + } + } + + #[derive(Copy, Clone)] + enum SpanAction { + Enter, + } + + /// Holds the name of a step span, stored in `tracing_subscriber`'s extensions. + struct StepNameExtension(String); + + /// Holds the name of a command span, stored in `tracing_subscriber`'s extensions. + struct CommandNameExtension(String); + + #[derive(Default)] + struct TracingPrinter { + indent: std::sync::atomic::AtomicU32, + span_values: std::sync::Mutex<std::collections::HashMap<tracing::Id, FieldValues>>, + } + + impl TracingPrinter { + fn format_header<W: Write>( + &self, + writer: &mut W, + time: DateTime<Utc>, + level: &Level, + ) -> std::io::Result<()> { + // Use a fixed-width timestamp without date, that shouldn't be very important + let timestamp = time.format("%H:%M:%S.%3f"); + write!(writer, "{timestamp} ")?; + // Make sure that levels are aligned to the same number of characters, in order not to + // break the layout + write!(writer, "{level:>5} ")?; + write!(writer, "{}", " ".repeat(self.indent.load(Ordering::Relaxed) as usize)) + } + + fn write_event<W: Write>(&self, writer: &mut W, event: &Event<'_>) -> std::io::Result<()> { + let now = Utc::now(); + + self.format_header(writer, now, event.metadata().level())?; + + let mut field_values = FieldValues::default(); + event.record(&mut field_values); + + if let Some(msg) = &field_values.message { + write!(writer, "{msg}")?; + } + + if !field_values.fields.is_empty() { + if field_values.message.is_some() { + write!(writer, " ")?; + } + write!(writer, "[")?; + for (index, (name, value)) in field_values.fields.iter().enumerate() { + write!(writer, "{name} = {value}")?; + if index < field_values.fields.len() - 1 { + write!(writer, ", ")?; + } + } + write!(writer, "]")?; + } + write_location(writer, event.metadata())?; + writeln!(writer)?; + Ok(()) + } + + fn write_span<W: Write, S>( + &self, + writer: &mut W, + span: SpanRef<'_, S>, + field_values: Option<&FieldValues>, + action: SpanAction, + ) -> std::io::Result<()> + where + S: for<'lookup> LookupSpan<'lookup>, { - ::tracing::span!( - target: "COMMAND", - ::tracing::Level::TRACE, - "executing command", - cmd = $cmd.fingerprint().format_short_cmd(), - full_cmd = ?$cmd - ).entered() + let now = Utc::now(); + + self.format_header(writer, now, span.metadata().level())?; + match action { + SpanAction::Enter => { + write!(writer, "> ")?; + } + } + + fn write_fields<'a, I: IntoIterator<Item = &'a (&'a str, String)>, W: Write>( + writer: &mut W, + iter: I, + ) -> std::io::Result<()> { + let items = iter.into_iter().collect::<Vec<_>>(); + if !items.is_empty() { + write!(writer, " [")?; + for (index, (name, value)) in items.iter().enumerate() { + write!(writer, "{name} = {value}")?; + if index < items.len() - 1 { + write!(writer, ", ")?; + } + } + write!(writer, "]")?; + } + Ok(()) + } + + // We handle steps specially. We instrument them dynamically in `Builder::ensure`, + // and we want to have custom name for each step span. But tracing doesn't allow setting + // dynamic span names. So we detect step spans here and override their name. + match span.metadata().target() { + // Executed step + STEP_SPAN_TARGET => { + let name = + field_values.and_then(|v| v.step_name.as_deref()).unwrap_or(span.name()); + write!(writer, "{name}")?; + + // There should be only one more field called `args` + if let Some(values) = field_values { + let field = &values.fields[0]; + write!(writer, " {{{}}}", field.1)?; + } + write_location(writer, span.metadata())?; + } + // Executed command + COMMAND_SPAN_TARGET => { + write!(writer, "{}", span.name())?; + if let Some(values) = field_values { + write_fields( + writer, + values.fields.iter().filter(|(name, _)| *name != "location"), + )?; + write!( + writer, + " ({})", + values.fields.iter().find(|(name, _)| *name == "location").unwrap().1 + )?; + } + } + // Other span + _ => { + write!(writer, "{}", span.name())?; + if let Some(values) = field_values { + write_fields(writer, values.fields.iter())?; + } + write_location(writer, span.metadata())?; + } + } + + writeln!(writer)?; + Ok(()) } - }; + } + + fn write_location<W: Write>( + writer: &mut W, + metadata: &'static tracing::Metadata<'static>, + ) -> std::io::Result<()> { + use std::path::{Path, PathBuf}; + + if let Some(filename) = metadata.file() { + // Keep only the module name and file name to make it shorter + let filename: PathBuf = Path::new(filename) + .components() + // Take last two path components + .rev() + .take(2) + .collect::<Vec<_>>() + .into_iter() + .rev() + .collect(); + + write!(writer, " ({}", filename.display())?; + if let Some(line) = metadata.line() { + write!(writer, ":{line}")?; + } + write!(writer, ")")?; + } + Ok(()) + } + + impl<S> Layer<S> for TracingPrinter + where + S: Subscriber, + S: for<'lookup> LookupSpan<'lookup>, + { + fn on_new_span(&self, attrs: &tracing::span::Attributes<'_>, id: &Id, ctx: Context<'_, S>) { + // Record value of span fields + // Note that we do not implement changing values of span fields after they are created. + // For that we would also need to implement the `on_record` method + let mut field_values = FieldValues::default(); + attrs.record(&mut field_values); + + // We need to propagate the actual name of the span to the Chrome layer below, because + // it cannot access field values. We do that through extensions. + if attrs.metadata().target() == STEP_SPAN_TARGET + && let Some(step_name) = field_values.step_name.clone() + { + ctx.span(id).unwrap().extensions_mut().insert(StepNameExtension(step_name)); + } else if attrs.metadata().target() == COMMAND_SPAN_TARGET + && let Some(cmd_name) = field_values.cmd_name.clone() + { + ctx.span(id).unwrap().extensions_mut().insert(CommandNameExtension(cmd_name)); + } + self.span_values.lock().unwrap().insert(id.clone(), field_values); + } + + fn on_event(&self, event: &Event<'_>, _ctx: Context<'_, S>) { + let mut writer = std::io::stderr().lock(); + self.write_event(&mut writer, event).unwrap(); + } + + fn on_enter(&self, id: &Id, ctx: Context<'_, S>) { + if let Some(span) = ctx.span(id) { + let mut writer = std::io::stderr().lock(); + let values = self.span_values.lock().unwrap(); + let values = values.get(id); + self.write_span(&mut writer, span, values, SpanAction::Enter).unwrap(); + } + self.indent.fetch_add(1, Ordering::Relaxed); + } + + fn on_exit(&self, _id: &Id, _ctx: Context<'_, S>) { + self.indent.fetch_sub(1, Ordering::Relaxed); + } + } } + +#[cfg(feature = "tracing")] +pub use inner::setup_tracing; diff --git a/src/ci/docker/host-x86_64/pr-check-2/Dockerfile b/src/ci/docker/host-x86_64/pr-check-2/Dockerfile index 6fea2437276..8073b8efb46 100644 --- a/src/ci/docker/host-x86_64/pr-check-2/Dockerfile +++ b/src/ci/docker/host-x86_64/pr-check-2/Dockerfile @@ -28,7 +28,7 @@ RUN sh /scripts/sccache.sh ENV SCRIPT \ python3 ../x.py check && \ - python3 ../x.py clippy ci && \ + python3 ../x.py clippy ci --stage 2 && \ python3 ../x.py test --stage 1 core alloc std test proc_macro && \ python3 ../x.py test --stage 1 src/tools/compiletest && \ python3 ../x.py doc bootstrap && \ diff --git a/src/ci/docker/scripts/freebsd-toolchain.sh b/src/ci/docker/scripts/freebsd-toolchain.sh index 0d02636db91..56b3c5cd82e 100755 --- a/src/ci/docker/scripts/freebsd-toolchain.sh +++ b/src/ci/docker/scripts/freebsd-toolchain.sh @@ -28,7 +28,9 @@ exit 1 # First up, build binutils mkdir binutils cd binutils -curl https://ftp.gnu.org/gnu/binutils/binutils-${binutils_version}.tar.bz2 | tar xjf - +# Originally downloaded from: +# https://sourceware.org/pub/binutils/releases/binutils-${binutils_version}.tar.bz2 +curl https://ci-mirrors.rust-lang.org/rustc/binutils-${binutils_version}.tar.bz2 | tar xjf - mkdir binutils-build cd binutils-build hide_output ../binutils-${binutils_version}/configure \ diff --git a/src/doc/index.md b/src/doc/index.md index 8ad5b427b55..892057a8f4d 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -172,9 +172,9 @@ unsafe Rust. It's also sometimes called "the 'nomicon." [The Unstable Book](unstable-book/index.html) has documentation for unstable features. -### The `rustc` Contribution Guide +### The `rustc` Development Guide -[The `rustc` Guide](https://rustc-dev-guide.rust-lang.org/) +[The `rustc-dev-guide`](https://rustc-dev-guide.rust-lang.org/) documents how the compiler works and how to contribute to it. This is useful if you want to build or modify the Rust compiler from source (e.g. to target something non-standard). diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping/debugging-bootstrap.md b/src/doc/rustc-dev-guide/src/building/bootstrapping/debugging-bootstrap.md index 9c5ebbd36c4..fb90c0fdb43 100644 --- a/src/doc/rustc-dev-guide/src/building/bootstrapping/debugging-bootstrap.md +++ b/src/doc/rustc-dev-guide/src/building/bootstrapping/debugging-bootstrap.md @@ -1,120 +1,100 @@ # Debugging bootstrap -There are two main ways to debug bootstrap itself. The first is through println logging, and the second is through the `tracing` feature. - -> FIXME: this section should be expanded +There are two main ways of debugging (and profiling bootstrap). The first is through println logging, and the second is through the `tracing` feature. ## `println` logging Bootstrap has extensive unstructured logging. Most of it is gated behind the `--verbose` flag (pass `-vv` for even more detail). -If you want to know which `Step` ran a command, you could invoke bootstrap like so: +If you want to see verbose output of executed Cargo commands and other kinds of detailed logs, pass `-v` or `-vv` when invoking bootstrap. Note that the logs are unstructured and may be overwhelming. ``` $ ./x dist rustc --dry-run -vv learning about cargo running: RUSTC_BOOTSTRAP="1" "/home/jyn/src/rust2/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "metadata" "--format-version" "1" "--no-deps" "--manifest-path" "/home/jyn/src/rust2/Cargo.toml" (failure_mode=Exit) (created at src/bootstrap/src/core/metadata.rs:81:25, executed at src/bootstrap/src/core/metadata.rs:92:50) running: RUSTC_BOOTSTRAP="1" "/home/jyn/src/rust2/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "metadata" "--format-version" "1" "--no-deps" "--manifest-path" "/home/jyn/src/rust2/library/Cargo.toml" (failure_mode=Exit) (created at src/bootstrap/src/core/metadata.rs:81:25, executed at src/bootstrap/src/core/metadata.rs:92:50) -> Assemble { target_compiler: Compiler { stage: 1, host: x86_64-unknown-linux-gnu } } - > Libdir { compiler: Compiler { stage: 1, host: x86_64-unknown-linux-gnu }, target: x86_64-unknown-linux-gnu } - > Sysroot { compiler: Compiler { stage: 1, host: x86_64-unknown-linux-gnu }, force_recompile: false } -Removing sysroot /home/jyn/src/rust2/build/tmp-dry-run/x86_64-unknown-linux-gnu/stage1 to avoid caching bugs - < Sysroot { compiler: Compiler { stage: 1, host: x86_64-unknown-linux-gnu }, force_recompile: false } - < Libdir { compiler: Compiler { stage: 1, host: x86_64-unknown-linux-gnu }, target: x86_64-unknown-linux-gnu } -... -``` - -This will go through all the recursive dependency calculations, where `Step`s internally call `builder.ensure()`, without actually running cargo or the compiler. - -In some cases, even this may not be enough logging (if so, please add more!). In that case, you can omit `--dry-run`, which will show the normal output inline with the debug logging: - -``` - c Sysroot { compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu }, force_recompile: false } -using sysroot /home/jyn/src/rust2/build/x86_64-unknown-linux-gnu/stage0-sysroot -Building stage0 library artifacts (x86_64-unknown-linux-gnu) -running: cd "/home/jyn/src/rust2" && env ... RUSTC_VERBOSE="2" RUSTC_WRAPPER="/home/jyn/src/rust2/build/bootstrap/debug/rustc" "/home/jyn/src/rust2/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "build" "--target" "x86_64-unknown-linux-gnu" "-Zbinary-dep-depinfo" "-Zroot-dir=/home/jyn/src/rust2" "-v" "-v" "--manifest-path" "/home/jyn/src/rust2/library/sysroot/Cargo.toml" "--message-format" "json-render-diagnostics" - 0.293440230s INFO prepare_target{force=false package_id=sysroot v0.0.0 (/home/jyn/src/rust2/library/sysroot) target="sysroot"}: cargo::core::compiler::fingerprint: fingerprint error for sysroot v0.0.0 (/home/jyn/src/rust2/library/sysroot)/Build/TargetInner { name_inferred: true, ..: lib_target("sysroot", ["lib"], "/home/jyn/src/rust2/library/sysroot/src/lib.rs", Edition2021) } ... ``` -In most cases this should not be necessary. +## `tracing` in bootstrap -TODO: we should convert all this to structured logging so it's easier to control precisely. +Bootstrap has a conditional `tracing` feature, which provides the following features: +- It enables structured logging using [`tracing`][tracing] events and spans. +- It generates a [Chrome trace file] that can be used to visualize the hierarchy and durations of executed steps and commands. + - You can open the generated `chrome-trace.json` file using Chrome, on the `chrome://tracing` tab, or e.g. using [Perfetto]. +- It generates [GraphViz] graphs that visualize the dependencies between executed steps. + - You can open the generated `step-graph-*.dot` file using e.g. [xdot] to visualize the step graph, or use e.g. `dot -Tsvg` to convert the GraphViz file to an SVG file. +- It generates a command execution summary, which shows which commands were executed, how many of their executions were cached, and what commands were the slowest to run. + - The generated `command-stats.txt` file is in a simple human-readable format. -## `tracing` in bootstrap +The structured logs will be written to standard error output (`stderr`), while the other outputs will be stored in files in the `<build-dir>/bootstrap-trace/<pid>` directory. For convenience, bootstrap will also create a symlink to the latest generated trace output directory at `<build-dir>/bootstrap-trace/latest`. -Bootstrap has conditional [`tracing`][tracing] setup to provide structured logging. +> Note that if you execute bootstrap with `--dry-run`, the tracing output directory might change. Bootstrap will always print a path where the tracing output files were stored at the end of its execution. [tracing]: https://docs.rs/tracing/0.1.41/tracing/index.html +[Chrome trace file]: https://www.chromium.org/developers/how-tos/trace-event-profiling-tool/ +[Perfetto]: https://ui.perfetto.dev/ +[GraphViz]: https://graphviz.org/doc/info/lang.html +[xdot]: https://github.com/jrfonseca/xdot.py ### Enabling `tracing` output -Bootstrap will conditionally build `tracing` support and enable `tracing` output if the `BOOTSTRAP_TRACING` env var is set. - -#### Basic usage - -Example basic usage[^just-trace]: +To enable the conditional `tracing` feature, run bootstrap with the `BOOTSTRAP_TRACING` environment variable. -[^just-trace]: It is not recommended to use *just* `BOOTSTRAP_TRACING=TRACE` because that will dump *everything* at `TRACE` level, including logs intentionally gated behind custom targets as they are too verbose even for `TRACE` level by default. +[tracing_subscriber filter]: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html ```bash -$ BOOTSTRAP_TRACING=bootstrap=TRACE ./x build library --stage 1 +$ BOOTSTRAP_TRACING=trace ./x build library --stage 1 ``` Example output[^unstable]: ``` -$ BOOTSTRAP_TRACING=bootstrap=TRACE ./x check src/bootstrap/ +$ BOOTSTRAP_TRACING=trace ./x build library --stage 1 --dry-run Building bootstrap - Compiling bootstrap v0.0.0 (/home/joe/repos/rust/src/bootstrap) - Finished `dev` profile [unoptimized] target(s) in 2.74s - DEBUG bootstrap parsing flags - bootstrap::core::config::flags::Flags::parse args=["check", "src/bootstrap/"] - DEBUG bootstrap parsing config based on flags - DEBUG bootstrap creating new build based on config - bootstrap::Build::build - TRACE bootstrap setting up job management - TRACE bootstrap downloading rustfmt early - bootstrap::handling hardcoded subcommands (Format, Suggest, Perf) - DEBUG bootstrap not a hardcoded subcommand; returning to normal handling, cmd=Check { all_targets: false } - DEBUG bootstrap handling subcommand normally - bootstrap::executing real run - bootstrap::(1) executing dry-run sanity-check - bootstrap::(2) executing actual run -Checking stage0 library artifacts (x86_64-unknown-linux-gnu) - Finished `release` profile [optimized + debuginfo] target(s) in 0.04s -Checking stage0 compiler artifacts {rustc-main, rustc_abi, rustc_arena, rustc_ast, rustc_ast_ir, rustc_ast_lowering, rustc_ast_passes, rustc_ast_pretty, rustc_attr_data_structures, rustc_attr_parsing, rustc_baked_icu_data, rustc_borrowck, rustc_builtin_macros, rustc_codegen_llvm, rustc_codegen_ssa, rustc_const_eval, rustc_data_structures, rustc_driver, rustc_driver_impl, rustc_error_codes, rustc_error_messages, rustc_errors, rustc_expand, rustc_feature, rustc_fluent_macro, rustc_fs_util, rustc_graphviz, rustc_hir, rustc_hir_analysis, rustc_hir_pretty, rustc_hir_typeck, rustc_incremental, rustc_index, rustc_index_macros, rustc_infer, rustc_interface, rustc_lexer, rustc_lint, rustc_lint_defs, rustc_llvm, rustc_log, rustc_macros, rustc_metadata, rustc_middle, rustc_mir_build, rustc_mir_dataflow, rustc_mir_transform, rustc_monomorphize, rustc_next_trait_solver, rustc_parse, rustc_parse_format, rustc_passes, rustc_pattern_analysis, rustc_privacy, rustc_query_impl, rustc_query_system, rustc_resolve, rustc_sanitizers, rustc_serialize, rustc_session, rustc_smir, rustc_span, rustc_symbol_mangling, rustc_target, rustc_trait_selection, rustc_traits, rustc_transmute, rustc_ty_utils, rustc_type_ir, rustc_type_ir_macros, stable_mir} (x86_64-unknown-linux-gnu) - Finished `release` profile [optimized + debuginfo] target(s) in 0.23s -Checking stage0 bootstrap artifacts (x86_64-unknown-linux-gnu) - Checking bootstrap v0.0.0 (/home/joe/repos/rust/src/bootstrap) - Finished `release` profile [optimized + debuginfo] target(s) in 0.64s - DEBUG bootstrap checking for postponed test failures from `test --no-fail-fast` -Build completed successfully in 0:00:08 + Finished `dev` profile [unoptimized] target(s) in 0.05s +15:56:52.477 INFO > tool::LibcxxVersionTool {target: x86_64-unknown-linux-gnu} (builder/mod.rs:1715) +15:56:52.575 INFO > compile::Assemble {target_compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }} (builder/mod.rs:1715) +15:56:52.575 INFO > tool::Compiletest {compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, target: x86_64-unknown-linux-gnu} (builder/mod.rs:1715) +15:56:52.576 INFO > tool::ToolBuild {build_compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, target: x86_64-unknown-linux-gnu, tool: "compiletest", path: "src/tools/compiletest", mode: ToolBootstrap, source_type: InTree, extra_features: [], allow_features: "internal_output_capture", cargo_args: [], artifact_kind: Binary} (builder/mod.rs:1715) +15:56:52.576 INFO > builder::Libdir {compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, target: x86_64-unknown-linux-gnu} (builder/mod.rs:1715) +15:56:52.576 INFO > compile::Sysroot {compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, force_recompile: false} (builder/mod.rs:1715) +15:56:52.578 INFO > compile::Assemble {target_compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }} (builder/mod.rs:1715) +15:56:52.578 INFO > tool::Compiletest {compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, target: x86_64-unknown-linux-gnu} (builder/mod.rs:1715) +15:56:52.578 INFO > tool::ToolBuild {build_compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, target: x86_64-unknown-linux-gnu, tool: "compiletest", path: "src/tools/compiletest", mode: ToolBootstrap, source_type: InTree, extra_features: [], allow_features: "internal_output_capture", cargo_args: [], artifact_kind: Binary} (builder/mod.rs:1715) +15:56:52.578 INFO > builder::Libdir {compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, target: x86_64-unknown-linux-gnu} (builder/mod.rs:1715) +15:56:52.578 INFO > compile::Sysroot {compiler: Compiler { stage: 0, host: x86_64-unknown-linux-gnu, forced_compiler: false }, force_recompile: false} (builder/mod.rs:1715) + Finished `release` profile [optimized] target(s) in 0.11s +Tracing/profiling output has been written to <src-root>/build/bootstrap-trace/latest +Build completed successfully in 0:00:00 ``` +[^unstable]: This output is always subject to further changes. + #### Controlling tracing output -The env var `BOOTSTRAP_TRACING` accepts a [`tracing` env-filter][tracing-env-filter]. +The environment variable `BOOTSTRAP_TRACING` accepts a [`tracing_subscriber` filter][tracing-env-filter]. If you set `BOOTSTRAP_TRACING=trace`, you will enable all logs, but that can be overwhelming. You can thus use the filter to reduce the amount of data logged. There are two orthogonal ways to control which kind of tracing logs you want: -1. You can specify the log **level**, e.g. `DEBUG` or `TRACE`. -2. You can also control the log **target**, e.g. `bootstrap` or `bootstrap::core::config` vs custom targets like `CONFIG_HANDLING`. - - Custom targets are used to limit what is output when `BOOTSTRAP_TRACING=bootstrap=TRACE` is used, as they can be too verbose even for `TRACE` level by default. Currently used custom targets: - - `CONFIG_HANDLING` - -The `TRACE` filter will enable *all* `trace` level or less verbose level tracing output. +1. You can specify the log **level**, e.g. `debug` or `trace`. + - If you select a level, all events/spans with an equal or higher priority level will be shown. +2. You can also control the log **target**, e.g. `bootstrap` or `bootstrap::core::config` or a custom target like `CONFIG_HANDLING` or `STEP`. + - Custom targets are used to limit what kinds of spans you are interested in, as the `BOOTSTRAP_TRACING=trace` output can be quite verbose. Currently, you can use the following custom targets: + - `CONFIG_HANDLING`: show spans related to config handling + - `STEP`: show all executed steps. Note that executed commands have `info` event level. + - `COMMAND`: show all executed commands. Note that executed commands have `trace` event level. You can of course combine them (custom target logs are typically gated behind `TRACE` log level additionally): ```bash -$ BOOTSTRAP_TRACING=CONFIG_HANDLING=TRACE ./x build library --stage 1 +$ BOOTSTRAP_TRACING=CONFIG_HANDLING=trace,STEP=info,COMMAND=trace ./x build library --stage 1 ``` -[^unstable]: This output is always subject to further changes. - [tracing-env-filter]: https://docs.rs/tracing-subscriber/0.3.19/tracing_subscriber/filter/struct.EnvFilter.html +Note that the level that you specify using `BOOTSTRAP_TRACING` also has an effect on the spans that will be recorded in the Chrome trace file. + ##### FIXME(#96176): specific tracing for `compiler()` vs `compiler_for()` The additional targets `COMPILER` and `COMPILER_FOR` are used to help trace what @@ -123,12 +103,6 @@ if [#96176][cleanup-compiler-for] is resolved. [cleanup-compiler-for]: https://github.com/rust-lang/rust/issues/96176 -### Rendering step graph - -When you run bootstrap with the `BOOTSTRAP_TRACING` environment variable configured, bootstrap will automatically output a DOT file that shows all executed steps and their dependencies. The files will have a prefix `bootstrap-steps`. You can use e.g. `xdot` to visualize the file or e.g. `dot -Tsvg` to convert the DOT file to a SVG file. - -A separate DOT file will be outputted for dry-run and non-dry-run execution. - ### Using `tracing` in bootstrap Both `tracing::*` macros and the `tracing::instrument` proc-macro attribute need to be gated behind `tracing` feature. Examples: @@ -149,15 +123,6 @@ impl Step for Foo { todo!() } - #[cfg_attr( - feature = "tracing", - instrument( - level = "trace", - name = "Foo::run", - skip_all, - fields(compiler = ?builder.compiler), - ), - )] fn run(self, builder: &Builder<'_>) -> Self::Output { trace!(?run, "entered Foo::run"); @@ -172,21 +137,6 @@ For `#[instrument]`, it's recommended to: - Explicitly pick an instrumentation name via `name = ".."` to distinguish between e.g. `run` of different steps. - Take care to not cause diverging behavior via tracing, e.g. building extra things only when tracing infra is enabled. -### Profiling bootstrap - -You can set the `BOOTSTRAP_PROFILE=1` environment variable to enable command execution profiling during bootstrap. This generates: - -* A Chrome trace file (for visualization in `chrome://tracing` or [Perfetto](https://ui.perfetto.dev)) if tracing is enabled via `BOOTSTRAP_TRACING=COMMAND=trace` -* A plain-text summary file, `bootstrap-profile-{pid}.txt`, listing all commands sorted by execution time (slowest first), along with cache hits and working directories - -Note: the `.txt` report is always generated when `BOOTSTRAP_PROFILE=1` is set — tracing is not required. - -Example usage: - -```bash -$ BOOTSTRAP_PROFILE=1 BOOTSTRAP_TRACING=COMMAND=trace ./x build library -``` - ### rust-analyzer integration? Unfortunately, because bootstrap is a `rust-analyzer.linkedProjects`, you can't ask r-a to check/build bootstrap itself with `tracing` feature enabled to get relevant completions, due to lack of support as described in <https://github.com/rust-lang/rust-analyzer/issues/8521>. diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 25f154f1180..b53494ed98d 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -23,6 +23,7 @@ - [Linker-plugin-based LTO](linker-plugin-lto.md) - [Checking Conditional Configurations](check-cfg.md) - [Cargo Specifics](check-cfg/cargo-specifics.md) +- [Remap source paths](remap-source-paths.md) - [Exploit Mitigations](exploit-mitigations.md) - [Symbol Mangling](symbol-mangling/index.md) - [v0 Symbol Format](symbol-mangling/v0.md) @@ -47,6 +48,7 @@ - [\*-apple-visionos](platform-support/apple-visionos.md) - [aarch64-nintendo-switch-freestanding](platform-support/aarch64-nintendo-switch-freestanding.md) - [aarch64-unknown-linux-musl](platform-support/aarch64-unknown-linux-musl.md) + - [aarch64_be-unknown-none-softfloat](platform-support/aarch64_be-unknown-none-softfloat.md) - [amdgcn-amd-amdhsa](platform-support/amdgcn-amd-amdhsa.md) - [armeb-unknown-linux-gnueabi](platform-support/armeb-unknown-linux-gnueabi.md) - [arm-none-eabi](platform-support/arm-none-eabi.md) diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index d45ad1be27b..0b15fbc24df 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -418,22 +418,15 @@ This flag takes a number that specifies the width of the terminal in characters. Formatting of diagnostics will take the width into consideration to make them better fit on the screen. <a id="option-remap-path-prefix"></a> -## `--remap-path-prefix`: remap source names in output +## `--remap-path-prefix`: remap source paths in output Remap source path prefixes in all output, including compiler diagnostics, -debug information, macro expansions, etc. It takes a value of the form -`FROM=TO` where a path prefix equal to `FROM` is rewritten to the value `TO`. -The `FROM` may itself contain an `=` symbol, but the `TO` value may not. This -flag may be specified multiple times. - -This is useful for normalizing build products, for example by removing the -current directory out of pathnames emitted into the object files. The -replacement is purely textual, with no consideration of the current system's -pathname syntax. For example `--remap-path-prefix foo=bar` will match -`foo/lib.rs` but not `./foo/lib.rs`. - -When multiple remappings are given and several of them match, the **last** -matching one is applied. +debug information, macro expansions, etc. It takes a value of the form `FROM=TO` +where a path prefix equal to `FROM` is rewritten to the value `TO`. This flag may be +specified multiple times. + +Refer to the [Remap source paths](remap-source-paths.md) section of this book for +further details and explanation. <a id="option-json"></a> ## `--json`: configure json messages printed by the compiler diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 8ebaa8dd874..89b43cda9b9 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -273,6 +273,7 @@ target | std | host | notes `aarch64_be-unknown-linux-gnu` | ✓ | ✓ | ARM64 Linux (big-endian) `aarch64_be-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (big-endian, ILP32 ABI) [`aarch64_be-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | ARM64 NetBSD (big-endian) +[`aarch64_be-unknown-none-softfloat`](platform-support/aarch64_be-unknown-none-softfloat.md) | * | | Bare big-endian ARM64, softfloat [`amdgcn-amd-amdhsa`](platform-support/amdgcn-amd-amdhsa.md) | * | | `-Ctarget-cpu=gfx...` to specify [the AMD GPU] to compile for [`arm64_32-apple-watchos`](platform-support/apple-watchos.md) | ✓ | | Arm Apple WatchOS 64-bit with 32-bit pointers [`arm64e-apple-darwin`](platform-support/arm64e-apple-darwin.md) | ✓ | ✓ | ARM64e Apple Darwin diff --git a/src/doc/rustc/src/platform-support/aarch64_be-unknown-none-softfloat.md b/src/doc/rustc/src/platform-support/aarch64_be-unknown-none-softfloat.md new file mode 100644 index 00000000000..a28ddcdf7f2 --- /dev/null +++ b/src/doc/rustc/src/platform-support/aarch64_be-unknown-none-softfloat.md @@ -0,0 +1,74 @@ +# aarch64_be-unknown-none-softfloat + +**Tier: 3** + +Target for freestanding/bare-metal big-endian ARM64 binaries in ELF format: +firmware, kernels, etc. + +## Target maintainers + +[@Gelbpunkt](https://github.com/Gelbpunkt) + +## Requirements + +This target is cross-compiled. There is no support for `std`. There is no +default allocator, but it's possible to use `alloc` by supplying an allocator. + +The target does not assume existence of a FPU and does not make use of any +non-GPR register. This allows the generated code to run in environments, such +as kernels, which may need to avoid the use of such registers or which may have +special considerations about the use of such registers (e.g. saving and +restoring them to avoid breaking userspace code using the same registers). You +can change code generation to use additional CPU features via the +`-C target-feature=` codegen options to rustc, or via the `#[target_feature]` +mechanism within Rust code. + +By default, code generated with the soft-float target should run on any +big-endian ARM64 hardware, enabling additional target features may raise this +baseline. + +`extern "C"` uses the [architecture's standard calling convention][aapcs64]. + +[aapcs64]: https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst + +The targets generate binaries in the ELF format. Any alternate formats or +special considerations for binary layout will require linker options or linker +scripts. + +## Building the target + +You can build Rust with support for the target by adding it to the `target` +list in `bootstrap.toml`: + +```toml +[build] +target = ["aarch64_be-unknown-none-softfloat"] +``` + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for this target. To compile for +this target, you will first need to build Rust with the target enabled (see +"Building the target" above). + +## Cross-compilation + +For cross builds, you will need an appropriate ARM64 C/C++ toolchain for +linking, or if you want to compile C code along with Rust (such as for Rust +crates with C dependencies). + +Rust *may* be able to use an `aarch64_be-unknown-linux-{gnu,musl}-` toolchain +with appropriate standalone flags to build for this target (depending on the +assumptions of that toolchain, see below), or you may wish to use a separate +`aarch64_be-unknown-none-softfloat` toolchain. + +On some ARM64 hosts that use ELF binaries, you *may* be able to use the host C +toolchain, if it does not introduce assumptions about the host environment that +don't match the expectations of a standalone environment. Otherwise, you may +need a separate toolchain for standalone/freestanding development, just as when +cross-compiling from a non-ARM64 platform. + +## Testing + +As the target supports a variety of different environments and does not support +`std`, it does not support running the Rust test suite. diff --git a/src/doc/rustc/src/remap-source-paths.md b/src/doc/rustc/src/remap-source-paths.md new file mode 100644 index 00000000000..03f5d98091c --- /dev/null +++ b/src/doc/rustc/src/remap-source-paths.md @@ -0,0 +1,53 @@ +# Remap source paths + +`rustc` supports remapping source paths prefixes **as a best effort** in all compiler generated +output, including compiler diagnostics, debugging information, macro expansions, etc. + +This is useful for normalizing build products, for example by removing the current directory +out of the paths emitted into object files. + +The remapping is done via the `--remap-path-prefix` option. + +## `--remap-path-prefix` + +It takes a value of the form `FROM=TO` where a path prefix equal to `FROM` is rewritten +to the value `TO`. `FROM` may itself contain an `=` symbol, but `TO` value may not. + +The replacement is purely textual, with no consideration of the current system's path separator. + +When multiple remappings are given and several of them match, the **last** matching one is applied. + +### Example + +```bash +rustc --remap-path-prefix "/home/user/project=/redacted" +``` + +This example replaces all occurrences of `/home/user/project` in emitted paths with `/redacted`. + +## Caveats and Limitations + +### Linkers generated paths + +On some platforms like `x86_64-pc-windows-msvc`, the linker may embed absolute host paths and compiler +arguments into debug info files (like `.pdb`) independently of `rustc`. + +Additionally, on Apple platforms, linkers generate [OSO entries] which are not remapped by the compiler +and need to be manually remapped with `-oso_prefix`. + +The `--remap-path-prefix` option does not affect these linker-generated paths. + +### Textual replacement only + +The remapping is strictly textual and does not account for different path separator conventions across +platforms. Care must be taken when specifying prefixes, especially on Windows where both `/` and `\` may +appear in paths. + +### External tools + +Paths introduced by external tools or environment variables may not be covered by `--remap-path-prefix` +unless explicitly accounted for. + +For example, generated code introduced by Cargo's build script may still contain un-remapped paths. + +[OSO entries]: https://wiki.dwarfstd.org/Apple%27s_%22Lazy%22_DWARF_Scheme.md diff --git a/src/doc/rustc/src/tests/index.md b/src/doc/rustc/src/tests/index.md index 12de69a4c9e..7609ed23351 100644 --- a/src/doc/rustc/src/tests/index.md +++ b/src/doc/rustc/src/tests/index.md @@ -164,7 +164,7 @@ Sets the number of threads to use for running tests in parallel. By default, uses the amount of concurrency available on the hardware as indicated by [`available_parallelism`]. -This can also be specified with the `RUST_TEST_THREADS` environment variable. +Deprecated: this can also be specified with the `RUST_TEST_THREADS` environment variable. #### `--force-run-in-process` @@ -186,7 +186,7 @@ docs](../../unstable-book/compiler-flags/report-time.html) for more information. Runs the tests in random order, as opposed to the default alphabetical order. -This may also be specified by setting the `RUST_TEST_SHUFFLE` environment +Deprecated: this may also be specified by setting the `RUST_TEST_SHUFFLE` environment variable to anything but `0`. The random number generator seed that is output can be passed to @@ -209,7 +209,7 @@ the tests in the same order both times. _SEED_ is any 64-bit unsigned integer, for example, one produced by [`--shuffle`](#--shuffle). -This can also be specified with the `RUST_TEST_SHUFFLE_SEED` environment +Deprecated: this can also be specified with the `RUST_TEST_SHUFFLE_SEED` environment variable. ⚠️ 🚧 This option is [unstable](#unstable-options), and requires the `-Z @@ -231,7 +231,7 @@ Does not capture the stdout and stderr of the test, and allows tests to print to the console. Usually the output is captured, and only displayed if the test fails. -This may also be specified by setting the `RUST_TEST_NOCAPTURE` environment +Deprecated: this may also be specified by setting the `RUST_TEST_NOCAPTURE` environment variable to anything but `0`. `--nocapture` is a deprecated alias for `--no-capture`. diff --git a/src/doc/rustdoc/src/write-documentation/documentation-tests.md b/src/doc/rustdoc/src/write-documentation/documentation-tests.md index e6b15e0dbd3..4084c1d962a 100644 --- a/src/doc/rustdoc/src/write-documentation/documentation-tests.md +++ b/src/doc/rustdoc/src/write-documentation/documentation-tests.md @@ -191,6 +191,20 @@ We can document it by escaping the initial `#`: /// ## bar # baz"; ``` +Here is an example with a macro rule which matches on tokens starting with `#`: + +`````rust,no_run +/// ``` +/// macro_rules! ignore { (##tag) => {}; } +/// ignore! { +/// ###tag +/// } +/// ``` +# fn f() {} +````` + +As you can see, the rule is expecting two `#`, so when calling it, we need to add an extra `#` +because the first one is used as escape. ## Using `?` in doc tests diff --git a/src/doc/unstable-book/src/compiler-flags/codegen-source-order.md b/src/doc/unstable-book/src/compiler-flags/codegen-source-order.md new file mode 100644 index 00000000000..cb019fe0176 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/codegen-source-order.md @@ -0,0 +1,12 @@ +# `codegen-source-order` + +--- + +This feature allows you to have a predictive and +deterministic order for items after codegen, which +is the same as in source code. + +For every `CodegenUnit`, local `MonoItem`s would +be sorted by `(Span, SymbolName)`, which +makes codegen tests rely on the order of items in +source files work. diff --git a/src/etc/completions/x.fish b/src/etc/completions/x.fish index a5e5bb8f09e..0b9af334214 100644 --- a/src/etc/completions/x.fish +++ b/src/etc/completions/x.fish @@ -97,6 +97,7 @@ complete -c x -n "__fish_x_using_subcommand build" -l llvm-profile-use -d 'use P complete -c x -n "__fish_x_using_subcommand build" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r complete -c x -n "__fish_x_using_subcommand build" -l set -d 'override options in bootstrap.toml' -r -f complete -c x -n "__fish_x_using_subcommand build" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" +complete -c x -n "__fish_x_using_subcommand build" -l timings -d 'Pass `--timings` to Cargo to get crate build timings' complete -c x -n "__fish_x_using_subcommand build" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x -n "__fish_x_using_subcommand build" -s i -l incremental -d 'use incremental compilation' complete -c x -n "__fish_x_using_subcommand build" -l include-default-paths -d 'include default paths in addition to the provided ones' @@ -133,6 +134,7 @@ complete -c x -n "__fish_x_using_subcommand check" -l reproducible-artifact -d ' complete -c x -n "__fish_x_using_subcommand check" -l set -d 'override options in bootstrap.toml' -r -f complete -c x -n "__fish_x_using_subcommand check" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x -n "__fish_x_using_subcommand check" -l all-targets -d 'Check all targets' +complete -c x -n "__fish_x_using_subcommand check" -l timings -d 'Pass `--timings` to Cargo to get crate build timings' complete -c x -n "__fish_x_using_subcommand check" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x -n "__fish_x_using_subcommand check" -s i -l incremental -d 'use incremental compilation' complete -c x -n "__fish_x_using_subcommand check" -l include-default-paths -d 'include default paths in addition to the provided ones' diff --git a/src/etc/completions/x.ps1 b/src/etc/completions/x.ps1 index 4fee3bc0a86..95cee4b6336 100644 --- a/src/etc/completions/x.ps1 +++ b/src/etc/completions/x.ps1 @@ -102,6 +102,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') + [CompletionResult]::new('--timings', '--timings', [CompletionResultType]::ParameterName, 'Pass `--timings` to Cargo to get crate build timings') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') @@ -145,6 +146,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('--all-targets', '--all-targets', [CompletionResultType]::ParameterName, 'Check all targets') + [CompletionResult]::new('--timings', '--timings', [CompletionResultType]::ParameterName, 'Pass `--timings` to Cargo to get crate build timings') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') diff --git a/src/etc/completions/x.py.fish b/src/etc/completions/x.py.fish index e2e6ae05ee0..6fba6a45623 100644 --- a/src/etc/completions/x.py.fish +++ b/src/etc/completions/x.py.fish @@ -97,6 +97,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand build" -l llvm-profile-use -d complete -c x.py -n "__fish_x.py_using_subcommand build" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r complete -c x.py -n "__fish_x.py_using_subcommand build" -l set -d 'override options in bootstrap.toml' -r -f complete -c x.py -n "__fish_x.py_using_subcommand build" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand build" -l timings -d 'Pass `--timings` to Cargo to get crate build timings' complete -c x.py -n "__fish_x.py_using_subcommand build" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x.py -n "__fish_x.py_using_subcommand build" -s i -l incremental -d 'use incremental compilation' complete -c x.py -n "__fish_x.py_using_subcommand build" -l include-default-paths -d 'include default paths in addition to the provided ones' @@ -133,6 +134,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand check" -l reproducible-artifac complete -c x.py -n "__fish_x.py_using_subcommand check" -l set -d 'override options in bootstrap.toml' -r -f complete -c x.py -n "__fish_x.py_using_subcommand check" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x.py -n "__fish_x.py_using_subcommand check" -l all-targets -d 'Check all targets' +complete -c x.py -n "__fish_x.py_using_subcommand check" -l timings -d 'Pass `--timings` to Cargo to get crate build timings' complete -c x.py -n "__fish_x.py_using_subcommand check" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x.py -n "__fish_x.py_using_subcommand check" -s i -l incremental -d 'use incremental compilation' complete -c x.py -n "__fish_x.py_using_subcommand check" -l include-default-paths -d 'include default paths in addition to the provided ones' diff --git a/src/etc/completions/x.py.ps1 b/src/etc/completions/x.py.ps1 index ea3aacc21c7..458879a17a7 100644 --- a/src/etc/completions/x.py.ps1 +++ b/src/etc/completions/x.py.ps1 @@ -102,6 +102,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') + [CompletionResult]::new('--timings', '--timings', [CompletionResultType]::ParameterName, 'Pass `--timings` to Cargo to get crate build timings') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') @@ -145,6 +146,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('--all-targets', '--all-targets', [CompletionResultType]::ParameterName, 'Check all targets') + [CompletionResult]::new('--timings', '--timings', [CompletionResultType]::ParameterName, 'Pass `--timings` to Cargo to get crate build timings') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') diff --git a/src/etc/completions/x.py.sh b/src/etc/completions/x.py.sh index f31bdb58dc4..e003bf7fd0b 100644 --- a/src/etc/completions/x.py.sh +++ b/src/etc/completions/x.py.sh @@ -458,7 +458,7 @@ _x.py() { return 0 ;; x.py__build) - opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --timings --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -644,7 +644,7 @@ _x.py() { return 0 ;; x.py__check) - opts="-v -i -j -h --all-targets --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --all-targets --timings --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 diff --git a/src/etc/completions/x.py.zsh b/src/etc/completions/x.py.zsh index 32e986ad141..b82c2d65e86 100644 --- a/src/etc/completions/x.py.zsh +++ b/src/etc/completions/x.py.zsh @@ -90,6 +90,7 @@ _arguments "${_arguments_options[@]}" : \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ '*--set=[override options in bootstrap.toml]:section.option=value:' \ '--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ +'--timings[Pass \`--timings\` to Cargo to get crate build timings]' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ @@ -135,6 +136,7 @@ _arguments "${_arguments_options[@]}" : \ '*--set=[override options in bootstrap.toml]:section.option=value:' \ '--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '--all-targets[Check all targets]' \ +'--timings[Pass \`--timings\` to Cargo to get crate build timings]' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ diff --git a/src/etc/completions/x.sh b/src/etc/completions/x.sh index 927d8f7661c..c2cb7710020 100644 --- a/src/etc/completions/x.sh +++ b/src/etc/completions/x.sh @@ -458,7 +458,7 @@ _x() { return 0 ;; x__build) - opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --timings --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -644,7 +644,7 @@ _x() { return 0 ;; x__check) - opts="-v -i -j -h --all-targets --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --all-targets --timings --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 diff --git a/src/etc/completions/x.zsh b/src/etc/completions/x.zsh index 65995553276..49139e70f7f 100644 --- a/src/etc/completions/x.zsh +++ b/src/etc/completions/x.zsh @@ -90,6 +90,7 @@ _arguments "${_arguments_options[@]}" : \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ '*--set=[override options in bootstrap.toml]:section.option=value:' \ '--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ +'--timings[Pass \`--timings\` to Cargo to get crate build timings]' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ @@ -135,6 +136,7 @@ _arguments "${_arguments_options[@]}" : \ '*--set=[override options in bootstrap.toml]:section.option=value:' \ '--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '--all-targets[Check all targets]' \ +'--timings[Pass \`--timings\` to Cargo to get crate build timings]' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 8c0f897c992..0d98c64bbde 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -6,7 +6,7 @@ use std::sync::Arc; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::Mutability; -use rustc_hir::def::{DefKind, Res}; +use rustc_hir::def::{DefKind, MacroKinds, Res}; use rustc_hir::def_id::{DefId, DefIdSet, LocalDefId, LocalModDefId}; use rustc_metadata::creader::{CStore, LoadedMacro}; use rustc_middle::ty::fast_reject::SimplifiedType; @@ -137,13 +137,16 @@ pub(crate) fn try_inline( clean::ConstantItem(Box::new(ct)) }) } - Res::Def(DefKind::Macro(kind), did) => { - let mac = build_macro(cx, did, name, kind); - - let type_kind = match kind { - MacroKind::Bang => ItemType::Macro, - MacroKind::Attr => ItemType::ProcAttribute, - MacroKind::Derive => ItemType::ProcDerive, + Res::Def(DefKind::Macro(kinds), did) => { + let mac = build_macro(cx, did, name, kinds); + + // FIXME: handle attributes and derives that aren't proc macros, and macros with + // multiple kinds + let type_kind = match kinds { + MacroKinds::BANG => ItemType::Macro, + MacroKinds::ATTR => ItemType::ProcAttribute, + MacroKinds::DERIVE => ItemType::ProcDerive, + _ => todo!("Handle macros with multiple kinds"), }; record_extern_fqn(cx, did, type_kind); mac @@ -749,22 +752,36 @@ fn build_macro( cx: &mut DocContext<'_>, def_id: DefId, name: Symbol, - macro_kind: MacroKind, + macro_kinds: MacroKinds, ) -> clean::ItemKind { match CStore::from_tcx(cx.tcx).load_macro_untracked(def_id, cx.tcx) { - LoadedMacro::MacroDef { def, .. } => match macro_kind { - MacroKind::Bang => clean::MacroItem(clean::Macro { + // FIXME: handle attributes and derives that aren't proc macros, and macros with multiple + // kinds + LoadedMacro::MacroDef { def, .. } => match macro_kinds { + MacroKinds::BANG => clean::MacroItem(clean::Macro { source: utils::display_macro_source(cx, name, &def), macro_rules: def.macro_rules, }), - MacroKind::Derive | MacroKind::Attr => { - clean::ProcMacroItem(clean::ProcMacro { kind: macro_kind, helpers: Vec::new() }) - } + MacroKinds::DERIVE => clean::ProcMacroItem(clean::ProcMacro { + kind: MacroKind::Derive, + helpers: Vec::new(), + }), + MacroKinds::ATTR => clean::ProcMacroItem(clean::ProcMacro { + kind: MacroKind::Attr, + helpers: Vec::new(), + }), + _ => todo!("Handle macros with multiple kinds"), }, - LoadedMacro::ProcMacro(ext) => clean::ProcMacroItem(clean::ProcMacro { - kind: ext.macro_kind(), - helpers: ext.helper_attrs, - }), + LoadedMacro::ProcMacro(ext) => { + // Proc macros can only have a single kind + let kind = match ext.macro_kinds() { + MacroKinds::BANG => MacroKind::Bang, + MacroKinds::ATTR => MacroKind::Attr, + MacroKinds::DERIVE => MacroKind::Derive, + _ => unreachable!(), + }; + clean::ProcMacroItem(clean::ProcMacro { kind, helpers: ext.helper_attrs }) + } } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 890bfaced6c..4ff94cc6f3b 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -40,7 +40,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet, In use rustc_errors::codes::*; use rustc_errors::{FatalError, struct_span_code_err}; use rustc_hir::attrs::AttributeKind; -use rustc_hir::def::{CtorKind, DefKind, Res}; +use rustc_hir::def::{CtorKind, DefKind, MacroKinds, Res}; use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LOCAL_CRATE, LocalDefId}; use rustc_hir::{LangItem, PredicateOrigin, find_attr}; use rustc_hir_analysis::hir_ty_lowering::FeedConstTy; @@ -2845,11 +2845,19 @@ fn clean_maybe_renamed_item<'tcx>( generics: clean_generics(generics, cx), fields: variant_data.fields().iter().map(|x| clean_field(x, cx)).collect(), }), - ItemKind::Macro(_, macro_def, MacroKind::Bang) => MacroItem(Macro { + // FIXME: handle attributes and derives that aren't proc macros, and macros with + // multiple kinds + ItemKind::Macro(_, macro_def, MacroKinds::BANG) => MacroItem(Macro { source: display_macro_source(cx, name, macro_def), macro_rules: macro_def.macro_rules, }), - ItemKind::Macro(_, _, macro_kind) => clean_proc_macro(item, &mut name, macro_kind, cx), + ItemKind::Macro(_, _, MacroKinds::ATTR) => { + clean_proc_macro(item, &mut name, MacroKind::Attr, cx) + } + ItemKind::Macro(_, _, MacroKinds::DERIVE) => { + clean_proc_macro(item, &mut name, MacroKind::Derive, cx) + } + ItemKind::Macro(_, _, _) => todo!("Handle macros with multiple kinds"), // proc macros can have a name set by attributes ItemKind::Fn { ref sig, generics, body: body_id, .. } => { clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx) diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs index 3aba7a370ad..1dba84aa44c 100644 --- a/src/librustdoc/formats/item_type.rs +++ b/src/librustdoc/formats/item_type.rs @@ -2,7 +2,7 @@ use std::fmt; -use rustc_hir::def::{CtorOf, DefKind}; +use rustc_hir::def::{CtorOf, DefKind, MacroKinds}; use rustc_span::hygiene::MacroKind; use serde::{Serialize, Serializer}; @@ -134,9 +134,10 @@ impl ItemType { DefKind::Trait => Self::Trait, DefKind::TyAlias => Self::TypeAlias, DefKind::TraitAlias => Self::TraitAlias, - DefKind::Macro(MacroKind::Bang) => ItemType::Macro, - DefKind::Macro(MacroKind::Attr) => ItemType::ProcAttribute, - DefKind::Macro(MacroKind::Derive) => ItemType::ProcDerive, + DefKind::Macro(MacroKinds::BANG) => ItemType::Macro, + DefKind::Macro(MacroKinds::ATTR) => ItemType::ProcAttribute, + DefKind::Macro(MacroKinds::DERIVE) => ItemType::ProcDerive, + DefKind::Macro(_) => todo!("Handle macros with multiple kinds"), DefKind::ForeignTy => Self::ForeignType, DefKind::Variant => Self::Variant, DefKind::Field => Self::StructField, diff --git a/src/librustdoc/html/markdown/footnotes.rs b/src/librustdoc/html/markdown/footnotes.rs index 7ee012c4da2..a81d8dd6035 100644 --- a/src/librustdoc/html/markdown/footnotes.rs +++ b/src/librustdoc/html/markdown/footnotes.rs @@ -23,6 +23,8 @@ struct FootnoteDef<'a> { content: Vec<Event<'a>>, /// The number that appears in the footnote reference and list. id: usize, + /// The number of footnote references. + num_refs: usize, } impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Footnotes<'a, I> { @@ -33,21 +35,25 @@ impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Footnotes<'a, I> { Footnotes { inner: iter, footnotes: FxIndexMap::default(), existing_footnotes, start_id } } - fn get_entry(&mut self, key: &str) -> (&mut Vec<Event<'a>>, usize) { + fn get_entry(&mut self, key: &str) -> (&mut Vec<Event<'a>>, usize, &mut usize) { let new_id = self.footnotes.len() + 1 + self.start_id; let key = key.to_owned(); - let FootnoteDef { content, id } = - self.footnotes.entry(key).or_insert(FootnoteDef { content: Vec::new(), id: new_id }); + let FootnoteDef { content, id, num_refs } = self + .footnotes + .entry(key) + .or_insert(FootnoteDef { content: Vec::new(), id: new_id, num_refs: 0 }); // Don't allow changing the ID of existing entries, but allow changing the contents. - (content, *id) + (content, *id, num_refs) } fn handle_footnote_reference(&mut self, reference: &CowStr<'a>) -> Event<'a> { // When we see a reference (to a footnote we may not know) the definition of, // reserve a number for it, and emit a link to that number. - let (_, id) = self.get_entry(reference); + let (_, id, num_refs) = self.get_entry(reference); + *num_refs += 1; + let fnref_suffix = if *num_refs <= 1 { "".to_owned() } else { format!("-{num_refs}") }; let reference = format!( - "<sup id=\"fnref{0}\"><a href=\"#fn{0}\">{1}</a></sup>", + "<sup id=\"fnref{0}{fnref_suffix}\"><a href=\"#fn{0}\">{1}</a></sup>", id, // Although the ID count is for the whole page, the footnote reference // are local to the item so we make this ID "local" when displayed. @@ -85,7 +91,7 @@ impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Iterator for Footnotes<'a, I> { // When we see a footnote definition, collect the associated content, and store // that for rendering later. let content = self.collect_footnote_def(); - let (entry_content, _) = self.get_entry(&def); + let (entry_content, _, _) = self.get_entry(&def); *entry_content = content; } Some(e) => return Some(e), @@ -113,7 +119,7 @@ fn render_footnotes_defs(mut footnotes: Vec<FootnoteDef<'_>>) -> String { // browser generated for <li> are right. footnotes.sort_by_key(|x| x.id); - for FootnoteDef { mut content, id } in footnotes { + for FootnoteDef { mut content, id, num_refs } in footnotes { write!(ret, "<li id=\"fn{id}\">").unwrap(); let mut is_paragraph = false; if let Some(&Event::End(TagEnd::Paragraph)) = content.last() { @@ -121,7 +127,16 @@ fn render_footnotes_defs(mut footnotes: Vec<FootnoteDef<'_>>) -> String { is_paragraph = true; } html::push_html(&mut ret, content.into_iter()); - write!(ret, " <a href=\"#fnref{id}\">↩</a>").unwrap(); + if num_refs <= 1 { + write!(ret, " <a href=\"#fnref{id}\">↩</a>").unwrap(); + } else { + // There are multiple references to single footnote. Make the first + // back link a single "a" element to make touch region larger. + write!(ret, " <a href=\"#fnref{id}\">↩ <sup>1</sup></a>").unwrap(); + for refid in 2..=num_refs { + write!(ret, " <sup><a href=\"#fnref{id}-{refid}\">{refid}</a></sup>").unwrap(); + } + } if is_paragraph { ret.push_str("</p>"); } diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 10e01b4e262..0011544d16e 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -2060,7 +2060,9 @@ class DocSearch { // Deprecated and unstable items and items with no description this.searchIndexDeprecated.set(crate, new RoaringBitmap(crateCorpus.c)); this.searchIndexEmptyDesc.set(crate, new RoaringBitmap(crateCorpus.e)); - this.searchIndexUnstable.set(crate, new RoaringBitmap(crateCorpus.u)); + if (crateCorpus.u !== undefined && crateCorpus.u !== null) { + this.searchIndexUnstable.set(crate, new RoaringBitmap(crateCorpus.u)); + } let descIndex = 0; /** diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 40191551e4f..bad51d7f5b2 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -13,7 +13,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::intern::Interned; use rustc_errors::{Applicability, Diag, DiagMessage}; use rustc_hir::def::Namespace::*; -use rustc_hir::def::{DefKind, Namespace, PerNS}; +use rustc_hir::def::{DefKind, MacroKinds, Namespace, PerNS}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE}; use rustc_hir::{Mutability, Safety}; use rustc_middle::ty::{Ty, TyCtxt}; @@ -25,7 +25,6 @@ use rustc_resolve::rustdoc::{ use rustc_session::config::CrateType; use rustc_session::lint::Lint; use rustc_span::BytePos; -use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{Ident, Symbol, sym}; use smallvec::{SmallVec, smallvec}; use tracing::{debug, info, instrument, trace}; @@ -115,9 +114,11 @@ impl Res { let prefix = match kind { DefKind::Fn | DefKind::AssocFn => return Suggestion::Function, - DefKind::Macro(MacroKind::Bang) => return Suggestion::Macro, + // FIXME: handle macros with multiple kinds, and attribute/derive macros that aren't + // proc macros + DefKind::Macro(MacroKinds::BANG) => return Suggestion::Macro, - DefKind::Macro(MacroKind::Derive) => "derive", + DefKind::Macro(MacroKinds::DERIVE) => "derive", DefKind::Struct => "struct", DefKind::Enum => "enum", DefKind::Trait => "trait", @@ -881,9 +882,12 @@ fn trait_impls_for<'a>( fn is_derive_trait_collision<T>(ns: &PerNS<Result<Vec<(Res, T)>, ResolutionFailure<'_>>>) -> bool { if let (Ok(type_ns), Ok(macro_ns)) = (&ns.type_ns, &ns.macro_ns) { type_ns.iter().any(|(res, _)| matches!(res, Res::Def(DefKind::Trait, _))) - && macro_ns - .iter() - .any(|(res, _)| matches!(res, Res::Def(DefKind::Macro(MacroKind::Derive), _))) + && macro_ns.iter().any(|(res, _)| { + matches!( + res, + Res::Def(DefKind::Macro(kinds), _) if kinds.contains(MacroKinds::DERIVE) + ) + }) } else { false } @@ -1674,11 +1678,11 @@ impl Disambiguator { let suffixes = [ // If you update this list, please also update the relevant rustdoc book section! - ("!()", DefKind::Macro(MacroKind::Bang)), - ("!{}", DefKind::Macro(MacroKind::Bang)), - ("![]", DefKind::Macro(MacroKind::Bang)), + ("!()", DefKind::Macro(MacroKinds::BANG)), + ("!{}", DefKind::Macro(MacroKinds::BANG)), + ("![]", DefKind::Macro(MacroKinds::BANG)), ("()", DefKind::Fn), - ("!", DefKind::Macro(MacroKind::Bang)), + ("!", DefKind::Macro(MacroKinds::BANG)), ]; if let Some(idx) = link.find('@') { @@ -1697,7 +1701,7 @@ impl Disambiguator { safety: Safety::Safe, }), "function" | "fn" | "method" => Kind(DefKind::Fn), - "derive" => Kind(DefKind::Macro(MacroKind::Derive)), + "derive" => Kind(DefKind::Macro(MacroKinds::DERIVE)), "field" => Kind(DefKind::Field), "variant" => Kind(DefKind::Variant), "type" => NS(Namespace::TypeNS), diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 9058277d72e..b2e4b594375 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -5,7 +5,7 @@ use std::mem; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_hir as hir; -use rustc_hir::def::{DefKind, Res}; +use rustc_hir::def::{DefKind, MacroKinds, Res}; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LocalDefIdSet}; use rustc_hir::intravisit::{Visitor, walk_body, walk_item}; use rustc_hir::{CRATE_HIR_ID, Node}; @@ -13,7 +13,6 @@ use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; use rustc_span::Span; use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE}; -use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{Symbol, kw, sym}; use tracing::debug; @@ -325,7 +324,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { let is_bang_macro = matches!( item, - Node::Item(&hir::Item { kind: hir::ItemKind::Macro(_, _, MacroKind::Bang), .. }) + Node::Item(&hir::Item { kind: hir::ItemKind::Macro(_, _, kinds), .. }) if kinds.contains(MacroKinds::BANG) ); if !self.view_item_stack.insert(res_did) && !is_bang_macro { @@ -406,7 +405,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { // attribute can still be visible. || match item.kind { hir::ItemKind::Impl(..) => true, - hir::ItemKind::Macro(_, _, MacroKind::Bang) => { + hir::ItemKind::Macro(_, _, _) => { self.cx.tcx.has_attr(item.owner_id.def_id, sym::macro_export) } _ => false, diff --git a/src/llvm-project b/src/llvm-project -Subproject d35840afa50d2615835d6a836f1967c57008188 +Subproject 9a1f898064f52269bc94675dcbd620b46d45d17 diff --git a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs index 95e16aae40f..945bb84708f 100644 --- a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs +++ b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs @@ -8,7 +8,6 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir::{EnumDef, FieldDef, Item, ItemKind, OwnerId, QPath, TyKind, Variant, VariantData}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; -use rustc_span::MacroKind; use rustc_span::symbol::Symbol; declare_clippy_lint! { @@ -503,8 +502,8 @@ impl LateLintPass<'_> for ItemNameRepetitions { ); } - let is_macro_rule = matches!(item.kind, ItemKind::Macro(_, _, MacroKind::Bang)); - if both_are_public && item_camel.len() > mod_camel.len() && !is_macro_rule { + let is_macro = matches!(item.kind, ItemKind::Macro(_, _, _)); + if both_are_public && item_camel.len() > mod_camel.len() && !is_macro { let matching = count_match_start(mod_camel, &item_camel); let rmatching = count_match_end(mod_camel, &item_camel); let nchars = mod_camel.chars().count(); diff --git a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs index 3828aff4164..902e8af7ec4 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs @@ -7,7 +7,6 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty; use rustc_session::impl_lint_pass; use rustc_span::def_id::CRATE_DEF_ID; -use rustc_span::hygiene::MacroKind; declare_clippy_lint! { /// ### What it does @@ -89,7 +88,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate { // We ignore macro exports. And `ListStem` uses, which aren't interesting. fn is_ignorable_export<'tcx>(item: &'tcx Item<'tcx>) -> bool { if let ItemKind::Use(path, kind) = item.kind { - let ignore = matches!(path.res.macro_ns, Some(Res::Def(DefKind::Macro(MacroKind::Bang), _))) + let ignore = matches!(path.res.macro_ns, Some(Res::Def(DefKind::Macro(_), _))) || kind == UseKind::ListStem; if ignore { return true; diff --git a/src/tools/clippy/tests/missing-test-files.rs b/src/tools/clippy/tests/missing-test-files.rs index 565dcd73f58..63f960c92fa 100644 --- a/src/tools/clippy/tests/missing-test-files.rs +++ b/src/tools/clippy/tests/missing-test-files.rs @@ -1,6 +1,6 @@ #![warn(rust_2018_idioms, unused_lifetimes)] #![allow(clippy::assertions_on_constants)] -#![feature(path_file_prefix)] +#![cfg_attr(bootstrap, feature(path_file_prefix))] use std::cmp::Ordering; use std::ffi::OsStr; diff --git a/src/tools/clippy/tests/ui/crashes/ice-6255.rs b/src/tools/clippy/tests/ui/crashes/ice-6255.rs index ef1e01f80ef..5f31696c791 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6255.rs +++ b/src/tools/clippy/tests/ui/crashes/ice-6255.rs @@ -9,7 +9,7 @@ macro_rules! define_other_core { } fn main() { - core::panic!(); + core::panic!(); //~ ERROR: `core` is ambiguous } define_other_core!(); diff --git a/src/tools/clippy/tests/ui/crashes/ice-6255.stderr b/src/tools/clippy/tests/ui/crashes/ice-6255.stderr index 738e9d1bd5c..420e4af936f 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6255.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-6255.stderr @@ -9,5 +9,25 @@ LL | define_other_core!(); | = note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 1 previous error +error[E0659]: `core` is ambiguous + --> tests/ui/crashes/ice-6255.rs:12:5 + | +LL | core::panic!(); + | ^^^^ ambiguous name + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution + = note: `core` could refer to a built-in crate +note: `core` could also refer to the crate imported here + --> tests/ui/crashes/ice-6255.rs:6:9 + | +LL | extern crate std as core; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | define_other_core!(); + | -------------------- in this macro invocation + = help: use `crate::core` to refer to this crate unambiguously + = note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0659`. diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index debf67e2741..be4663fffbe 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1695,6 +1695,10 @@ impl<'test> TestCx<'test> { } TestMode::Assembly | TestMode::Codegen => { rustc.arg("-Cdebug-assertions=no"); + // For assembly and codegen tests, we want to use the same order + // of the items of a codegen unit as the source order, so that + // we can compare the output with the source code through filecheck. + rustc.arg("-Zcodegen-source-order"); } TestMode::Crashes => { set_mir_dump_dir(&mut rustc); diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index a8e2151afe6..1b5d9d50996 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -32,6 +32,8 @@ pub enum AccessKind { /// /// A `None` namespace indicates we are looking for a module. fn try_resolve_did(tcx: TyCtxt<'_>, path: &[&str], namespace: Option<Namespace>) -> Option<DefId> { + let _trace = enter_trace_span!("try_resolve_did", ?path); + /// Yield all children of the given item, that have the given name. fn find_children<'tcx: 'a, 'a>( tcx: TyCtxt<'tcx>, diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs index b5b35797fec..6e56fdfe35a 100644 --- a/src/tools/miri/src/shims/time.rs +++ b/src/tools/miri/src/shims/time.rs @@ -322,8 +322,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Since our emulated ticks in `mach_absolute_time` *are* nanoseconds, // no scaling needs to happen. - let (numer, denom) = (1, 1); - this.write_int_fields(&[numer.into(), denom.into()], &info)?; + let (numerator, denom) = (1, 1); + this.write_int_fields(&[numerator.into(), denom.into()], &info)?; interp_ok(Scalar::from_i32(0)) // KERN_SUCCESS } diff --git a/src/tools/run-make-support/src/external_deps/rustc.rs b/src/tools/run-make-support/src/external_deps/rustc.rs index 60d3366ee98..b74b1d5e166 100644 --- a/src/tools/run-make-support/src/external_deps/rustc.rs +++ b/src/tools/run-make-support/src/external_deps/rustc.rs @@ -405,6 +405,12 @@ impl Rustc { }; self } + + /// Make that the generated LLVM IR is in source order. + pub fn codegen_source_order(&mut self) -> &mut Self { + self.cmd.arg("-Zcodegen-source-order"); + self + } } /// Query the sysroot path corresponding `rustc --print=sysroot`. diff --git a/src/tools/unicode-table-generator/src/raw_emitter.rs b/src/tools/unicode-table-generator/src/raw_emitter.rs index e9e0efc4594..03ed9499e26 100644 --- a/src/tools/unicode-table-generator/src/raw_emitter.rs +++ b/src/tools/unicode-table-generator/src/raw_emitter.rs @@ -341,7 +341,7 @@ impl Canonicalized { for &w in unique_words { unique_mapping.entry(w).or_insert_with(|| { canonical_words.push(w); - UniqueMapping::Canonical(canonical_words.len()) + UniqueMapping::Canonical(canonical_words.len() - 1) }); } assert_eq!(canonicalized_words.len() + canonical_words.len(), unique_words.len()); diff --git a/tests/assembly-llvm/asm/aarch64-outline-atomics.rs b/tests/assembly-llvm/asm/aarch64-outline-atomics.rs index 22599c18dcf..1177c1e68ed 100644 --- a/tests/assembly-llvm/asm/aarch64-outline-atomics.rs +++ b/tests/assembly-llvm/asm/aarch64-outline-atomics.rs @@ -8,6 +8,10 @@ use std::sync::atomic::AtomicI32; use std::sync::atomic::Ordering::*; +// Verify config on outline-atomics works (it is always enabled on aarch64-linux). +#[cfg(not(target_feature = "outline-atomics"))] +compile_error!("outline-atomics is not enabled"); + pub fn compare_exchange(a: &AtomicI32) { // On AArch64 LLVM should outline atomic operations. // CHECK: __aarch64_cas4_relax diff --git a/tests/assembly-llvm/targets/targets-elf.rs b/tests/assembly-llvm/targets/targets-elf.rs index ee63dffe9ea..a1d759ede2b 100644 --- a/tests/assembly-llvm/targets/targets-elf.rs +++ b/tests/assembly-llvm/targets/targets-elf.rs @@ -10,6 +10,9 @@ //@ revisions: aarch64_be_unknown_netbsd //@ [aarch64_be_unknown_netbsd] compile-flags: --target aarch64_be-unknown-netbsd //@ [aarch64_be_unknown_netbsd] needs-llvm-components: aarch64 +//@ revisions: aarch64_be_unknown_none_softfloat +//@ [aarch64_be_unknown_none_softfloat] compile-flags: --target aarch64_be-unknown-none-softfloat +//@ [aarch64_be_unknown_none_softfloat] needs-llvm-components: aarch64 //@ revisions: aarch64_kmc_solid_asp3 //@ [aarch64_kmc_solid_asp3] compile-flags: --target aarch64-kmc-solid_asp3 //@ [aarch64_kmc_solid_asp3] needs-llvm-components: aarch64 diff --git a/tests/codegen-llvm/addr-of-mutate.rs b/tests/codegen-llvm/addr-of-mutate.rs index 14bc4b8ab28..71669065289 100644 --- a/tests/codegen-llvm/addr-of-mutate.rs +++ b/tests/codegen-llvm/addr-of-mutate.rs @@ -5,7 +5,7 @@ // Test for the absence of `readonly` on the argument when it is mutated via `&raw const`. // See <https://github.com/rust-lang/rust/issues/111502>. -// CHECK: i8 @foo(ptr noalias{{( nocapture)?}} noundef align 1{{( captures\(none\))?}} dereferenceable(128) %x) +// CHECK: i8 @foo(ptr{{( dead_on_return)?}} noalias{{( nocapture)?}} noundef align 1{{( captures\(none\))?}} dereferenceable(128) %x) #[no_mangle] pub fn foo(x: [u8; 128]) -> u8 { let ptr = core::ptr::addr_of!(x).cast_mut(); @@ -15,7 +15,7 @@ pub fn foo(x: [u8; 128]) -> u8 { x[0] } -// CHECK: i1 @second(ptr noalias{{( nocapture)?}} noundef align {{[0-9]+}}{{( captures\(none\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b) +// CHECK: i1 @second(ptr{{( dead_on_return)?}} noalias{{( nocapture)?}} noundef align {{[0-9]+}}{{( captures\(none\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b) #[no_mangle] pub unsafe fn second(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool { let b_bool_ptr = core::ptr::addr_of!(a_ptr_and_b.1.1).cast_mut(); @@ -24,7 +24,7 @@ pub unsafe fn second(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool { } // If going through a deref (and there are no other mutating accesses), then `readonly` is fine. -// CHECK: i1 @third(ptr noalias{{( nocapture)?}} noundef readonly align {{[0-9]+}}{{( captures\(none\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b) +// CHECK: i1 @third(ptr{{( dead_on_return)?}} noalias{{( nocapture)?}} noundef readonly align {{[0-9]+}}{{( captures\(none\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b) #[no_mangle] pub unsafe fn third(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool { let b_bool_ptr = core::ptr::addr_of!((*a_ptr_and_b.0).1).cast_mut(); diff --git a/tests/codegen-llvm/dead_on_return.rs b/tests/codegen-llvm/dead_on_return.rs new file mode 100644 index 00000000000..3c1940d6ba7 --- /dev/null +++ b/tests/codegen-llvm/dead_on_return.rs @@ -0,0 +1,31 @@ +//@ compile-flags: -C opt-level=3 +//@ min-llvm-version: 21 + +#![crate_type = "lib"] +#![allow(unused_assignments, unused_variables)] + +// Check that the old string is deallocated, but a new one is not initialized. +#[unsafe(no_mangle)] +pub fn test_str_new(mut s: String) { + // CHECK-LABEL: @test_str_new + // CHECK: __rust_dealloc + // CHECK-NOT: store + s = String::new(); +} + +#[unsafe(no_mangle)] +pub fn test_str_take(mut x: String) -> String { + // CHECK-LABEL: @test_str_take + // CHECK-NEXT: {{.*}}: + // CHECK-NEXT: call void @llvm.memcpy + // CHECK-NEXT: ret + core::mem::take(&mut x) +} + +#[unsafe(no_mangle)] +pub fn test_array_store(mut x: [u32; 100]) { + // CHECK-LABEL: @test_array_store + // CHECK-NEXT: {{.*}}: + // CHECK-NEXT: ret + x[0] = 1; +} diff --git a/tests/codegen-llvm/function-arguments.rs b/tests/codegen-llvm/function-arguments.rs index c8cd8526ae5..a3fafbe6f82 100644 --- a/tests/codegen-llvm/function-arguments.rs +++ b/tests/codegen-llvm/function-arguments.rs @@ -134,7 +134,7 @@ pub fn mutable_notunpin_borrow(_: &mut NotUnpin) {} #[no_mangle] pub fn notunpin_borrow(_: &NotUnpin) {} -// CHECK: @indirect_struct(ptr noalias{{( nocapture)?}} noundef readonly align 4{{( captures\(none\))?}} dereferenceable(32) %_1) +// CHECK: @indirect_struct(ptr{{( dead_on_return)?}} noalias{{( nocapture)?}} noundef readonly align 4{{( captures\(none\))?}} dereferenceable(32) %_1) #[no_mangle] pub fn indirect_struct(_: S) {} diff --git a/tests/codegen-llvm/loongarch-abi/loongarch64-lp64d-abi.rs b/tests/codegen-llvm/loongarch-abi/loongarch64-lp64d-abi.rs index 93c8d60930b..4666342a16a 100644 --- a/tests/codegen-llvm/loongarch-abi/loongarch64-lp64d-abi.rs +++ b/tests/codegen-llvm/loongarch-abi/loongarch64-lp64d-abi.rs @@ -256,7 +256,7 @@ pub struct IntDoubleInt { c: i32, } -// CHECK: define void @f_int_double_int_s_arg(ptr noalias{{( nocapture)?}} noundef align 8{{( captures\(none\))?}} dereferenceable(24) %a) +// CHECK: define void @f_int_double_int_s_arg(ptr{{( dead_on_return)?}} noalias{{( nocapture)?}} noundef align 8{{( captures\(none\))?}} dereferenceable(24) %a) #[no_mangle] pub extern "C" fn f_int_double_int_s_arg(a: IntDoubleInt) {} diff --git a/tests/crashes/138510.rs b/tests/crashes/138510.rs deleted file mode 100644 index f429e8bb33b..00000000000 --- a/tests/crashes/138510.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ known-bug: #138510 -fn main() -where - #[repr()] - _: Sized, -{ -} diff --git a/tests/run-make/pgo-branch-weights/rmake.rs b/tests/run-make/pgo-branch-weights/rmake.rs index 1893248e307..e74eabc1875 100644 --- a/tests/run-make/pgo-branch-weights/rmake.rs +++ b/tests/run-make/pgo-branch-weights/rmake.rs @@ -17,15 +17,21 @@ use run_make_support::{llvm_filecheck, llvm_profdata, rfs, run_with_args, rustc} fn main() { let path_prof_data_dir = Path::new("prof_data_dir"); let path_merged_profdata = path_prof_data_dir.join("merged.profdata"); - rustc().input("opaque.rs").run(); + rustc().input("opaque.rs").codegen_source_order().run(); rfs::create_dir_all(&path_prof_data_dir); rustc() .input("interesting.rs") .profile_generate(&path_prof_data_dir) .opt() .codegen_units(1) + .codegen_source_order() + .run(); + rustc() + .input("main.rs") + .profile_generate(&path_prof_data_dir) + .opt() + .codegen_source_order() .run(); - rustc().input("main.rs").profile_generate(&path_prof_data_dir).opt().run(); run_with_args("main", &["aaaaaaaaaaaa2bbbbbbbbbbbb2bbbbbbbbbbbbbbbbcc"]); llvm_profdata().merge().output(&path_merged_profdata).input(path_prof_data_dir).run(); rustc() @@ -34,6 +40,7 @@ fn main() { .opt() .codegen_units(1) .emit("llvm-ir") + .codegen_source_order() .run(); llvm_filecheck() .patterns("filecheck-patterns.txt") diff --git a/tests/run-make/pgo-indirect-call-promotion/rmake.rs b/tests/run-make/pgo-indirect-call-promotion/rmake.rs index ce9754f13b9..ee09141912b 100644 --- a/tests/run-make/pgo-indirect-call-promotion/rmake.rs +++ b/tests/run-make/pgo-indirect-call-promotion/rmake.rs @@ -14,11 +14,17 @@ use run_make_support::{llvm_filecheck, llvm_profdata, rfs, run, rustc}; fn main() { // We don't compile `opaque` with either optimizations or instrumentation. - rustc().input("opaque.rs").run(); + rustc().input("opaque.rs").codegen_source_order().run(); // Compile the test program with instrumentation rfs::create_dir("prof_data_dir"); - rustc().input("interesting.rs").profile_generate("prof_data_dir").opt().codegen_units(1).run(); - rustc().input("main.rs").profile_generate("prof_data_dir").opt().run(); + rustc() + .input("interesting.rs") + .profile_generate("prof_data_dir") + .opt() + .codegen_units(1) + .codegen_source_order() + .run(); + rustc().input("main.rs").profile_generate("prof_data_dir").opt().codegen_source_order().run(); // The argument below generates to the expected branch weights run("main"); llvm_profdata().merge().output("prof_data_dir/merged.profdata").input("prof_data_dir").run(); @@ -28,6 +34,7 @@ fn main() { .opt() .codegen_units(1) .emit("llvm-ir") + .codegen_source_order() .run(); llvm_filecheck() .patterns("filecheck-patterns.txt") diff --git a/tests/run-make/pgo-use/rmake.rs b/tests/run-make/pgo-use/rmake.rs index c09a82353b9..137b0b859a0 100644 --- a/tests/run-make/pgo-use/rmake.rs +++ b/tests/run-make/pgo-use/rmake.rs @@ -22,6 +22,7 @@ fn main() { .opt_level("2") .codegen_units(1) .arg("-Cllvm-args=-disable-preinline") + .codegen_source_order() .profile_generate(cwd()) .input("main.rs") .run(); @@ -40,6 +41,7 @@ fn main() { .arg("-Cllvm-args=-disable-preinline") .profile_use("merged.profdata") .emit("llvm-ir") + .codegen_source_order() .input("main.rs") .run(); // Check that the generate IR contains some things that we expect. diff --git a/tests/rustdoc-ui/check-doc-alias-attr-location.stderr b/tests/rustdoc-ui/check-doc-alias-attr-location.stderr index 9d3ce5e63ef..85c9516236c 100644 --- a/tests/rustdoc-ui/check-doc-alias-attr-location.stderr +++ b/tests/rustdoc-ui/check-doc-alias-attr-location.stderr @@ -4,13 +4,13 @@ error: `#[doc(alias = "...")]` isn't allowed on foreign module LL | #[doc(alias = "foo")] | ^^^^^^^^^^^^^ -error: `#[doc(alias = "...")]` isn't allowed on inherent implementation block +error: `#[doc(alias = "...")]` isn't allowed on implementation block --> $DIR/check-doc-alias-attr-location.rs:10:7 | LL | #[doc(alias = "bar")] | ^^^^^^^^^^^^^ -error: `#[doc(alias = "...")]` isn't allowed on trait implementation block +error: `#[doc(alias = "...")]` isn't allowed on implementation block --> $DIR/check-doc-alias-attr-location.rs:16:7 | LL | #[doc(alias = "foobar")] diff --git a/tests/rustdoc/footnote-reference-ids.rs b/tests/rustdoc/footnote-reference-ids.rs new file mode 100644 index 00000000000..ffa04e1d767 --- /dev/null +++ b/tests/rustdoc/footnote-reference-ids.rs @@ -0,0 +1,23 @@ +// This test ensures that multiple references to a single footnote and +// corresponding back links work as expected. + +#![crate_name = "foo"] + +//@ has 'foo/index.html' +//@ has - '//*[@class="docblock"]/p/sup[@id="fnref1"]/a[@href="#fn1"]' '1' +//@ has - '//*[@class="docblock"]/p/sup[@id="fnref2"]/a[@href="#fn2"]' '2' +//@ has - '//*[@class="docblock"]/p/sup[@id="fnref2-2"]/a[@href="#fn2"]' '2' +//@ has - '//li[@id="fn1"]/p' 'meow' +//@ has - '//li[@id="fn1"]/p/a[@href="#fnref1"]' '↩' +//@ has - '//li[@id="fn2"]/p' 'uwu' +//@ has - '//li[@id="fn2"]/p/a[@href="#fnref2"]/sup' '1' +//@ has - '//li[@id="fn2"]/p/sup/a[@href="#fnref2-2"]' '2' + +//! # Footnote, references and back links +//! +//! Single: [^a]. +//! +//! Double: [^b] [^b]. +//! +//! [^a]: meow +//! [^b]: uwu diff --git a/tests/rustdoc/footnote-reference-in-footnote-def.rs b/tests/rustdoc/footnote-reference-in-footnote-def.rs index db3f9a59ef8..504d0bdb8f7 100644 --- a/tests/rustdoc/footnote-reference-in-footnote-def.rs +++ b/tests/rustdoc/footnote-reference-in-footnote-def.rs @@ -9,7 +9,7 @@ //@ has - '//li[@id="fn1"]/p/sup[@id="fnref2"]/a[@href="#fn2"]' '2' //@ has - '//li[@id="fn1"]//a[@href="#fn2"]' '2' //@ has - '//li[@id="fn2"]/p' 'uwu' -//@ has - '//li[@id="fn2"]/p/sup[@id="fnref1"]/a[@href="#fn1"]' '1' +//@ has - '//li[@id="fn2"]/p/sup[@id="fnref1-2"]/a[@href="#fn1"]' '1' //@ has - '//li[@id="fn2"]//a[@href="#fn1"]' '1' //! # footnote-hell diff --git a/tests/ui/asm/naked-invalid-attr.rs b/tests/ui/asm/naked-invalid-attr.rs index 6ac9cb9e3a9..c9e0949abfb 100644 --- a/tests/ui/asm/naked-invalid-attr.rs +++ b/tests/ui/asm/naked-invalid-attr.rs @@ -1,25 +1,25 @@ // Checks that the #[unsafe(naked)] attribute can be placed on function definitions only. // //@ needs-asm-support -#![unsafe(naked)] //~ ERROR should be applied to a function definition +#![unsafe(naked)] //~ ERROR attribute cannot be used on use std::arch::naked_asm; extern "C" { - #[unsafe(naked)] //~ ERROR should be applied to a function definition + #[unsafe(naked)] //~ ERROR attribute cannot be used on fn f(); } -#[unsafe(naked)] //~ ERROR should be applied to a function definition +#[unsafe(naked)] //~ ERROR attribute cannot be used on #[repr(C)] struct S { - #[unsafe(naked)] //~ ERROR should be applied to a function definition + #[unsafe(naked)] //~ ERROR attribute cannot be used on a: u32, b: u32, } trait Invoke { - #[unsafe(naked)] //~ ERROR should be applied to a function definition + #[unsafe(naked)] //~ ERROR attribute cannot be used on extern "C" fn invoke(&self); } @@ -48,7 +48,7 @@ impl S { } fn main() { - #[unsafe(naked)] //~ ERROR should be applied to a function definition + #[unsafe(naked)] //~ ERROR attribute cannot be used on || {}; } diff --git a/tests/ui/asm/naked-invalid-attr.stderr b/tests/ui/asm/naked-invalid-attr.stderr index 2571c8fa989..936a36cd92e 100644 --- a/tests/ui/asm/naked-invalid-attr.stderr +++ b/tests/ui/asm/naked-invalid-attr.stderr @@ -4,65 +4,62 @@ error[E0433]: failed to resolve: use of unresolved module or unlinked crate `a` LL | #[::a] | ^ use of unresolved module or unlinked crate `a` -error[E0736]: attribute incompatible with `#[unsafe(naked)]` - --> $DIR/naked-invalid-attr.rs:56:3 +error: `#[naked]` attribute cannot be used on crates + --> $DIR/naked-invalid-attr.rs:4:1 | -LL | #[::a] - | ^^^ the `::a` attribute is incompatible with `#[unsafe(naked)]` -... -LL | #[unsafe(naked)] - | ---------------- function marked with `#[unsafe(naked)]` here - -error: attribute should be applied to a function definition - --> $DIR/naked-invalid-attr.rs:13:1 +LL | #![unsafe(naked)] + | ^^^^^^^^^^^^^^^^^ | -LL | #[unsafe(naked)] - | ^^^^^^^^^^^^^^^^ -LL | #[repr(C)] -LL | / struct S { -LL | | #[unsafe(naked)] -LL | | a: u32, -LL | | b: u32, -LL | | } - | |_- not a function definition + = help: `#[naked]` can only be applied to functions -error: attribute should be applied to a function definition - --> $DIR/naked-invalid-attr.rs:16:5 +error: `#[naked]` attribute cannot be used on foreign functions + --> $DIR/naked-invalid-attr.rs:9:5 | LL | #[unsafe(naked)] | ^^^^^^^^^^^^^^^^ -LL | a: u32, - | ------ not a function definition + | + = help: `#[naked]` can be applied to methods, functions -error: attribute should be applied to a function definition - --> $DIR/naked-invalid-attr.rs:51:5 +error: `#[naked]` attribute cannot be used on structs + --> $DIR/naked-invalid-attr.rs:13:1 + | +LL | #[unsafe(naked)] + | ^^^^^^^^^^^^^^^^ + | + = help: `#[naked]` can only be applied to functions + +error: `#[naked]` attribute cannot be used on struct fields + --> $DIR/naked-invalid-attr.rs:16:5 | LL | #[unsafe(naked)] | ^^^^^^^^^^^^^^^^ -LL | || {}; - | ----- not a function definition + | + = help: `#[naked]` can only be applied to functions -error: attribute should be applied to a function definition +error: `#[naked]` attribute cannot be used on required trait methods --> $DIR/naked-invalid-attr.rs:22:5 | LL | #[unsafe(naked)] | ^^^^^^^^^^^^^^^^ -LL | extern "C" fn invoke(&self); - | ---------------------------- not a function definition + | + = help: `#[naked]` can be applied to functions, inherent methods, provided trait methods, trait methods in impl blocks -error: attribute should be applied to a function definition - --> $DIR/naked-invalid-attr.rs:9:5 +error: `#[naked]` attribute cannot be used on closures + --> $DIR/naked-invalid-attr.rs:51:5 | LL | #[unsafe(naked)] | ^^^^^^^^^^^^^^^^ -LL | fn f(); - | ------- not a function definition + | + = help: `#[naked]` can be applied to methods, functions -error: attribute should be applied to a function definition - --> $DIR/naked-invalid-attr.rs:4:1 +error[E0736]: attribute incompatible with `#[unsafe(naked)]` + --> $DIR/naked-invalid-attr.rs:56:3 | -LL | #![unsafe(naked)] - | ^^^^^^^^^^^^^^^^^ cannot be applied to crates +LL | #[::a] + | ^^^ the `::a` attribute is incompatible with `#[unsafe(naked)]` +... +LL | #[unsafe(naked)] + | ---------------- function marked with `#[unsafe(naked)]` here error: aborting due to 8 previous errors diff --git a/tests/ui/attributes/attrs-on-params.rs b/tests/ui/attributes/attrs-on-params.rs index 158a4500bde..c8e9810327c 100644 --- a/tests/ui/attributes/attrs-on-params.rs +++ b/tests/ui/attributes/attrs-on-params.rs @@ -1,7 +1,7 @@ // This checks that incorrect params on function parameters are caught fn function(#[inline] param: u32) { - //~^ ERROR attribute should be applied to function or closure + //~^ ERROR attribute cannot be used on //~| ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes } diff --git a/tests/ui/attributes/attrs-on-params.stderr b/tests/ui/attributes/attrs-on-params.stderr index 306e862cb58..91f87a954c5 100644 --- a/tests/ui/attributes/attrs-on-params.stderr +++ b/tests/ui/attributes/attrs-on-params.stderr @@ -4,14 +4,13 @@ error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed LL | fn function(#[inline] param: u32) { | ^^^^^^^^^ -error[E0518]: attribute should be applied to function or closure +error: `#[inline]` attribute cannot be used on function params --> $DIR/attrs-on-params.rs:3:13 | LL | fn function(#[inline] param: u32) { - | ^^^^^^^^^----------- - | | - | not a function or closure + | ^^^^^^^^^ + | + = help: `#[inline]` can only be applied to functions error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0518`. diff --git a/tests/ui/attributes/auxiliary/derive_macro_with_helper.rs b/tests/ui/attributes/auxiliary/derive_macro_with_helper.rs new file mode 100644 index 00000000000..128af50ce36 --- /dev/null +++ b/tests/ui/attributes/auxiliary/derive_macro_with_helper.rs @@ -0,0 +1,8 @@ +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Derive, attributes(arg))] +pub fn derive(_: TokenStream) -> TokenStream { + TokenStream::new() +} diff --git a/tests/ui/attributes/cold-attribute-application-54044.rs b/tests/ui/attributes/cold-attribute-application-54044.rs index 2e644b91c07..cf027ac02b0 100644 --- a/tests/ui/attributes/cold-attribute-application-54044.rs +++ b/tests/ui/attributes/cold-attribute-application-54044.rs @@ -2,13 +2,13 @@ #![deny(unused_attributes)] //~ NOTE lint level is defined here #[cold] -//~^ ERROR attribute should be applied to a function -//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -struct Foo; //~ NOTE not a function +//~^ ERROR attribute cannot be used on +//~| WARN previously accepted +struct Foo; fn main() { #[cold] - //~^ ERROR attribute should be applied to a function - //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - 5; //~ NOTE not a function + //~^ ERROR attribute cannot be used on + //~| WARN previously accepted + 5; } diff --git a/tests/ui/attributes/cold-attribute-application-54044.stderr b/tests/ui/attributes/cold-attribute-application-54044.stderr index efdf5e0de52..367686f02cb 100644 --- a/tests/ui/attributes/cold-attribute-application-54044.stderr +++ b/tests/ui/attributes/cold-attribute-application-54044.stderr @@ -1,29 +1,25 @@ -error: attribute should be applied to a function definition +error: `#[cold]` attribute cannot be used on structs --> $DIR/cold-attribute-application-54044.rs:4:1 | LL | #[cold] | ^^^^^^^ -... -LL | struct Foo; - | ----------- not a function definition | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[cold]` can only be applied to functions note: the lint level is defined here --> $DIR/cold-attribute-application-54044.rs:2:9 | LL | #![deny(unused_attributes)] | ^^^^^^^^^^^^^^^^^ -error: attribute should be applied to a function definition +error: `#[cold]` attribute cannot be used on expressions --> $DIR/cold-attribute-application-54044.rs:10:5 | LL | #[cold] | ^^^^^^^ -... -LL | 5; - | - not a function definition | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[cold]` can only be applied to functions error: aborting due to 2 previous errors diff --git a/tests/ui/attributes/empty-repr.rs b/tests/ui/attributes/empty-repr.rs new file mode 100644 index 00000000000..e6ba1baf031 --- /dev/null +++ b/tests/ui/attributes/empty-repr.rs @@ -0,0 +1,14 @@ +// Regression test for https://github.com/rust-lang/rust/issues/138510 + +#![feature(where_clause_attrs)] +#![deny(unused_attributes)] + +fn main() { +} + +fn test() where +#[repr()] +//~^ ERROR unused attribute +(): Sized { + +} diff --git a/tests/ui/attributes/empty-repr.stderr b/tests/ui/attributes/empty-repr.stderr new file mode 100644 index 00000000000..92901fa170c --- /dev/null +++ b/tests/ui/attributes/empty-repr.stderr @@ -0,0 +1,14 @@ +error: unused attribute + --> $DIR/empty-repr.rs:10:1 + | +LL | #[repr()] + | ^^^^^^^^^ help: remove this attribute + | +note: the lint level is defined here + --> $DIR/empty-repr.rs:4:9 + | +LL | #![deny(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/attributes/helper-attr-interpolated-non-lit-arg.rs b/tests/ui/attributes/helper-attr-interpolated-non-lit-arg.rs new file mode 100644 index 00000000000..17c9ad1bd48 --- /dev/null +++ b/tests/ui/attributes/helper-attr-interpolated-non-lit-arg.rs @@ -0,0 +1,20 @@ +// Regression test for <https://github.com/rust-lang/rust/issues/140612>. +//@ proc-macro: derive_macro_with_helper.rs +//@ edition: 2018 +//@ check-pass + +macro_rules! expand { + ($text:expr) => { + #[derive(derive_macro_with_helper::Derive)] + // This inert attr is completely valid because it follows the grammar + // `#` `[` SimplePath DelimitedTokenStream `]`. + // However, we used to incorrectly delay a bug here and ICE when trying to parse `$text` as + // the inside of a "meta item list" which may only begin with literals or paths. + #[arg($text)] + pub struct Foo; + }; +} + +expand!(1 + 1); + +fn main() {} diff --git a/tests/ui/attributes/inline-attribute-enum-variant-error.rs b/tests/ui/attributes/inline-attribute-enum-variant-error.rs index 305b285d2a4..fd2cd49be16 100644 --- a/tests/ui/attributes/inline-attribute-enum-variant-error.rs +++ b/tests/ui/attributes/inline-attribute-enum-variant-error.rs @@ -2,7 +2,7 @@ enum Foo { #[inline] - //~^ ERROR attribute should be applied + //~^ ERROR attribute cannot be used on Variant, } diff --git a/tests/ui/attributes/inline-attribute-enum-variant-error.stderr b/tests/ui/attributes/inline-attribute-enum-variant-error.stderr index a4564d8f722..03954388c2e 100644 --- a/tests/ui/attributes/inline-attribute-enum-variant-error.stderr +++ b/tests/ui/attributes/inline-attribute-enum-variant-error.stderr @@ -1,12 +1,10 @@ -error[E0518]: attribute should be applied to function or closure +error: `#[inline]` attribute cannot be used on enum variants --> $DIR/inline-attribute-enum-variant-error.rs:4:5 | LL | #[inline] | ^^^^^^^^^ -LL | -LL | Variant, - | ------- not a function or closure + | + = help: `#[inline]` can only be applied to functions error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0518`. diff --git a/tests/ui/attributes/inline/attr-usage-inline.rs b/tests/ui/attributes/inline/attr-usage-inline.rs index d8ca0fce163..8217b9834ff 100644 --- a/tests/ui/attributes/inline/attr-usage-inline.rs +++ b/tests/ui/attributes/inline/attr-usage-inline.rs @@ -4,7 +4,7 @@ #[inline] fn f() {} -#[inline] //~ ERROR: attribute should be applied to function or closure +#[inline] //~ ERROR: attribute cannot be used on struct S; struct I { diff --git a/tests/ui/attributes/inline/attr-usage-inline.stderr b/tests/ui/attributes/inline/attr-usage-inline.stderr index 2123438032c..9fca17d90ca 100644 --- a/tests/ui/attributes/inline/attr-usage-inline.stderr +++ b/tests/ui/attributes/inline/attr-usage-inline.stderr @@ -1,10 +1,10 @@ -error[E0518]: attribute should be applied to function or closure +error: `#[inline]` attribute cannot be used on structs --> $DIR/attr-usage-inline.rs:7:1 | LL | #[inline] | ^^^^^^^^^ -LL | struct S; - | --------- not a function or closure + | + = help: `#[inline]` can only be applied to functions error[E0518]: attribute should be applied to function or closure --> $DIR/attr-usage-inline.rs:21:1 diff --git a/tests/ui/attributes/issue-105594-invalid-attr-validation.rs b/tests/ui/attributes/issue-105594-invalid-attr-validation.rs index cb196471fd7..f9e01cd1507 100644 --- a/tests/ui/attributes/issue-105594-invalid-attr-validation.rs +++ b/tests/ui/attributes/issue-105594-invalid-attr-validation.rs @@ -3,5 +3,5 @@ fn main() {} -#[track_caller] //~ ERROR attribute should be applied to a function +#[track_caller] //~ ERROR attribute cannot be used on static _A: () = (); diff --git a/tests/ui/attributes/issue-105594-invalid-attr-validation.stderr b/tests/ui/attributes/issue-105594-invalid-attr-validation.stderr index 1248967c47b..337d3808d28 100644 --- a/tests/ui/attributes/issue-105594-invalid-attr-validation.stderr +++ b/tests/ui/attributes/issue-105594-invalid-attr-validation.stderr @@ -1,11 +1,10 @@ -error[E0739]: attribute should be applied to a function definition +error: `#[track_caller]` attribute cannot be used on statics --> $DIR/issue-105594-invalid-attr-validation.rs:6:1 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ -LL | static _A: () = (); - | ------------------- not a function definition + | + = help: `#[track_caller]` can only be applied to functions error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0739`. diff --git a/tests/ui/attributes/linkage.rs b/tests/ui/attributes/linkage.rs index 0d5ce699fa8..932bfa88fc5 100644 --- a/tests/ui/attributes/linkage.rs +++ b/tests/ui/attributes/linkage.rs @@ -3,16 +3,16 @@ #![deny(unused_attributes)] #![allow(dead_code)] -#[linkage = "weak"] //~ ERROR attribute should be applied to a function or static +#[linkage = "weak"] //~ ERROR attribute cannot be used on type InvalidTy = (); -#[linkage = "weak"] //~ ERROR attribute should be applied to a function or static +#[linkage = "weak"] //~ ERROR attribute cannot be used on mod invalid_module {} -#[linkage = "weak"] //~ ERROR attribute should be applied to a function or static +#[linkage = "weak"] //~ ERROR attribute cannot be used on struct F; -#[linkage = "weak"] //~ ERROR attribute should be applied to a function or static +#[linkage = "weak"] //~ ERROR attribute cannot be used on impl F { #[linkage = "weak"] fn valid(&self) {} @@ -24,7 +24,7 @@ fn f() { { 1 }; - //~^^^^ ERROR attribute should be applied to a function or static + //~^^^^ ERROR attribute cannot be used on } extern "C" { @@ -38,5 +38,5 @@ extern "C" { fn main() { let _ = #[linkage = "weak"] (|| 1); - //~^^ ERROR attribute should be applied to a function or static + //~^^ ERROR attribute cannot be used on } diff --git a/tests/ui/attributes/linkage.stderr b/tests/ui/attributes/linkage.stderr index d5595529f40..2e7ff0e7936 100644 --- a/tests/ui/attributes/linkage.stderr +++ b/tests/ui/attributes/linkage.stderr @@ -1,55 +1,50 @@ -error: attribute should be applied to a function or static +error: `#[linkage]` attribute cannot be used on type aliases --> $DIR/linkage.rs:6:1 | LL | #[linkage = "weak"] | ^^^^^^^^^^^^^^^^^^^ -LL | type InvalidTy = (); - | -------------------- not a function definition or static + | + = help: `#[linkage]` can be applied to functions, statics, foreign statics -error: attribute should be applied to a function or static +error: `#[linkage]` attribute cannot be used on modules --> $DIR/linkage.rs:9:1 | LL | #[linkage = "weak"] | ^^^^^^^^^^^^^^^^^^^ -LL | mod invalid_module {} - | --------------------- not a function definition or static + | + = help: `#[linkage]` can be applied to functions, statics, foreign statics -error: attribute should be applied to a function or static +error: `#[linkage]` attribute cannot be used on structs --> $DIR/linkage.rs:12:1 | LL | #[linkage = "weak"] | ^^^^^^^^^^^^^^^^^^^ -LL | struct F; - | --------- not a function definition or static + | + = help: `#[linkage]` can be applied to functions, statics, foreign statics -error: attribute should be applied to a function or static +error: `#[linkage]` attribute cannot be used on inherent impl blocks --> $DIR/linkage.rs:15:1 | -LL | #[linkage = "weak"] - | ^^^^^^^^^^^^^^^^^^^ -LL | / impl F { -LL | | #[linkage = "weak"] -LL | | fn valid(&self) {} -LL | | } - | |_- not a function definition or static +LL | #[linkage = "weak"] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: `#[linkage]` can be applied to functions, statics, foreign statics -error: attribute should be applied to a function or static +error: `#[linkage]` attribute cannot be used on expressions --> $DIR/linkage.rs:23:5 | -LL | #[linkage = "weak"] - | ^^^^^^^^^^^^^^^^^^^ -LL | / { -LL | | 1 -LL | | }; - | |_____- not a function definition or static +LL | #[linkage = "weak"] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: `#[linkage]` can be applied to functions, statics, foreign statics -error: attribute should be applied to a function or static +error: `#[linkage]` attribute cannot be used on closures --> $DIR/linkage.rs:39:13 | LL | let _ = #[linkage = "weak"] | ^^^^^^^^^^^^^^^^^^^ -LL | (|| 1); - | ------ not a function definition or static + | + = help: `#[linkage]` can be applied to methods, functions, statics, foreign statics, foreign functions error: aborting due to 6 previous errors diff --git a/tests/ui/attributes/lint_on_root.rs b/tests/ui/attributes/lint_on_root.rs index 9029da7dc97..bafdb46883f 100644 --- a/tests/ui/attributes/lint_on_root.rs +++ b/tests/ui/attributes/lint_on_root.rs @@ -3,5 +3,6 @@ #![inline = ""] //~^ ERROR: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]` [ill_formed_attribute_input] //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +//~| ERROR attribute cannot be used on fn main() {} diff --git a/tests/ui/attributes/lint_on_root.stderr b/tests/ui/attributes/lint_on_root.stderr index 91b72730530..9d8d1495c1b 100644 --- a/tests/ui/attributes/lint_on_root.stderr +++ b/tests/ui/attributes/lint_on_root.stderr @@ -1,3 +1,11 @@ +error: `#[inline]` attribute cannot be used on crates + --> $DIR/lint_on_root.rs:3:1 + | +LL | #![inline = ""] + | ^^^^^^^^^^^^^^^ + | + = help: `#[inline]` can only be applied to functions + error: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]` --> $DIR/lint_on_root.rs:3:1 | @@ -8,7 +16,7 @@ LL | #![inline = ""] = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> = note: `#[deny(ill_formed_attribute_input)]` on by default -error: aborting due to 1 previous error +error: aborting due to 2 previous errors Future incompatibility report: Future breakage diagnostic: error: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]` diff --git a/tests/ui/attributes/malformed-attrs.rs b/tests/ui/attributes/malformed-attrs.rs index 3261b29fe7e..3293f75fba9 100644 --- a/tests/ui/attributes/malformed-attrs.rs +++ b/tests/ui/attributes/malformed-attrs.rs @@ -35,6 +35,7 @@ //~^ ERROR `allow_internal_unstable` expects a list of feature names #[rustc_confusables] //~^ ERROR malformed +//~| ERROR attribute cannot be used on #[deprecated = 5] //~^ ERROR malformed #[doc] @@ -42,9 +43,10 @@ //~| WARN this was previously accepted by the compiler #[rustc_macro_transparency] //~^ ERROR malformed +//~| ERROR attribute cannot be used on #[repr] //~^ ERROR malformed -//~| ERROR is not supported on function items +//~| ERROR is not supported on functions #[rustc_as_ptr = 5] //~^ ERROR malformed #[inline = 5] @@ -68,6 +70,7 @@ //~^ ERROR malformed #[used()] //~^ ERROR malformed +//~| ERROR attribute cannot be used on #[crate_name] //~^ ERROR malformed #[doc] diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr index 705050e9a7d..9c31765149b 100644 --- a/tests/ui/attributes/malformed-attrs.stderr +++ b/tests/ui/attributes/malformed-attrs.stderr @@ -1,5 +1,5 @@ error[E0539]: malformed `cfg` attribute input - --> $DIR/malformed-attrs.rs:99:1 + --> $DIR/malformed-attrs.rs:102:1 | LL | #[cfg] | ^^^^^^ @@ -10,7 +10,7 @@ LL | #[cfg] = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute> error: malformed `cfg_attr` attribute input - --> $DIR/malformed-attrs.rs:101:1 + --> $DIR/malformed-attrs.rs:104:1 | LL | #[cfg_attr] | ^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | #[cfg_attr(condition, attribute, other_attribute, ...)] | ++++++++++++++++++++++++++++++++++++++++++++ error[E0463]: can't find crate for `wloop` - --> $DIR/malformed-attrs.rs:208:1 + --> $DIR/malformed-attrs.rs:211:1 | LL | extern crate wloop; | ^^^^^^^^^^^^^^^^^^^ can't find crate @@ -42,7 +42,7 @@ LL | #![windows_subsystem = "windows"] | +++++++++++ error: malformed `crate_name` attribute input - --> $DIR/malformed-attrs.rs:71:1 + --> $DIR/malformed-attrs.rs:74:1 | LL | #[crate_name] | ^^^^^^^^^^^^^ help: must be of the form: `#[crate_name = "name"]` @@ -50,13 +50,13 @@ LL | #[crate_name] = note: for more information, visit <https://doc.rust-lang.org/reference/crates-and-source-files.html#the-crate_name-attribute> error: malformed `no_sanitize` attribute input - --> $DIR/malformed-attrs.rs:89:1 + --> $DIR/malformed-attrs.rs:92:1 | LL | #[no_sanitize] | ^^^^^^^^^^^^^^ help: must be of the form: `#[no_sanitize(address, kcfi, memory, thread)]` error: malformed `instruction_set` attribute input - --> $DIR/malformed-attrs.rs:103:1 + --> $DIR/malformed-attrs.rs:106:1 | LL | #[instruction_set] | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[instruction_set(set)]` @@ -64,13 +64,13 @@ LL | #[instruction_set] = note: for more information, visit <https://doc.rust-lang.org/reference/attributes/codegen.html#the-instruction_set-attribute> error: malformed `patchable_function_entry` attribute input - --> $DIR/malformed-attrs.rs:105:1 + --> $DIR/malformed-attrs.rs:108:1 | LL | #[patchable_function_entry] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[patchable_function_entry(prefix_nops = m, entry_nops = n)]` error: malformed `must_not_suspend` attribute input - --> $DIR/malformed-attrs.rs:129:1 + --> $DIR/malformed-attrs.rs:132:1 | LL | #[must_not_suspend()] | ^^^^^^^^^^^^^^^^^^^^^ @@ -85,32 +85,13 @@ LL + #[must_not_suspend] | error: malformed `cfi_encoding` attribute input - --> $DIR/malformed-attrs.rs:131:1 + --> $DIR/malformed-attrs.rs:134:1 | LL | #[cfi_encoding] | ^^^^^^^^^^^^^^^ help: must be of the form: `#[cfi_encoding = "encoding"]` -error: malformed `linkage` attribute input - --> $DIR/malformed-attrs.rs:170:5 - | -LL | #[linkage] - | ^^^^^^^^^^ - | - = note: for more information, visit <https://doc.rust-lang.org/reference/linkage.html> -help: the following are the possible correct uses - | -LL | #[linkage = "available_externally"] - | ++++++++++++++++++++++++ -LL | #[linkage = "common"] - | ++++++++++ -LL | #[linkage = "extern_weak"] - | +++++++++++++++ -LL | #[linkage = "external"] - | ++++++++++++ - = and 5 other candidates - error: malformed `allow` attribute input - --> $DIR/malformed-attrs.rs:175:1 + --> $DIR/malformed-attrs.rs:178:1 | LL | #[allow] | ^^^^^^^^ @@ -126,7 +107,7 @@ LL | #[allow(lint1, lint2, lint3, reason = "...")] | +++++++++++++++++++++++++++++++++++++ error: malformed `expect` attribute input - --> $DIR/malformed-attrs.rs:177:1 + --> $DIR/malformed-attrs.rs:180:1 | LL | #[expect] | ^^^^^^^^^ @@ -142,7 +123,7 @@ LL | #[expect(lint1, lint2, lint3, reason = "...")] | +++++++++++++++++++++++++++++++++++++ error: malformed `warn` attribute input - --> $DIR/malformed-attrs.rs:179:1 + --> $DIR/malformed-attrs.rs:182:1 | LL | #[warn] | ^^^^^^^ @@ -158,7 +139,7 @@ LL | #[warn(lint1, lint2, lint3, reason = "...")] | +++++++++++++++++++++++++++++++++++++ error: malformed `deny` attribute input - --> $DIR/malformed-attrs.rs:181:1 + --> $DIR/malformed-attrs.rs:184:1 | LL | #[deny] | ^^^^^^^ @@ -174,7 +155,7 @@ LL | #[deny(lint1, lint2, lint3, reason = "...")] | +++++++++++++++++++++++++++++++++++++ error: malformed `forbid` attribute input - --> $DIR/malformed-attrs.rs:183:1 + --> $DIR/malformed-attrs.rs:186:1 | LL | #[forbid] | ^^^^^^^^^ @@ -190,7 +171,7 @@ LL | #[forbid(lint1, lint2, lint3, reason = "...")] | +++++++++++++++++++++++++++++++++++++ error: malformed `debugger_visualizer` attribute input - --> $DIR/malformed-attrs.rs:185:1 + --> $DIR/malformed-attrs.rs:188:1 | LL | #[debugger_visualizer] | ^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[debugger_visualizer(natvis_file = "...", gdb_script_file = "...")]` @@ -198,13 +179,13 @@ LL | #[debugger_visualizer] = note: for more information, visit <https://doc.rust-lang.org/reference/attributes/debugger.html#the-debugger_visualizer-attribute> error: malformed `thread_local` attribute input - --> $DIR/malformed-attrs.rs:200:1 + --> $DIR/malformed-attrs.rs:203:1 | LL | #[thread_local()] | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[thread_local]` error: malformed `no_link` attribute input - --> $DIR/malformed-attrs.rs:204:1 + --> $DIR/malformed-attrs.rs:207:1 | LL | #[no_link()] | ^^^^^^^^^^^^ help: must be of the form: `#[no_link]` @@ -212,7 +193,7 @@ LL | #[no_link()] = note: for more information, visit <https://doc.rust-lang.org/reference/items/extern-crates.html#the-no_link-attribute> error: malformed `macro_export` attribute input - --> $DIR/malformed-attrs.rs:211:1 + --> $DIR/malformed-attrs.rs:214:1 | LL | #[macro_export = 18] | ^^^^^^^^^^^^^^^^^^^^ @@ -228,25 +209,25 @@ LL + #[macro_export] | error: the `#[proc_macro]` attribute is only usable with crates of the `proc-macro` crate type - --> $DIR/malformed-attrs.rs:96:1 + --> $DIR/malformed-attrs.rs:99:1 | LL | #[proc_macro = 18] | ^^^^^^^^^^^^^^^^^^ error: the `#[proc_macro_attribute]` attribute is only usable with crates of the `proc-macro` crate type - --> $DIR/malformed-attrs.rs:113:1 + --> $DIR/malformed-attrs.rs:116:1 | LL | #[proc_macro_attribute = 19] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type - --> $DIR/malformed-attrs.rs:120:1 + --> $DIR/malformed-attrs.rs:123:1 | LL | #[proc_macro_derive] | ^^^^^^^^^^^^^^^^^^^^ error[E0658]: allow_internal_unsafe side-steps the unsafe_code lint - --> $DIR/malformed-attrs.rs:213:1 + --> $DIR/malformed-attrs.rs:216:1 | LL | #[allow_internal_unsafe = 1] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -255,7 +236,7 @@ LL | #[allow_internal_unsafe = 1] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: valid forms for the attribute are `#[doc(hidden)]`, `#[doc(inline)]`, and `#[doc = "string"]` - --> $DIR/malformed-attrs.rs:40:1 + --> $DIR/malformed-attrs.rs:41:1 | LL | #[doc] | ^^^^^^ @@ -266,7 +247,7 @@ LL | #[doc] = note: `#[deny(ill_formed_attribute_input)]` on by default error: valid forms for the attribute are `#[doc(hidden)]`, `#[doc(inline)]`, and `#[doc = "string"]` - --> $DIR/malformed-attrs.rs:73:1 + --> $DIR/malformed-attrs.rs:76:1 | LL | #[doc] | ^^^^^^ @@ -276,7 +257,7 @@ LL | #[doc] = note: for more information, visit <https://doc.rust-lang.org/rustdoc/write-documentation/the-doc-attribute.html> error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]` - --> $DIR/malformed-attrs.rs:80:1 + --> $DIR/malformed-attrs.rs:83:1 | LL | #[link] | ^^^^^^^ @@ -286,7 +267,7 @@ LL | #[link] = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> error: invalid argument - --> $DIR/malformed-attrs.rs:185:1 + --> $DIR/malformed-attrs.rs:188:1 | LL | #[debugger_visualizer] | ^^^^^^^^^^^^^^^^^^^^^^ @@ -322,8 +303,16 @@ LL | #[rustc_confusables] | expected this to be a list | help: must be of the form: `#[rustc_confusables("name1", "name2", ...)]` +error: `#[rustc_confusables]` attribute cannot be used on functions + --> $DIR/malformed-attrs.rs:36:1 + | +LL | #[rustc_confusables] + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_confusables]` can only be applied to inherent methods + error[E0539]: malformed `deprecated` attribute input - --> $DIR/malformed-attrs.rs:38:1 + --> $DIR/malformed-attrs.rs:39:1 | LL | #[deprecated = 5] | ^^^^^^^^^^^^^^^-^ @@ -347,7 +336,7 @@ LL + #[deprecated(since = "version", note = "reason")] = and 1 other candidate error[E0539]: malformed `rustc_macro_transparency` attribute input - --> $DIR/malformed-attrs.rs:43:1 + --> $DIR/malformed-attrs.rs:44:1 | LL | #[rustc_macro_transparency] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -361,8 +350,16 @@ LL | #[rustc_macro_transparency = "semitransparent"] LL | #[rustc_macro_transparency = "transparent"] | +++++++++++++++ +error: `#[rustc_macro_transparency]` attribute cannot be used on functions + --> $DIR/malformed-attrs.rs:44:1 + | +LL | #[rustc_macro_transparency] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_macro_transparency]` can only be applied to macro defs + error[E0539]: malformed `repr` attribute input - --> $DIR/malformed-attrs.rs:45:1 + --> $DIR/malformed-attrs.rs:47:1 | LL | #[repr] | ^^^^^^^ expected this to be a list @@ -381,7 +378,7 @@ LL | #[repr(align(...))] = and 2 other candidates error[E0565]: malformed `rustc_as_ptr` attribute input - --> $DIR/malformed-attrs.rs:48:1 + --> $DIR/malformed-attrs.rs:50:1 | LL | #[rustc_as_ptr = 5] | ^^^^^^^^^^^^^^^---^ @@ -390,7 +387,7 @@ LL | #[rustc_as_ptr = 5] | help: must be of the form: `#[rustc_as_ptr]` error[E0539]: malformed `rustc_align` attribute input - --> $DIR/malformed-attrs.rs:53:1 + --> $DIR/malformed-attrs.rs:55:1 | LL | #[rustc_align] | ^^^^^^^^^^^^^^ @@ -399,7 +396,7 @@ LL | #[rustc_align] | help: must be of the form: `#[rustc_align(<alignment in bytes>)]` error[E0539]: malformed `optimize` attribute input - --> $DIR/malformed-attrs.rs:55:1 + --> $DIR/malformed-attrs.rs:57:1 | LL | #[optimize] | ^^^^^^^^^^^ expected this to be a list @@ -414,7 +411,7 @@ LL | #[optimize(speed)] | +++++++ error[E0565]: malformed `cold` attribute input - --> $DIR/malformed-attrs.rs:57:1 + --> $DIR/malformed-attrs.rs:59:1 | LL | #[cold = 1] | ^^^^^^^---^ @@ -423,13 +420,13 @@ LL | #[cold = 1] | help: must be of the form: `#[cold]` error: valid forms for the attribute are `#[must_use = "reason"]` and `#[must_use]` - --> $DIR/malformed-attrs.rs:59:1 + --> $DIR/malformed-attrs.rs:61:1 | LL | #[must_use()] | ^^^^^^^^^^^^^ error[E0565]: malformed `no_mangle` attribute input - --> $DIR/malformed-attrs.rs:61:1 + --> $DIR/malformed-attrs.rs:63:1 | LL | #[no_mangle = 1] | ^^^^^^^^^^^^---^ @@ -438,7 +435,7 @@ LL | #[no_mangle = 1] | help: must be of the form: `#[no_mangle]` error[E0565]: malformed `naked` attribute input - --> $DIR/malformed-attrs.rs:63:1 + --> $DIR/malformed-attrs.rs:65:1 | LL | #[unsafe(naked())] | ^^^^^^^^^^^^^^--^^ @@ -447,7 +444,7 @@ LL | #[unsafe(naked())] | help: must be of the form: `#[naked]` error[E0565]: malformed `track_caller` attribute input - --> $DIR/malformed-attrs.rs:65:1 + --> $DIR/malformed-attrs.rs:67:1 | LL | #[track_caller()] | ^^^^^^^^^^^^^^--^ @@ -456,13 +453,13 @@ LL | #[track_caller()] | help: must be of the form: `#[track_caller]` error[E0539]: malformed `export_name` attribute input - --> $DIR/malformed-attrs.rs:67:1 + --> $DIR/malformed-attrs.rs:69:1 | LL | #[export_name()] | ^^^^^^^^^^^^^^^^ help: must be of the form: `#[export_name = "name"]` error[E0805]: malformed `used` attribute input - --> $DIR/malformed-attrs.rs:69:1 + --> $DIR/malformed-attrs.rs:71:1 | LL | #[used()] | ^^^^^^--^ @@ -479,8 +476,16 @@ LL - #[used()] LL + #[used] | +error: `#[used]` attribute cannot be used on functions + --> $DIR/malformed-attrs.rs:71:1 + | +LL | #[used()] + | ^^^^^^^^^ + | + = help: `#[used]` can only be applied to statics + error[E0539]: malformed `target_feature` attribute input - --> $DIR/malformed-attrs.rs:76:1 + --> $DIR/malformed-attrs.rs:79:1 | LL | #[target_feature] | ^^^^^^^^^^^^^^^^^ @@ -489,7 +494,7 @@ LL | #[target_feature] | help: must be of the form: `#[target_feature(enable = "feat1, feat2")]` error[E0565]: malformed `export_stable` attribute input - --> $DIR/malformed-attrs.rs:78:1 + --> $DIR/malformed-attrs.rs:81:1 | LL | #[export_stable = 1] | ^^^^^^^^^^^^^^^^---^ @@ -498,7 +503,7 @@ LL | #[export_stable = 1] | help: must be of the form: `#[export_stable]` error[E0539]: malformed `link_name` attribute input - --> $DIR/malformed-attrs.rs:83:1 + --> $DIR/malformed-attrs.rs:86:1 | LL | #[link_name] | ^^^^^^^^^^^^ help: must be of the form: `#[link_name = "name"]` @@ -506,7 +511,7 @@ LL | #[link_name] = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_name-attribute> error[E0539]: malformed `link_section` attribute input - --> $DIR/malformed-attrs.rs:85:1 + --> $DIR/malformed-attrs.rs:88:1 | LL | #[link_section] | ^^^^^^^^^^^^^^^ help: must be of the form: `#[link_section = "name"]` @@ -514,7 +519,7 @@ LL | #[link_section] = note: for more information, visit <https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute> error[E0539]: malformed `coverage` attribute input - --> $DIR/malformed-attrs.rs:87:1 + --> $DIR/malformed-attrs.rs:90:1 | LL | #[coverage] | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument @@ -527,7 +532,7 @@ LL | #[coverage(on)] | ++++ error[E0565]: malformed `no_implicit_prelude` attribute input - --> $DIR/malformed-attrs.rs:94:1 + --> $DIR/malformed-attrs.rs:97:1 | LL | #[no_implicit_prelude = 23] | ^^^^^^^^^^^^^^^^^^^^^^----^ @@ -536,7 +541,7 @@ LL | #[no_implicit_prelude = 23] | help: must be of the form: `#[no_implicit_prelude]` error[E0565]: malformed `proc_macro` attribute input - --> $DIR/malformed-attrs.rs:96:1 + --> $DIR/malformed-attrs.rs:99:1 | LL | #[proc_macro = 18] | ^^^^^^^^^^^^^----^ @@ -545,7 +550,7 @@ LL | #[proc_macro = 18] | help: must be of the form: `#[proc_macro]` error[E0565]: malformed `coroutine` attribute input - --> $DIR/malformed-attrs.rs:108:5 + --> $DIR/malformed-attrs.rs:111:5 | LL | #[coroutine = 63] || {} | ^^^^^^^^^^^^----^ @@ -554,7 +559,7 @@ LL | #[coroutine = 63] || {} | help: must be of the form: `#[coroutine]` error[E0565]: malformed `proc_macro_attribute` attribute input - --> $DIR/malformed-attrs.rs:113:1 + --> $DIR/malformed-attrs.rs:116:1 | LL | #[proc_macro_attribute = 19] | ^^^^^^^^^^^^^^^^^^^^^^^----^ @@ -563,7 +568,7 @@ LL | #[proc_macro_attribute = 19] | help: must be of the form: `#[proc_macro_attribute]` error[E0539]: malformed `must_use` attribute input - --> $DIR/malformed-attrs.rs:116:1 + --> $DIR/malformed-attrs.rs:119:1 | LL | #[must_use = 1] | ^^^^^^^^^^^^^-^ @@ -581,7 +586,7 @@ LL + #[must_use] | error[E0539]: malformed `proc_macro_derive` attribute input - --> $DIR/malformed-attrs.rs:120:1 + --> $DIR/malformed-attrs.rs:123:1 | LL | #[proc_macro_derive] | ^^^^^^^^^^^^^^^^^^^^ expected this to be a list @@ -595,7 +600,7 @@ LL | #[proc_macro_derive(TraitName, attributes(name1, name2, ...))] | ++++++++++++++++++++++++++++++++++++++++++ error[E0539]: malformed `rustc_layout_scalar_valid_range_start` attribute input - --> $DIR/malformed-attrs.rs:125:1 + --> $DIR/malformed-attrs.rs:128:1 | LL | #[rustc_layout_scalar_valid_range_start] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -604,7 +609,7 @@ LL | #[rustc_layout_scalar_valid_range_start] | help: must be of the form: `#[rustc_layout_scalar_valid_range_start(start)]` error[E0539]: malformed `rustc_layout_scalar_valid_range_end` attribute input - --> $DIR/malformed-attrs.rs:127:1 + --> $DIR/malformed-attrs.rs:130:1 | LL | #[rustc_layout_scalar_valid_range_end] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -613,7 +618,7 @@ LL | #[rustc_layout_scalar_valid_range_end] | help: must be of the form: `#[rustc_layout_scalar_valid_range_end(end)]` error[E0565]: malformed `marker` attribute input - --> $DIR/malformed-attrs.rs:152:1 + --> $DIR/malformed-attrs.rs:155:1 | LL | #[marker = 3] | ^^^^^^^^^---^ @@ -622,7 +627,7 @@ LL | #[marker = 3] | help: must be of the form: `#[marker]` error[E0565]: malformed `fundamental` attribute input - --> $DIR/malformed-attrs.rs:154:1 + --> $DIR/malformed-attrs.rs:157:1 | LL | #[fundamental()] | ^^^^^^^^^^^^^--^ @@ -631,7 +636,7 @@ LL | #[fundamental()] | help: must be of the form: `#[fundamental]` error[E0565]: malformed `ffi_pure` attribute input - --> $DIR/malformed-attrs.rs:162:5 + --> $DIR/malformed-attrs.rs:165:5 | LL | #[unsafe(ffi_pure = 1)] | ^^^^^^^^^^^^^^^^^^---^^ @@ -640,7 +645,7 @@ LL | #[unsafe(ffi_pure = 1)] | help: must be of the form: `#[ffi_pure]` error[E0539]: malformed `link_ordinal` attribute input - --> $DIR/malformed-attrs.rs:164:5 + --> $DIR/malformed-attrs.rs:167:5 | LL | #[link_ordinal] | ^^^^^^^^^^^^^^^ @@ -651,7 +656,7 @@ LL | #[link_ordinal] = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_ordinal-attribute> error[E0565]: malformed `ffi_const` attribute input - --> $DIR/malformed-attrs.rs:168:5 + --> $DIR/malformed-attrs.rs:171:5 | LL | #[unsafe(ffi_const = 1)] | ^^^^^^^^^^^^^^^^^^^---^^ @@ -659,8 +664,26 @@ LL | #[unsafe(ffi_const = 1)] | | didn't expect any arguments here | help: must be of the form: `#[ffi_const]` +error[E0539]: malformed `linkage` attribute input + --> $DIR/malformed-attrs.rs:173:5 + | +LL | #[linkage] + | ^^^^^^^^^^ expected this to be of the form `linkage = "..."` + | +help: try changing it to one of the following valid forms of the attribute + | +LL | #[linkage = "available_externally"] + | ++++++++++++++++++++++++ +LL | #[linkage = "common"] + | ++++++++++ +LL | #[linkage = "extern_weak"] + | +++++++++++++++ +LL | #[linkage = "external"] + | ++++++++++++ + = and 5 other candidates + error[E0565]: malformed `automatically_derived` attribute input - --> $DIR/malformed-attrs.rs:188:1 + --> $DIR/malformed-attrs.rs:191:1 | LL | #[automatically_derived = 18] | ^^^^^^^^^^^^^^^^^^^^^^^^----^ @@ -669,7 +692,7 @@ LL | #[automatically_derived = 18] | help: must be of the form: `#[automatically_derived]` error[E0565]: malformed `non_exhaustive` attribute input - --> $DIR/malformed-attrs.rs:194:1 + --> $DIR/malformed-attrs.rs:197:1 | LL | #[non_exhaustive = 1] | ^^^^^^^^^^^^^^^^^---^ @@ -678,13 +701,13 @@ LL | #[non_exhaustive = 1] | help: must be of the form: `#[non_exhaustive]` error: valid forms for the attribute are `#[macro_use(name1, name2, ...)]` and `#[macro_use]` - --> $DIR/malformed-attrs.rs:206:1 + --> $DIR/malformed-attrs.rs:209:1 | LL | #[macro_use = 1] | ^^^^^^^^^^^^^^^^ error[E0565]: malformed `allow_internal_unsafe` attribute input - --> $DIR/malformed-attrs.rs:213:1 + --> $DIR/malformed-attrs.rs:216:1 | LL | #[allow_internal_unsafe = 1] | ^^^^^^^^^^^^^^^^^^^^^^^^---^ @@ -693,7 +716,7 @@ LL | #[allow_internal_unsafe = 1] | help: must be of the form: `#[allow_internal_unsafe]` error[E0565]: malformed `type_const` attribute input - --> $DIR/malformed-attrs.rs:140:5 + --> $DIR/malformed-attrs.rs:143:5 | LL | #[type_const = 1] | ^^^^^^^^^^^^^---^ @@ -713,20 +736,20 @@ LL | | #[coroutine = 63] || {} LL | | } | |_- not a `const fn` -error: `#[repr(align(...))]` is not supported on function items - --> $DIR/malformed-attrs.rs:45:1 +error: `#[repr(align(...))]` is not supported on functions + --> $DIR/malformed-attrs.rs:47:1 | LL | #[repr] | ^^^^^^^ | help: use `#[rustc_align(...)]` instead - --> $DIR/malformed-attrs.rs:45:1 + --> $DIR/malformed-attrs.rs:47:1 | LL | #[repr] | ^^^^^^^ warning: `#[diagnostic::do_not_recommend]` does not expect any arguments - --> $DIR/malformed-attrs.rs:146:1 + --> $DIR/malformed-attrs.rs:149:1 | LL | #[diagnostic::do_not_recommend()] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -734,7 +757,7 @@ LL | #[diagnostic::do_not_recommend()] = note: `#[warn(malformed_diagnostic_attributes)]` on by default warning: missing options for `on_unimplemented` attribute - --> $DIR/malformed-attrs.rs:135:1 + --> $DIR/malformed-attrs.rs:138:1 | LL | #[diagnostic::on_unimplemented] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -742,7 +765,7 @@ LL | #[diagnostic::on_unimplemented] = help: at least one of the `message`, `note` and `label` options are expected warning: malformed `on_unimplemented` attribute - --> $DIR/malformed-attrs.rs:137:1 + --> $DIR/malformed-attrs.rs:140:1 | LL | #[diagnostic::on_unimplemented = 1] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here @@ -750,7 +773,7 @@ LL | #[diagnostic::on_unimplemented = 1] = help: only `message`, `note` and `label` are allowed as options error: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]` - --> $DIR/malformed-attrs.rs:50:1 + --> $DIR/malformed-attrs.rs:52:1 | LL | #[inline = 5] | ^^^^^^^^^^^^^ @@ -759,7 +782,7 @@ LL | #[inline = 5] = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` - --> $DIR/malformed-attrs.rs:91:1 + --> $DIR/malformed-attrs.rs:94:1 | LL | #[ignore()] | ^^^^^^^^^^^ @@ -768,7 +791,7 @@ LL | #[ignore()] = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` - --> $DIR/malformed-attrs.rs:220:1 + --> $DIR/malformed-attrs.rs:223:1 | LL | #[ignore = 1] | ^^^^^^^^^^^^^ @@ -777,7 +800,7 @@ LL | #[ignore = 1] = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> error[E0308]: mismatched types - --> $DIR/malformed-attrs.rs:108:23 + --> $DIR/malformed-attrs.rs:111:23 | LL | fn test() { | - help: a return type might be missing here: `-> _` @@ -785,15 +808,15 @@ LL | #[coroutine = 63] || {} | ^^^^^ expected `()`, found coroutine | = note: expected unit type `()` - found coroutine `{coroutine@$DIR/malformed-attrs.rs:108:23: 108:25}` + found coroutine `{coroutine@$DIR/malformed-attrs.rs:111:23: 111:25}` -error: aborting due to 74 previous errors; 3 warnings emitted +error: aborting due to 77 previous errors; 3 warnings emitted Some errors have detailed explanations: E0308, E0463, E0539, E0565, E0658, E0805. For more information about an error, try `rustc --explain E0308`. Future incompatibility report: Future breakage diagnostic: error: valid forms for the attribute are `#[doc(hidden)]`, `#[doc(inline)]`, and `#[doc = "string"]` - --> $DIR/malformed-attrs.rs:40:1 + --> $DIR/malformed-attrs.rs:41:1 | LL | #[doc] | ^^^^^^ @@ -805,7 +828,7 @@ LL | #[doc] Future breakage diagnostic: error: valid forms for the attribute are `#[doc(hidden)]`, `#[doc(inline)]`, and `#[doc = "string"]` - --> $DIR/malformed-attrs.rs:73:1 + --> $DIR/malformed-attrs.rs:76:1 | LL | #[doc] | ^^^^^^ @@ -817,7 +840,7 @@ LL | #[doc] Future breakage diagnostic: error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]` - --> $DIR/malformed-attrs.rs:80:1 + --> $DIR/malformed-attrs.rs:83:1 | LL | #[link] | ^^^^^^^ @@ -829,7 +852,7 @@ LL | #[link] Future breakage diagnostic: error: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]` - --> $DIR/malformed-attrs.rs:50:1 + --> $DIR/malformed-attrs.rs:52:1 | LL | #[inline = 5] | ^^^^^^^^^^^^^ @@ -840,7 +863,7 @@ LL | #[inline = 5] Future breakage diagnostic: error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` - --> $DIR/malformed-attrs.rs:91:1 + --> $DIR/malformed-attrs.rs:94:1 | LL | #[ignore()] | ^^^^^^^^^^^ @@ -851,7 +874,7 @@ LL | #[ignore()] Future breakage diagnostic: error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` - --> $DIR/malformed-attrs.rs:220:1 + --> $DIR/malformed-attrs.rs:223:1 | LL | #[ignore = 1] | ^^^^^^^^^^^^^ diff --git a/tests/ui/attributes/malformed-fn-align.rs b/tests/ui/attributes/malformed-fn-align.rs index cf143b28e54..adce84763ab 100644 --- a/tests/ui/attributes/malformed-fn-align.rs +++ b/tests/ui/attributes/malformed-fn-align.rs @@ -23,7 +23,7 @@ fn f2() {} #[rustc_align(0)] //~ ERROR invalid alignment value: not a power of two fn f3() {} -#[repr(align(16))] //~ ERROR `#[repr(align(...))]` is not supported on function items +#[repr(align(16))] //~ ERROR `#[repr(align(...))]` is not supported on functions fn f4() {} #[rustc_align(-1)] //~ ERROR expected unsuffixed literal, found `-` @@ -41,14 +41,14 @@ fn f7() {} #[rustc_align(16)] fn f8() {} -#[rustc_align(16)] //~ ERROR `#[rustc_align(...)]` is not supported on struct items +#[rustc_align(16)] //~ ERROR attribute cannot be used on struct S1; -#[rustc_align(32)] //~ ERROR `#[rustc_align(...)]` should be applied to a function item +#[rustc_align(32)] //~ ERROR attribute cannot be used on const FOO: i32 = 42; -#[rustc_align(32)] //~ ERROR `#[rustc_align(...)]` should be applied to a function item +#[rustc_align(32)] //~ ERROR attribute cannot be used on mod test {} -#[rustc_align(32)] //~ ERROR `#[rustc_align(...)]` should be applied to a function item +#[rustc_align(32)] //~ ERROR attribute cannot be used on use ::std::iter; diff --git a/tests/ui/attributes/malformed-fn-align.stderr b/tests/ui/attributes/malformed-fn-align.stderr index d995a7bf070..346fe2b4b7f 100644 --- a/tests/ui/attributes/malformed-fn-align.stderr +++ b/tests/ui/attributes/malformed-fn-align.stderr @@ -69,53 +69,49 @@ error[E0589]: invalid alignment value: not a power of two LL | #[rustc_align(3)] | ^ -error: `#[repr(align(...))]` is not supported on function items - --> $DIR/malformed-fn-align.rs:26:8 - | -LL | #[repr(align(16))] - | ^^^^^^^^^ - | -help: use `#[rustc_align(...)]` instead - --> $DIR/malformed-fn-align.rs:26:8 - | -LL | #[repr(align(16))] - | ^^^^^^^^^ - -error: `#[rustc_align(...)]` is not supported on struct items +error: `#[rustc_align]` attribute cannot be used on structs --> $DIR/malformed-fn-align.rs:44:1 | LL | #[rustc_align(16)] | ^^^^^^^^^^^^^^^^^^ | -help: use `#[repr(align(...))]` instead - | -LL - #[rustc_align(16)] -LL + #[repr(align(16))] - | + = help: `#[rustc_align]` can only be applied to functions -error: `#[rustc_align(...)]` should be applied to a function item +error: `#[rustc_align]` attribute cannot be used on constants --> $DIR/malformed-fn-align.rs:47:1 | LL | #[rustc_align(32)] | ^^^^^^^^^^^^^^^^^^ -LL | const FOO: i32 = 42; - | -------------------- not a function item + | + = help: `#[rustc_align]` can only be applied to functions -error: `#[rustc_align(...)]` should be applied to a function item +error: `#[rustc_align]` attribute cannot be used on modules --> $DIR/malformed-fn-align.rs:50:1 | LL | #[rustc_align(32)] | ^^^^^^^^^^^^^^^^^^ -LL | mod test {} - | ----------- not a function item + | + = help: `#[rustc_align]` can only be applied to functions -error: `#[rustc_align(...)]` should be applied to a function item +error: `#[rustc_align]` attribute cannot be used on use statements --> $DIR/malformed-fn-align.rs:53:1 | LL | #[rustc_align(32)] | ^^^^^^^^^^^^^^^^^^ -LL | use ::std::iter; - | ---------------- not a function item + | + = help: `#[rustc_align]` can only be applied to functions + +error: `#[repr(align(...))]` is not supported on functions + --> $DIR/malformed-fn-align.rs:26:8 + | +LL | #[repr(align(16))] + | ^^^^^^^^^ + | +help: use `#[rustc_align(...)]` instead + --> $DIR/malformed-fn-align.rs:26:8 + | +LL | #[repr(align(16))] + | ^^^^^^^^^ error: aborting due to 15 previous errors diff --git a/tests/ui/attributes/multiple-invalid.rs b/tests/ui/attributes/multiple-invalid.rs index ae044eb843b..49d1aeed604 100644 --- a/tests/ui/attributes/multiple-invalid.rs +++ b/tests/ui/attributes/multiple-invalid.rs @@ -2,9 +2,9 @@ // on an item. #[inline] -//~^ ERROR attribute should be applied to function or closure [E0518] +//~^ ERROR attribute cannot be used on #[target_feature(enable = "sse2")] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on const FOO: u8 = 0; fn main() { } diff --git a/tests/ui/attributes/multiple-invalid.stderr b/tests/ui/attributes/multiple-invalid.stderr index f4f7dd7c4f1..182d39b14bc 100644 --- a/tests/ui/attributes/multiple-invalid.stderr +++ b/tests/ui/attributes/multiple-invalid.stderr @@ -1,21 +1,18 @@ -error: attribute should be applied to a function definition +error: `#[inline]` attribute cannot be used on constants + --> $DIR/multiple-invalid.rs:4:1 + | +LL | #[inline] + | ^^^^^^^^^ + | + = help: `#[inline]` can only be applied to functions + +error: `#[target_feature]` attribute cannot be used on constants --> $DIR/multiple-invalid.rs:6:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | const FOO: u8 = 0; - | ------------------ not a function definition - -error[E0518]: attribute should be applied to function or closure - --> $DIR/multiple-invalid.rs:4:1 | -LL | #[inline] - | ^^^^^^^^^ -... -LL | const FOO: u8 = 0; - | ------------------ not a function or closure + = help: `#[target_feature]` can only be applied to functions error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0518`. diff --git a/tests/ui/attributes/optimize.rs b/tests/ui/attributes/optimize.rs index 7a1cc1be9ee..78e05f111e7 100644 --- a/tests/ui/attributes/optimize.rs +++ b/tests/ui/attributes/optimize.rs @@ -5,11 +5,11 @@ //@ edition: 2018 -#[optimize(speed)] //~ ERROR attribute applied to an invalid target +#[optimize(speed)] //~ ERROR attribute cannot be used on struct F; fn invalid() { - #[optimize(speed)] //~ ERROR attribute applied to an invalid target + #[optimize(speed)] //~ ERROR attribute cannot be used on { 1 }; @@ -18,10 +18,10 @@ fn invalid() { #[optimize(speed)] fn valid() {} -#[optimize(speed)] //~ ERROR attribute applied to an invalid target +#[optimize(speed)] //~ ERROR attribute cannot be used on mod valid_module {} -#[optimize(speed)] //~ ERROR attribute applied to an invalid target +#[optimize(speed)] //~ ERROR attribute cannot be used on impl F {} fn main() { diff --git a/tests/ui/attributes/optimize.stderr b/tests/ui/attributes/optimize.stderr index ad9309d27a5..2ded1a973f3 100644 --- a/tests/ui/attributes/optimize.stderr +++ b/tests/ui/attributes/optimize.stderr @@ -1,36 +1,34 @@ -error: attribute applied to an invalid target +error: `#[optimize]` attribute cannot be used on structs --> $DIR/optimize.rs:8:1 | LL | #[optimize(speed)] | ^^^^^^^^^^^^^^^^^^ -LL | struct F; - | --------- invalid target + | + = help: `#[optimize]` can only be applied to functions -error: attribute applied to an invalid target +error: `#[optimize]` attribute cannot be used on expressions --> $DIR/optimize.rs:12:5 | -LL | #[optimize(speed)] - | ^^^^^^^^^^^^^^^^^^ -LL | / { -LL | | 1 -LL | | }; - | |_____- invalid target +LL | #[optimize(speed)] + | ^^^^^^^^^^^^^^^^^^ + | + = help: `#[optimize]` can only be applied to functions -error: attribute applied to an invalid target +error: `#[optimize]` attribute cannot be used on modules --> $DIR/optimize.rs:21:1 | LL | #[optimize(speed)] | ^^^^^^^^^^^^^^^^^^ -LL | mod valid_module {} - | ------------------- invalid target + | + = help: `#[optimize]` can only be applied to functions -error: attribute applied to an invalid target +error: `#[optimize]` attribute cannot be used on inherent impl blocks --> $DIR/optimize.rs:24:1 | LL | #[optimize(speed)] | ^^^^^^^^^^^^^^^^^^ -LL | impl F {} - | --------- invalid target + | + = help: `#[optimize]` can only be applied to functions error: aborting due to 4 previous errors diff --git a/tests/ui/attributes/positions/used.rs b/tests/ui/attributes/positions/used.rs index 7950fa773a1..7e106d278f2 100644 --- a/tests/ui/attributes/positions/used.rs +++ b/tests/ui/attributes/positions/used.rs @@ -4,20 +4,20 @@ #[used] static FOO: u32 = 0; // OK -#[used] //~ ERROR attribute must be applied to a `static` variable +#[used] //~ ERROR attribute cannot be used on fn foo() {} -#[used] //~ ERROR attribute must be applied to a `static` variable +#[used] //~ ERROR attribute cannot be used on struct Foo {} -#[used] //~ ERROR attribute must be applied to a `static` variable +#[used] //~ ERROR attribute cannot be used on trait Bar {} -#[used] //~ ERROR attribute must be applied to a `static` variable +#[used] //~ ERROR attribute cannot be used on impl Bar for Foo {} // Regression test for <https://github.com/rust-lang/rust/issues/126789>. extern "C" { - #[used] //~ ERROR attribute must be applied to a `static` variable + #[used] //~ ERROR attribute cannot be used on static BAR: i32; } diff --git a/tests/ui/attributes/positions/used.stderr b/tests/ui/attributes/positions/used.stderr index 64460c178cb..79011f3a758 100644 --- a/tests/ui/attributes/positions/used.stderr +++ b/tests/ui/attributes/positions/used.stderr @@ -1,42 +1,42 @@ -error: attribute must be applied to a `static` variable +error: `#[used]` attribute cannot be used on functions --> $DIR/used.rs:7:1 | LL | #[used] | ^^^^^^^ -LL | fn foo() {} - | ----------- but this is a function + | + = help: `#[used]` can only be applied to statics -error: attribute must be applied to a `static` variable +error: `#[used]` attribute cannot be used on structs --> $DIR/used.rs:10:1 | LL | #[used] | ^^^^^^^ -LL | struct Foo {} - | ------------- but this is a struct + | + = help: `#[used]` can only be applied to statics -error: attribute must be applied to a `static` variable +error: `#[used]` attribute cannot be used on traits --> $DIR/used.rs:13:1 | LL | #[used] | ^^^^^^^ -LL | trait Bar {} - | ------------ but this is a trait + | + = help: `#[used]` can only be applied to statics -error: attribute must be applied to a `static` variable +error: `#[used]` attribute cannot be used on trait impl blocks --> $DIR/used.rs:16:1 | LL | #[used] | ^^^^^^^ -LL | impl Bar for Foo {} - | ------------------- but this is a trait implementation block + | + = help: `#[used]` can only be applied to statics -error: attribute must be applied to a `static` variable +error: `#[used]` attribute cannot be used on foreign statics --> $DIR/used.rs:21:5 | LL | #[used] | ^^^^^^^ -LL | static BAR: i32; - | ---------------- but this is a foreign static item + | + = help: `#[used]` can only be applied to statics error: aborting due to 5 previous errors diff --git a/tests/ui/attributes/rustc_confusables.rs b/tests/ui/attributes/rustc_confusables.rs index a8095936cff..91c66a75cc3 100644 --- a/tests/ui/attributes/rustc_confusables.rs +++ b/tests/ui/attributes/rustc_confusables.rs @@ -43,5 +43,6 @@ impl Bar { } #[rustc_confusables("blah")] -//~^ ERROR attribute should be applied to an inherent method +//~^ ERROR attribute cannot be used on +//~| HELP can only be applied to fn not_inherent_impl_method() {} diff --git a/tests/ui/attributes/rustc_confusables.stderr b/tests/ui/attributes/rustc_confusables.stderr index 3ed4efeb4db..c714257ee77 100644 --- a/tests/ui/attributes/rustc_confusables.stderr +++ b/tests/ui/attributes/rustc_confusables.stderr @@ -22,11 +22,13 @@ LL | #[rustc_confusables(invalid_meta_item)] | | expected a string literal here | help: must be of the form: `#[rustc_confusables("name1", "name2", ...)]` -error: attribute should be applied to an inherent method +error: `#[rustc_confusables]` attribute cannot be used on functions --> $DIR/rustc_confusables.rs:45:1 | LL | #[rustc_confusables("blah")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_confusables]` can only be applied to inherent methods error[E0599]: no method named `inser` found for struct `rustc_confusables_across_crate::BTreeSet` in the current scope --> $DIR/rustc_confusables.rs:12:7 diff --git a/tests/ui/attributes/rustc_skip_during_method_dispatch.rs b/tests/ui/attributes/rustc_skip_during_method_dispatch.rs index 25b473d5a58..e1bd0ca3896 100644 --- a/tests/ui/attributes/rustc_skip_during_method_dispatch.rs +++ b/tests/ui/attributes/rustc_skip_during_method_dispatch.rs @@ -32,7 +32,7 @@ trait String {} trait OK {} #[rustc_skip_during_method_dispatch(array)] -//~^ ERROR: attribute should be applied to a trait +//~^ ERROR: attribute cannot be used on impl OK for () {} fn main() {} diff --git a/tests/ui/attributes/rustc_skip_during_method_dispatch.stderr b/tests/ui/attributes/rustc_skip_during_method_dispatch.stderr index 2f5d7968489..094987e944f 100644 --- a/tests/ui/attributes/rustc_skip_during_method_dispatch.stderr +++ b/tests/ui/attributes/rustc_skip_during_method_dispatch.stderr @@ -61,14 +61,13 @@ LL | #[rustc_skip_during_method_dispatch("array")] | | didn't expect a literal here | help: must be of the form: `#[rustc_skip_during_method_dispatch(array, boxed_slice)]` -error: attribute should be applied to a trait +error: `#[rustc_skip_during_method_dispatch]` attribute cannot be used on trait impl blocks --> $DIR/rustc_skip_during_method_dispatch.rs:34:1 | LL | #[rustc_skip_during_method_dispatch(array)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | impl OK for () {} - | ----------------- not a trait + | + = help: `#[rustc_skip_during_method_dispatch]` can only be applied to traits error: aborting due to 8 previous errors diff --git a/tests/ui/borrowck/borrowck-in-static.stderr b/tests/ui/borrowck/borrowck-in-static.stderr index d85f6f5fdd5..32419da0ce2 100644 --- a/tests/ui/borrowck/borrowck-in-static.stderr +++ b/tests/ui/borrowck/borrowck-in-static.stderr @@ -10,7 +10,7 @@ LL | Box::new(|| x) | | | captured by this `Fn` closure | - = help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once + = help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once help: consider cloning the value if the performance cost is acceptable | LL | Box::new(|| x.clone()) diff --git a/tests/ui/borrowck/borrowck-move-by-capture.stderr b/tests/ui/borrowck/borrowck-move-by-capture.stderr index e9e05440766..0ace6156281 100644 --- a/tests/ui/borrowck/borrowck-move-by-capture.stderr +++ b/tests/ui/borrowck/borrowck-move-by-capture.stderr @@ -12,7 +12,7 @@ LL | let _h = to_fn_once(move || -> isize { *bar }); | | | `bar` is moved here | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/borrowck-move-by-capture.rs:3:37 | LL | fn to_fn_mut<A:std::marker::Tuple,F:FnMut<A>>(f: F) -> F { f } diff --git a/tests/ui/borrowck/issue-103624.stderr b/tests/ui/borrowck/issue-103624.stderr index ef022808886..bd6c1c44bfb 100644 --- a/tests/ui/borrowck/issue-103624.stderr +++ b/tests/ui/borrowck/issue-103624.stderr @@ -13,7 +13,7 @@ LL | LL | self.b; | ^^^^^^ `self.b` is moved here | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/issue-103624.rs:7:36 | LL | async fn spawn_blocking<T>(f: impl (Fn() -> T) + Send + Sync + 'static) -> T { diff --git a/tests/ui/borrowck/issue-87456-point-to-closure.stderr b/tests/ui/borrowck/issue-87456-point-to-closure.stderr index 043e336cd86..c31d096109c 100644 --- a/tests/ui/borrowck/issue-87456-point-to-closure.stderr +++ b/tests/ui/borrowck/issue-87456-point-to-closure.stderr @@ -10,7 +10,7 @@ LL | LL | let _foo: String = val; | ^^^ move occurs because `val` has type `String`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/issue-87456-point-to-closure.rs:3:24 | LL | fn take_mut(_val: impl FnMut()) {} diff --git a/tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr b/tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr index d3333041310..69c36674916 100644 --- a/tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr +++ b/tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr @@ -10,7 +10,7 @@ LL | y.into_iter(); | | | move occurs because `y` has type `Vec<String>`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/unboxed-closures-move-upvar-from-non-once-ref-closure.rs:5:28 | LL | fn call<F>(f: F) where F : Fn() { diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr index 44fc23b6390..5dd81f486c8 100644 --- a/tests/ui/check-cfg/target_feature.stderr +++ b/tests/ui/check-cfg/target_feature.stderr @@ -183,6 +183,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `nnp-assist` `nontrapping-fptoint` `nvic` +`outline-atomics` `paca` `pacg` `pan` diff --git a/tests/ui/consts/const-eval/union-const-eval-field.rs b/tests/ui/consts/const-eval/union-const-eval-field.rs index 719e59b007c..2c9061a7a50 100644 --- a/tests/ui/consts/const-eval/union-const-eval-field.rs +++ b/tests/ui/consts/const-eval/union-const-eval-field.rs @@ -1,5 +1,6 @@ //@ dont-require-annotations: NOTE //@ normalize-stderr: "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" +//@ normalize-stderr: "([[:xdigit:]]{2}\s){4}(__\s){4}\s+│\s+([?|\.]){4}\W{4}" -> "HEX_DUMP" type Field1 = i32; type Field2 = f32; diff --git a/tests/ui/consts/const-eval/union-const-eval-field.stderr b/tests/ui/consts/const-eval/union-const-eval-field.stderr index 1843ce273ac..3b7e5508d56 100644 --- a/tests/ui/consts/const-eval/union-const-eval-field.stderr +++ b/tests/ui/consts/const-eval/union-const-eval-field.stderr @@ -1,21 +1,21 @@ error[E0080]: reading memory at ALLOC0[0x0..0x8], but memory is uninitialized at [0x4..0x8], and this operation requires initialized memory - --> $DIR/union-const-eval-field.rs:29:37 + --> $DIR/union-const-eval-field.rs:30:37 | LL | const FIELD3: Field3 = unsafe { UNION.field3 }; | ^^^^^^^^^^^^ evaluation of `read_field3::FIELD3` failed here | = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { - 00 00 80 3f __ __ __ __ │ ...?░░░░ + HEX_DUMP } note: erroneous constant encountered - --> $DIR/union-const-eval-field.rs:31:5 + --> $DIR/union-const-eval-field.rs:32:5 | LL | FIELD3 | ^^^^^^ note: erroneous constant encountered - --> $DIR/union-const-eval-field.rs:31:5 + --> $DIR/union-const-eval-field.rs:32:5 | LL | FIELD3 | ^^^^^^ diff --git a/tests/ui/coroutine/invalid_attr_usage.rs b/tests/ui/coroutine/invalid_attr_usage.rs index 995a3aa3100..5081c17de4b 100644 --- a/tests/ui/coroutine/invalid_attr_usage.rs +++ b/tests/ui/coroutine/invalid_attr_usage.rs @@ -3,9 +3,9 @@ #![feature(coroutines)] #[coroutine] -//~^ ERROR: attribute should be applied to closures +//~^ ERROR: attribute cannot be used on struct Foo; #[coroutine] -//~^ ERROR: attribute should be applied to closures +//~^ ERROR: attribute cannot be used on fn main() {} diff --git a/tests/ui/coroutine/invalid_attr_usage.stderr b/tests/ui/coroutine/invalid_attr_usage.stderr index 316a0117e5d..46fc80c1bad 100644 --- a/tests/ui/coroutine/invalid_attr_usage.stderr +++ b/tests/ui/coroutine/invalid_attr_usage.stderr @@ -1,14 +1,18 @@ -error: attribute should be applied to closures +error: `#[coroutine]` attribute cannot be used on structs --> $DIR/invalid_attr_usage.rs:5:1 | LL | #[coroutine] | ^^^^^^^^^^^^ + | + = help: `#[coroutine]` can only be applied to closures -error: attribute should be applied to closures +error: `#[coroutine]` attribute cannot be used on functions --> $DIR/invalid_attr_usage.rs:9:1 | LL | #[coroutine] | ^^^^^^^^^^^^ + | + = help: `#[coroutine]` can only be applied to closures error: aborting due to 2 previous errors diff --git a/tests/ui/coverage-attr/allowed-positions.rs b/tests/ui/coverage-attr/allowed-positions.rs index f1169fa6570..cfbc7f5e6c0 100644 --- a/tests/ui/coverage-attr/allowed-positions.rs +++ b/tests/ui/coverage-attr/allowed-positions.rs @@ -11,24 +11,24 @@ #[coverage(off)] mod submod {} -#[coverage(off)] //~ ERROR coverage attribute not allowed here [E0788] +#[coverage(off)] //~ ERROR attribute cannot be used on type MyTypeAlias = (); -#[coverage(off)] //~ ERROR [E0788] +#[coverage(off)] //~ ERROR attribute cannot be used on trait MyTrait { - #[coverage(off)] //~ ERROR [E0788] + #[coverage(off)] //~ ERROR attribute cannot be used on const TRAIT_ASSOC_CONST: u32; - #[coverage(off)] //~ ERROR [E0788] + #[coverage(off)] //~ ERROR attribute cannot be used on type TraitAssocType; - #[coverage(off)] //~ ERROR [E0788] + #[coverage(off)] //~ ERROR attribute cannot be used on fn trait_method(&self); #[coverage(off)] fn trait_method_with_default(&self) {} - #[coverage(off)] //~ ERROR [E0788] + #[coverage(off)] //~ ERROR attribute cannot be used on fn trait_assoc_fn(); } @@ -36,7 +36,7 @@ trait MyTrait { impl MyTrait for () { const TRAIT_ASSOC_CONST: u32 = 0; - #[coverage(off)] //~ ERROR [E0788] + #[coverage(off)] //~ ERROR attribute cannot be used on type TraitAssocType = Self; #[coverage(off)] @@ -53,14 +53,14 @@ trait HasAssocType { } impl HasAssocType for () { - #[coverage(off)] //~ ERROR [E0788] + #[coverage(off)] //~ ERROR attribute cannot be used on type T = impl Copy; fn constrain_assoc_type() -> Self::T {} } -#[coverage(off)] //~ ERROR [E0788] +#[coverage(off)] //~ ERROR attribute cannot be used on struct MyStruct { - #[coverage(off)] //~ ERROR [E0788] + #[coverage(off)] //~ ERROR attribute cannot be used on field: u32, } @@ -73,25 +73,25 @@ impl MyStruct { } extern "C" { - #[coverage(off)] //~ ERROR [E0788] + #[coverage(off)] //~ ERROR attribute cannot be used on static X: u32; - #[coverage(off)] //~ ERROR [E0788] + #[coverage(off)] //~ ERROR attribute cannot be used on type T; - #[coverage(off)] //~ ERROR [E0788] + #[coverage(off)] //~ ERROR attribute cannot be used on fn foreign_fn(); } #[coverage(off)] fn main() { - #[coverage(off)] //~ ERROR [E0788] + #[coverage(off)] //~ ERROR attribute cannot be used on let _ = (); // Currently not allowed on let statements, even if they bind to a closure. // It might be nice to support this as a special case someday, but trying // to define the precise boundaries of that special case might be tricky. - #[coverage(off)] //~ ERROR [E0788] + #[coverage(off)] //~ ERROR attribute cannot be used on let _let_closure = || (); // In situations where attributes can already be applied to expressions, @@ -107,10 +107,10 @@ fn main() { //~^ ERROR attributes on expressions are experimental [E0658] match () { - #[coverage(off)] //~ ERROR [E0788] + #[coverage(off)] //~ ERROR attribute cannot be used on () => (), } - #[coverage(off)] //~ ERROR [E0788] + #[coverage(off)] //~ ERROR attribute cannot be used on return (); } diff --git a/tests/ui/coverage-attr/allowed-positions.stderr b/tests/ui/coverage-attr/allowed-positions.stderr index 34562a4da1b..aaef3ad0203 100644 --- a/tests/ui/coverage-attr/allowed-positions.stderr +++ b/tests/ui/coverage-attr/allowed-positions.stderr @@ -8,185 +8,142 @@ LL | let _closure_expr = #[coverage(off)] || (); = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0788]: coverage attribute not allowed here +error: `#[coverage]` attribute cannot be used on type aliases --> $DIR/allowed-positions.rs:14:1 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ -LL | type MyTypeAlias = (); - | ---------------------- not a function, impl block, or module | - = help: coverage attribute can be applied to a function (with body), impl block, or module + = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates -error[E0788]: coverage attribute not allowed here +error: `#[coverage]` attribute cannot be used on traits --> $DIR/allowed-positions.rs:17:1 | -LL | #[coverage(off)] - | ^^^^^^^^^^^^^^^^ -LL | / trait MyTrait { -LL | | #[coverage(off)] -LL | | const TRAIT_ASSOC_CONST: u32; -... | -LL | | fn trait_assoc_fn(); -LL | | } - | |_- not a function, impl block, or module +LL | #[coverage(off)] + | ^^^^^^^^^^^^^^^^ | - = help: coverage attribute can be applied to a function (with body), impl block, or module + = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates -error[E0788]: coverage attribute not allowed here - --> $DIR/allowed-positions.rs:61:1 +error: `#[coverage]` attribute cannot be used on associated consts + --> $DIR/allowed-positions.rs:19:5 | -LL | #[coverage(off)] - | ^^^^^^^^^^^^^^^^ -LL | / struct MyStruct { -LL | | #[coverage(off)] -LL | | field: u32, -LL | | } - | |_- not a function, impl block, or module +LL | #[coverage(off)] + | ^^^^^^^^^^^^^^^^ | - = help: coverage attribute can be applied to a function (with body), impl block, or module + = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates -error[E0788]: coverage attribute not allowed here - --> $DIR/allowed-positions.rs:63:5 +error: `#[coverage]` attribute cannot be used on associated types + --> $DIR/allowed-positions.rs:22:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ -LL | field: u32, - | ---------- not a function, impl block, or module | - = help: coverage attribute can be applied to a function (with body), impl block, or module + = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates -error[E0788]: coverage attribute not allowed here - --> $DIR/allowed-positions.rs:88:5 +error: `#[coverage]` attribute cannot be used on required trait methods + --> $DIR/allowed-positions.rs:25:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ -LL | let _ = (); - | ----------- not a function, impl block, or module | - = help: coverage attribute can be applied to a function (with body), impl block, or module + = help: `#[coverage]` can be applied to impl blocks, functions, closures, provided trait methods, trait methods in impl blocks, inherent methods, modules, crates -error[E0788]: coverage attribute not allowed here - --> $DIR/allowed-positions.rs:94:5 +error: `#[coverage]` attribute cannot be used on required trait methods + --> $DIR/allowed-positions.rs:31:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ -LL | let _let_closure = || (); - | ------------------------- not a function, impl block, or module | - = help: coverage attribute can be applied to a function (with body), impl block, or module + = help: `#[coverage]` can be applied to impl blocks, functions, closures, provided trait methods, trait methods in impl blocks, inherent methods, modules, crates -error[E0788]: coverage attribute not allowed here - --> $DIR/allowed-positions.rs:110:9 +error: `#[coverage]` attribute cannot be used on associated types + --> $DIR/allowed-positions.rs:39:5 | -LL | #[coverage(off)] - | ^^^^^^^^^^^^^^^^ -LL | () => (), - | -------- not a function, impl block, or module +LL | #[coverage(off)] + | ^^^^^^^^^^^^^^^^ | - = help: coverage attribute can be applied to a function (with body), impl block, or module + = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates -error[E0788]: coverage attribute not allowed here - --> $DIR/allowed-positions.rs:114:5 +error: `#[coverage]` attribute cannot be used on associated types + --> $DIR/allowed-positions.rs:56:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ -LL | return (); - | --------- not a function, impl block, or module | - = help: coverage attribute can be applied to a function (with body), impl block, or module + = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates -error[E0788]: coverage attribute not allowed here - --> $DIR/allowed-positions.rs:19:5 +error: `#[coverage]` attribute cannot be used on structs + --> $DIR/allowed-positions.rs:61:1 | -LL | #[coverage(off)] - | ^^^^^^^^^^^^^^^^ -LL | const TRAIT_ASSOC_CONST: u32; - | ----------------------------- not a function, impl block, or module +LL | #[coverage(off)] + | ^^^^^^^^^^^^^^^^ | - = help: coverage attribute can be applied to a function (with body), impl block, or module + = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates -error[E0788]: coverage attribute not allowed here - --> $DIR/allowed-positions.rs:22:5 +error: `#[coverage]` attribute cannot be used on struct fields + --> $DIR/allowed-positions.rs:63:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ -LL | type TraitAssocType; - | -------------------- not a function, impl block, or module | - = help: coverage attribute can be applied to a function (with body), impl block, or module + = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates -error[E0788]: coverage attribute not allowed here - --> $DIR/allowed-positions.rs:25:5 +error: `#[coverage]` attribute cannot be used on foreign statics + --> $DIR/allowed-positions.rs:76:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ -LL | fn trait_method(&self); - | ----------------------- function has no body | - = help: coverage attribute can be applied to a function (with body), impl block, or module + = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates -error[E0788]: coverage attribute not allowed here - --> $DIR/allowed-positions.rs:31:5 +error: `#[coverage]` attribute cannot be used on foreign types + --> $DIR/allowed-positions.rs:79:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ -LL | fn trait_assoc_fn(); - | -------------------- function has no body | - = help: coverage attribute can be applied to a function (with body), impl block, or module + = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates -error[E0788]: coverage attribute not allowed here - --> $DIR/allowed-positions.rs:39:5 +error: `#[coverage]` attribute cannot be used on foreign functions + --> $DIR/allowed-positions.rs:82:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ -LL | type TraitAssocType = Self; - | --------------------------- not a function, impl block, or module | - = help: coverage attribute can be applied to a function (with body), impl block, or module + = help: `#[coverage]` can be applied to methods, impl blocks, functions, closures, modules, crates -error[E0788]: coverage attribute not allowed here - --> $DIR/allowed-positions.rs:56:5 +error: `#[coverage]` attribute cannot be used on statements + --> $DIR/allowed-positions.rs:88:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ -LL | type T = impl Copy; - | ------------------- not a function, impl block, or module | - = help: coverage attribute can be applied to a function (with body), impl block, or module + = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates -error[E0788]: coverage attribute not allowed here - --> $DIR/allowed-positions.rs:76:5 +error: `#[coverage]` attribute cannot be used on statements + --> $DIR/allowed-positions.rs:94:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ -LL | static X: u32; - | -------------- not a function, impl block, or module | - = help: coverage attribute can be applied to a function (with body), impl block, or module + = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates -error[E0788]: coverage attribute not allowed here - --> $DIR/allowed-positions.rs:79:5 +error: `#[coverage]` attribute cannot be used on match arms + --> $DIR/allowed-positions.rs:110:9 | -LL | #[coverage(off)] - | ^^^^^^^^^^^^^^^^ -LL | type T; - | ------- not a function, impl block, or module +LL | #[coverage(off)] + | ^^^^^^^^^^^^^^^^ | - = help: coverage attribute can be applied to a function (with body), impl block, or module + = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates -error[E0788]: coverage attribute not allowed here - --> $DIR/allowed-positions.rs:82:5 +error: `#[coverage]` attribute cannot be used on expressions + --> $DIR/allowed-positions.rs:114:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ -LL | fn foreign_fn(); - | ---------------- function has no body | - = help: coverage attribute can be applied to a function (with body), impl block, or module + = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates error: aborting due to 18 previous errors -Some errors have detailed explanations: E0658, E0788. -For more information about an error, try `rustc --explain E0658`. +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/coverage-attr/name-value.rs b/tests/ui/coverage-attr/name-value.rs index 8171dbbf692..6e81ab89616 100644 --- a/tests/ui/coverage-attr/name-value.rs +++ b/tests/ui/coverage-attr/name-value.rs @@ -20,6 +20,7 @@ mod my_mod_inner { #[coverage = "off"] //~^ ERROR malformed `coverage` attribute input +//~| ERROR attribute cannot be used on struct MyStruct; #[coverage = "off"] @@ -27,18 +28,22 @@ struct MyStruct; impl MyStruct { #[coverage = "off"] //~^ ERROR malformed `coverage` attribute input + //~| ERROR attribute cannot be used on const X: u32 = 7; } #[coverage = "off"] //~^ ERROR malformed `coverage` attribute input +//~| ERROR attribute cannot be used on trait MyTrait { #[coverage = "off"] //~^ ERROR malformed `coverage` attribute input + //~| ERROR attribute cannot be used on const X: u32; #[coverage = "off"] //~^ ERROR malformed `coverage` attribute input + //~| ERROR attribute cannot be used on type T; } @@ -47,10 +52,12 @@ trait MyTrait { impl MyTrait for MyStruct { #[coverage = "off"] //~^ ERROR malformed `coverage` attribute input + //~| ERROR attribute cannot be used on const X: u32 = 8; #[coverage = "off"] //~^ ERROR malformed `coverage` attribute input + //~| ERROR attribute cannot be used on type T = (); } diff --git a/tests/ui/coverage-attr/name-value.stderr b/tests/ui/coverage-attr/name-value.stderr index a838ec5df8e..2dac2401e3c 100644 --- a/tests/ui/coverage-attr/name-value.stderr +++ b/tests/ui/coverage-attr/name-value.stderr @@ -43,8 +43,16 @@ LL - #[coverage = "off"] LL + #[coverage(on)] | +error: `#[coverage]` attribute cannot be used on structs + --> $DIR/name-value.rs:21:1 + | +LL | #[coverage = "off"] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates + error[E0539]: malformed `coverage` attribute input - --> $DIR/name-value.rs:25:1 + --> $DIR/name-value.rs:26:1 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument @@ -59,7 +67,7 @@ LL + #[coverage(on)] | error[E0539]: malformed `coverage` attribute input - --> $DIR/name-value.rs:28:5 + --> $DIR/name-value.rs:29:5 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument @@ -73,8 +81,16 @@ LL - #[coverage = "off"] LL + #[coverage(on)] | +error: `#[coverage]` attribute cannot be used on associated consts + --> $DIR/name-value.rs:29:5 + | +LL | #[coverage = "off"] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates + error[E0539]: malformed `coverage` attribute input - --> $DIR/name-value.rs:33:1 + --> $DIR/name-value.rs:35:1 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument @@ -88,8 +104,16 @@ LL - #[coverage = "off"] LL + #[coverage(on)] | +error: `#[coverage]` attribute cannot be used on traits + --> $DIR/name-value.rs:35:1 + | +LL | #[coverage = "off"] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates + error[E0539]: malformed `coverage` attribute input - --> $DIR/name-value.rs:36:5 + --> $DIR/name-value.rs:39:5 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument @@ -103,8 +127,16 @@ LL - #[coverage = "off"] LL + #[coverage(on)] | +error: `#[coverage]` attribute cannot be used on associated consts + --> $DIR/name-value.rs:39:5 + | +LL | #[coverage = "off"] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates + error[E0539]: malformed `coverage` attribute input - --> $DIR/name-value.rs:40:5 + --> $DIR/name-value.rs:44:5 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument @@ -118,8 +150,16 @@ LL - #[coverage = "off"] LL + #[coverage(on)] | +error: `#[coverage]` attribute cannot be used on associated types + --> $DIR/name-value.rs:44:5 + | +LL | #[coverage = "off"] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates + error[E0539]: malformed `coverage` attribute input - --> $DIR/name-value.rs:45:1 + --> $DIR/name-value.rs:50:1 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument @@ -134,7 +174,7 @@ LL + #[coverage(on)] | error[E0539]: malformed `coverage` attribute input - --> $DIR/name-value.rs:48:5 + --> $DIR/name-value.rs:53:5 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument @@ -148,8 +188,16 @@ LL - #[coverage = "off"] LL + #[coverage(on)] | +error: `#[coverage]` attribute cannot be used on associated consts + --> $DIR/name-value.rs:53:5 + | +LL | #[coverage = "off"] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates + error[E0539]: malformed `coverage` attribute input - --> $DIR/name-value.rs:52:5 + --> $DIR/name-value.rs:58:5 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument @@ -163,8 +211,16 @@ LL - #[coverage = "off"] LL + #[coverage(on)] | +error: `#[coverage]` attribute cannot be used on associated types + --> $DIR/name-value.rs:58:5 + | +LL | #[coverage = "off"] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates + error[E0539]: malformed `coverage` attribute input - --> $DIR/name-value.rs:57:1 + --> $DIR/name-value.rs:64:1 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument @@ -178,6 +234,6 @@ LL - #[coverage = "off"] LL + #[coverage(on)] | -error: aborting due to 12 previous errors +error: aborting due to 19 previous errors For more information about this error, try `rustc --explain E0539`. diff --git a/tests/ui/coverage-attr/word-only.rs b/tests/ui/coverage-attr/word-only.rs index 81bd558b8b0..e47279f74ca 100644 --- a/tests/ui/coverage-attr/word-only.rs +++ b/tests/ui/coverage-attr/word-only.rs @@ -20,6 +20,7 @@ mod my_mod_inner { #[coverage] //~^ ERROR malformed `coverage` attribute input +//~| ERROR attribute cannot be used on struct MyStruct; #[coverage] @@ -27,18 +28,22 @@ struct MyStruct; impl MyStruct { #[coverage] //~^ ERROR malformed `coverage` attribute input + //~| ERROR attribute cannot be used on const X: u32 = 7; } #[coverage] //~^ ERROR malformed `coverage` attribute input +//~| ERROR attribute cannot be used on trait MyTrait { #[coverage] //~^ ERROR malformed `coverage` attribute input + //~| ERROR attribute cannot be used on const X: u32; #[coverage] //~^ ERROR malformed `coverage` attribute input + //~| ERROR attribute cannot be used on type T; } @@ -47,10 +52,12 @@ trait MyTrait { impl MyTrait for MyStruct { #[coverage] //~^ ERROR malformed `coverage` attribute input + //~| ERROR attribute cannot be used on const X: u32 = 8; #[coverage] //~^ ERROR malformed `coverage` attribute input + //~| ERROR attribute cannot be used on type T = (); } diff --git a/tests/ui/coverage-attr/word-only.stderr b/tests/ui/coverage-attr/word-only.stderr index dd161360a5c..e916a817e36 100644 --- a/tests/ui/coverage-attr/word-only.stderr +++ b/tests/ui/coverage-attr/word-only.stderr @@ -39,8 +39,16 @@ LL | #[coverage(off)] LL | #[coverage(on)] | ++++ +error: `#[coverage]` attribute cannot be used on structs + --> $DIR/word-only.rs:21:1 + | +LL | #[coverage] + | ^^^^^^^^^^^ + | + = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates + error[E0539]: malformed `coverage` attribute input - --> $DIR/word-only.rs:25:1 + --> $DIR/word-only.rs:26:1 | LL | #[coverage] | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument @@ -53,7 +61,7 @@ LL | #[coverage(on)] | ++++ error[E0539]: malformed `coverage` attribute input - --> $DIR/word-only.rs:28:5 + --> $DIR/word-only.rs:29:5 | LL | #[coverage] | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument @@ -65,8 +73,16 @@ LL | #[coverage(off)] LL | #[coverage(on)] | ++++ +error: `#[coverage]` attribute cannot be used on associated consts + --> $DIR/word-only.rs:29:5 + | +LL | #[coverage] + | ^^^^^^^^^^^ + | + = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates + error[E0539]: malformed `coverage` attribute input - --> $DIR/word-only.rs:33:1 + --> $DIR/word-only.rs:35:1 | LL | #[coverage] | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument @@ -78,8 +94,16 @@ LL | #[coverage(off)] LL | #[coverage(on)] | ++++ +error: `#[coverage]` attribute cannot be used on traits + --> $DIR/word-only.rs:35:1 + | +LL | #[coverage] + | ^^^^^^^^^^^ + | + = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates + error[E0539]: malformed `coverage` attribute input - --> $DIR/word-only.rs:36:5 + --> $DIR/word-only.rs:39:5 | LL | #[coverage] | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument @@ -91,8 +115,16 @@ LL | #[coverage(off)] LL | #[coverage(on)] | ++++ +error: `#[coverage]` attribute cannot be used on associated consts + --> $DIR/word-only.rs:39:5 + | +LL | #[coverage] + | ^^^^^^^^^^^ + | + = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates + error[E0539]: malformed `coverage` attribute input - --> $DIR/word-only.rs:40:5 + --> $DIR/word-only.rs:44:5 | LL | #[coverage] | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument @@ -104,8 +136,16 @@ LL | #[coverage(off)] LL | #[coverage(on)] | ++++ +error: `#[coverage]` attribute cannot be used on associated types + --> $DIR/word-only.rs:44:5 + | +LL | #[coverage] + | ^^^^^^^^^^^ + | + = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates + error[E0539]: malformed `coverage` attribute input - --> $DIR/word-only.rs:45:1 + --> $DIR/word-only.rs:50:1 | LL | #[coverage] | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument @@ -118,7 +158,7 @@ LL | #[coverage(on)] | ++++ error[E0539]: malformed `coverage` attribute input - --> $DIR/word-only.rs:48:5 + --> $DIR/word-only.rs:53:5 | LL | #[coverage] | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument @@ -130,8 +170,16 @@ LL | #[coverage(off)] LL | #[coverage(on)] | ++++ +error: `#[coverage]` attribute cannot be used on associated consts + --> $DIR/word-only.rs:53:5 + | +LL | #[coverage] + | ^^^^^^^^^^^ + | + = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates + error[E0539]: malformed `coverage` attribute input - --> $DIR/word-only.rs:52:5 + --> $DIR/word-only.rs:58:5 | LL | #[coverage] | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument @@ -143,8 +191,16 @@ LL | #[coverage(off)] LL | #[coverage(on)] | ++++ +error: `#[coverage]` attribute cannot be used on associated types + --> $DIR/word-only.rs:58:5 + | +LL | #[coverage] + | ^^^^^^^^^^^ + | + = help: `#[coverage]` can be applied to functions, impl blocks, modules, crates + error[E0539]: malformed `coverage` attribute input - --> $DIR/word-only.rs:57:1 + --> $DIR/word-only.rs:64:1 | LL | #[coverage] | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument @@ -156,6 +212,6 @@ LL | #[coverage(off)] LL | #[coverage(on)] | ++++ -error: aborting due to 12 previous errors +error: aborting due to 19 previous errors For more information about this error, try `rustc --explain E0539`. diff --git a/tests/ui/deprecation/deprecation-sanity.rs b/tests/ui/deprecation/deprecation-sanity.rs index 80198ab8196..9698a376025 100644 --- a/tests/ui/deprecation/deprecation-sanity.rs +++ b/tests/ui/deprecation/deprecation-sanity.rs @@ -1,3 +1,5 @@ +#![deny(unused_attributes)] + // Various checks that deprecation attributes are used correctly mod bogus_attribute_types_1 { @@ -32,7 +34,8 @@ fn f1() { } struct X; -#[deprecated = "hello"] //~ ERROR this `#[deprecated]` annotation has no effect +#[deprecated = "hello"] //~ ERROR attribute cannot be used on +//~| WARN previously accepted impl Default for X { fn default() -> Self { X diff --git a/tests/ui/deprecation/deprecation-sanity.stderr b/tests/ui/deprecation/deprecation-sanity.stderr index 856f51a4b24..1d44215731d 100644 --- a/tests/ui/deprecation/deprecation-sanity.stderr +++ b/tests/ui/deprecation/deprecation-sanity.stderr @@ -1,11 +1,11 @@ error[E0541]: unknown meta item 'reason' - --> $DIR/deprecation-sanity.rs:4:43 + --> $DIR/deprecation-sanity.rs:6:43 | LL | #[deprecated(since = "a", note = "a", reason)] | ^^^^^^ expected one of `since`, `note` error[E0539]: malformed `deprecated` attribute input - --> $DIR/deprecation-sanity.rs:7:5 + --> $DIR/deprecation-sanity.rs:9:5 | LL | #[deprecated(since = "a", note)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^----^^ @@ -29,7 +29,7 @@ LL + #[deprecated(since = "version", note = "reason")] = and 1 other candidate error[E0539]: malformed `deprecated` attribute input - --> $DIR/deprecation-sanity.rs:10:5 + --> $DIR/deprecation-sanity.rs:12:5 | LL | #[deprecated(since, note = "a")] | ^^^^^^^^^^^^^-----^^^^^^^^^^^^^^ @@ -53,7 +53,7 @@ LL + #[deprecated(since = "version", note = "reason")] = and 1 other candidate error[E0539]: malformed `deprecated` attribute input - --> $DIR/deprecation-sanity.rs:13:5 + --> $DIR/deprecation-sanity.rs:15:5 | LL | #[deprecated(since = "a", note(b))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^-------^^ @@ -77,7 +77,7 @@ LL + #[deprecated(since = "version", note = "reason")] = and 1 other candidate error[E0539]: malformed `deprecated` attribute input - --> $DIR/deprecation-sanity.rs:16:5 + --> $DIR/deprecation-sanity.rs:18:5 | LL | #[deprecated(since(b), note = "a")] | ^^^^^^^^^^^^^--------^^^^^^^^^^^^^^ @@ -101,7 +101,7 @@ LL + #[deprecated(since = "version", note = "reason")] = and 1 other candidate error[E0539]: malformed `deprecated` attribute input - --> $DIR/deprecation-sanity.rs:19:5 + --> $DIR/deprecation-sanity.rs:21:5 | LL | #[deprecated(note = b"test")] | ^^^^^^^^^^^^^^^^^^^^-^^^^^^^^ @@ -111,7 +111,7 @@ LL | #[deprecated(note = b"test")] = note: expected a normal string literal, not a byte string literal error[E0565]: malformed `deprecated` attribute input - --> $DIR/deprecation-sanity.rs:22:5 + --> $DIR/deprecation-sanity.rs:24:5 | LL | #[deprecated("test")] | ^^^^^^^^^^^^^------^^ @@ -135,19 +135,19 @@ LL + #[deprecated(since = "version", note = "reason")] = and 1 other candidate error: multiple `deprecated` attributes - --> $DIR/deprecation-sanity.rs:27:1 + --> $DIR/deprecation-sanity.rs:29:1 | LL | #[deprecated(since = "a", note = "b")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/deprecation-sanity.rs:26:1 + --> $DIR/deprecation-sanity.rs:28:1 | LL | #[deprecated(since = "a", note = "b")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0538]: malformed `deprecated` attribute input - --> $DIR/deprecation-sanity.rs:30:1 + --> $DIR/deprecation-sanity.rs:32:1 | LL | #[deprecated(since = "a", since = "b", note = "c")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^^^^^^^^^^^ @@ -170,12 +170,14 @@ LL + #[deprecated(since = "version", note = "reason")] | = and 1 other candidate -error: this `#[deprecated]` annotation has no effect - --> $DIR/deprecation-sanity.rs:35:1 +error: `#[deprecated]` attribute cannot be used on trait impl blocks + --> $DIR/deprecation-sanity.rs:37:1 | LL | #[deprecated = "hello"] - | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove the unnecessary deprecation attribute + | ^^^^^^^^^^^^^^^^^^^^^^^ | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[deprecated]` can be applied to functions, data types, modules, unions, constants, statics, macro defs, type aliases, use statements, struct fields, traits, associated types, associated consts, enum variants, inherent impl blocks, crates = note: `#[deny(useless_deprecated)]` on by default error: aborting due to 10 previous errors diff --git a/tests/ui/error-codes/E0518.rs b/tests/ui/error-codes/E0518.rs deleted file mode 100644 index 9c99702ada8..00000000000 --- a/tests/ui/error-codes/E0518.rs +++ /dev/null @@ -1,9 +0,0 @@ -#[inline(always)] //~ ERROR: E0518 -struct Foo; - -#[inline(never)] //~ ERROR: E0518 -impl Foo { -} - -fn main() { -} diff --git a/tests/ui/error-codes/E0518.stderr b/tests/ui/error-codes/E0518.stderr deleted file mode 100644 index 561446f8175..00000000000 --- a/tests/ui/error-codes/E0518.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0518]: attribute should be applied to function or closure - --> $DIR/E0518.rs:1:1 - | -LL | #[inline(always)] - | ^^^^^^^^^^^^^^^^^ -LL | struct Foo; - | ----------- not a function or closure - -error[E0518]: attribute should be applied to function or closure - --> $DIR/E0518.rs:4:1 - | -LL | #[inline(never)] - | ^^^^^^^^^^^^^^^^ -LL | / impl Foo { -LL | | } - | |_- not a function or closure - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0518`. diff --git a/tests/ui/error-codes/E0718.stderr b/tests/ui/error-codes/E0718.stderr index ec7462765f8..e7784d193ba 100644 --- a/tests/ui/error-codes/E0718.stderr +++ b/tests/ui/error-codes/E0718.stderr @@ -2,7 +2,7 @@ error[E0718]: `owned_box` lang item must be applied to a struct --> $DIR/E0718.rs:4:1 | LL | #[lang = "owned_box"] - | ^^^^^^^^^^^^^^^^^^^^^ attribute should be applied to a struct, not a static item + | ^^^^^^^^^^^^^^^^^^^^^ attribute should be applied to a struct, not a static error: aborting due to 1 previous error diff --git a/tests/ui/extern/extern-no-mangle.rs b/tests/ui/extern/extern-no-mangle.rs index dba9689a075..6f2d125b923 100644 --- a/tests/ui/extern/extern-no-mangle.rs +++ b/tests/ui/extern/extern-no-mangle.rs @@ -9,21 +9,21 @@ extern "C" { #[no_mangle] - //~^ WARNING `#[no_mangle]` has no effect on a foreign static - //~^^ WARNING this was previously accepted by the compiler + //~^ WARNING attribute cannot be used on + //~| WARN previously accepted pub static FOO: u8; #[no_mangle] - //~^ WARNING `#[no_mangle]` has no effect on a foreign function - //~^^ WARNING this was previously accepted by the compiler + //~^ WARNING attribute cannot be used on + //~| WARN previously accepted pub fn bar(); } fn no_new_warn() { // Should emit the generic "not a function or static" warning #[no_mangle] - //~^ WARNING attribute should be applied to a free function, impl method or static - //~^^ WARNING this was previously accepted by the compiler + //~^ WARNING attribute cannot be used on + //~| WARN previously accepted let x = 0_u8; } diff --git a/tests/ui/extern/extern-no-mangle.stderr b/tests/ui/extern/extern-no-mangle.stderr index f20ee158ac4..b07cf0d4b4d 100644 --- a/tests/ui/extern/extern-no-mangle.stderr +++ b/tests/ui/extern/extern-no-mangle.stderr @@ -1,42 +1,34 @@ -warning: attribute should be applied to a free function, impl method or static - --> $DIR/extern-no-mangle.rs:24:5 +warning: `#[no_mangle]` attribute cannot be used on foreign statics + --> $DIR/extern-no-mangle.rs:11:5 | LL | #[no_mangle] | ^^^^^^^^^^^^ -... -LL | let x = 0_u8; - | ------------- not a free function, impl method or static | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[no_mangle]` can be applied to functions, statics note: the lint level is defined here --> $DIR/extern-no-mangle.rs:1:9 | LL | #![warn(unused_attributes)] | ^^^^^^^^^^^^^^^^^ -warning: `#[no_mangle]` has no effect on a foreign static - --> $DIR/extern-no-mangle.rs:11:5 +warning: `#[no_mangle]` attribute cannot be used on foreign functions + --> $DIR/extern-no-mangle.rs:16:5 | LL | #[no_mangle] - | ^^^^^^^^^^^^ help: remove this attribute -... -LL | pub static FOO: u8; - | ------------------- foreign static + | ^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: symbol names in extern blocks are not mangled + = help: `#[no_mangle]` can be applied to methods, functions, statics -warning: `#[no_mangle]` has no effect on a foreign function - --> $DIR/extern-no-mangle.rs:16:5 +warning: `#[no_mangle]` attribute cannot be used on statements + --> $DIR/extern-no-mangle.rs:24:5 | LL | #[no_mangle] - | ^^^^^^^^^^^^ help: remove this attribute -... -LL | pub fn bar(); - | ------------- foreign function + | ^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: symbol names in extern blocks are not mangled + = help: `#[no_mangle]` can be applied to functions, statics warning: 3 warnings emitted diff --git a/tests/ui/extern/issue-47725.rs b/tests/ui/extern/issue-47725.rs index 8ac866dc7d9..b0a0af930de 100644 --- a/tests/ui/extern/issue-47725.rs +++ b/tests/ui/extern/issue-47725.rs @@ -1,22 +1,25 @@ #![warn(unused_attributes)] //~ NOTE lint level is defined here #[link_name = "foo"] -//~^ WARN attribute should be applied to a foreign function or static [unused_attributes] -//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -struct Foo; //~ NOTE not a foreign function or static +//~^ WARN attribute cannot be used on +//~| WARN previously accepted +//~| HELP can be applied to +struct Foo; #[link_name = "foobar"] -//~^ WARN attribute should be applied to a foreign function or static [unused_attributes] -//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -//~| HELP try `#[link(name = "foobar")]` instead +//~^ WARN attribute cannot be used on +//~| WARN previously accepted +//~| HELP can be applied to extern "C" { fn foo() -> u32; } -//~^^^ NOTE not a foreign function or static #[link_name] //~^ ERROR malformed `link_name` attribute input //~| HELP must be of the form +//~| WARN attribute cannot be used on +//~| WARN previously accepted +//~| HELP can be applied to //~| NOTE for more information, visit extern "C" { fn bar() -> u32; diff --git a/tests/ui/extern/issue-47725.stderr b/tests/ui/extern/issue-47725.stderr index c5af54b8029..704b1d81b63 100644 --- a/tests/ui/extern/issue-47725.stderr +++ b/tests/ui/extern/issue-47725.stderr @@ -6,40 +6,38 @@ LL | #[link_name] | = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_name-attribute> -warning: attribute should be applied to a foreign function or static +warning: `#[link_name]` attribute cannot be used on structs --> $DIR/issue-47725.rs:3:1 | LL | #[link_name = "foo"] | ^^^^^^^^^^^^^^^^^^^^ -... -LL | struct Foo; - | ----------- not a foreign function or static | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[link_name]` can be applied to foreign functions, foreign statics note: the lint level is defined here --> $DIR/issue-47725.rs:1:9 | LL | #![warn(unused_attributes)] | ^^^^^^^^^^^^^^^^^ -warning: attribute should be applied to a foreign function or static - --> $DIR/issue-47725.rs:8:1 +warning: `#[link_name]` attribute cannot be used on foreign modules + --> $DIR/issue-47725.rs:9:1 | -LL | #[link_name = "foobar"] - | ^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | / extern "C" { -LL | | fn foo() -> u32; -LL | | } - | |_- not a foreign function or static +LL | #[link_name = "foobar"] + | ^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -help: try `#[link(name = "foobar")]` instead - --> $DIR/issue-47725.rs:8:1 + = help: `#[link_name]` can be applied to foreign functions, foreign statics + +warning: `#[link_name]` attribute cannot be used on foreign modules + --> $DIR/issue-47725.rs:17:1 | -LL | #[link_name = "foobar"] - | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[link_name] + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[link_name]` can be applied to foreign functions, foreign statics -error: aborting due to 1 previous error; 2 warnings emitted +error: aborting due to 1 previous error; 3 warnings emitted For more information about this error, try `rustc --explain E0539`. diff --git a/tests/ui/feature-gates/feature-gate-allow-internal-unstable-struct.rs b/tests/ui/feature-gates/feature-gate-allow-internal-unstable-struct.rs index 81b7fe3db2b..91caba81cb6 100644 --- a/tests/ui/feature-gates/feature-gate-allow-internal-unstable-struct.rs +++ b/tests/ui/feature-gates/feature-gate-allow-internal-unstable-struct.rs @@ -4,7 +4,7 @@ // FIXME(jdonszelmann): empty attributes are currently ignored, since when its empty no actual // change is applied. This should be fixed when later moving this check to attribute parsing. #[allow_internal_unstable(something)] //~ ERROR allow_internal_unstable side-steps -//~| ERROR attribute should +//~| ERROR attribute cannot be used on struct S; fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-allow-internal-unstable-struct.stderr b/tests/ui/feature-gates/feature-gate-allow-internal-unstable-struct.stderr index 076f2df28e3..cb8cf29e99d 100644 --- a/tests/ui/feature-gates/feature-gate-allow-internal-unstable-struct.stderr +++ b/tests/ui/feature-gates/feature-gate-allow-internal-unstable-struct.stderr @@ -7,14 +7,13 @@ LL | #[allow_internal_unstable(something)] = help: add `#![feature(allow_internal_unstable)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: attribute should be applied to a macro +error: `#[allow_internal_unstable]` attribute cannot be used on structs --> $DIR/feature-gate-allow-internal-unstable-struct.rs:6:1 | LL | #[allow_internal_unstable(something)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | struct S; - | --------- not a macro + | + = help: `#[allow_internal_unstable]` can be applied to macro defs, functions error: aborting due to 2 previous errors diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs index 7fb11b7bde7..130dd48b0fe 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs @@ -1,6 +1,4 @@ //~ NOTE: not an `extern crate` item -//~^ NOTE: not a free function, impl method or static -//~^^ NOTE: not a function or closure // This is testing whether various builtin attributes signals an // error or warning when put in "weird" places. // @@ -19,29 +17,25 @@ #![repr()] //~^ ERROR: `repr` attribute cannot be used at crate level #![path = "3800"] -//~^ ERROR: `path` attribute cannot be used at crate level +//~^ ERROR: attribute cannot be used on #![automatically_derived] -//~^ ERROR: `automatically_derived` attribute cannot be used at crate level +//~^ ERROR: attribute cannot be used on #![no_mangle] #![no_link] //~^ ERROR: attribute should be applied to an `extern crate` item #![export_name = "2200"] -//~^ ERROR: attribute should be applied to a free function, impl method or static +//~^ ERROR: attribute cannot be used on #![inline] -//~^ ERROR: attribute should be applied to function or closure +//~^ ERROR: attribute cannot be used on #[inline] -//~^ ERROR attribute should be applied to function or closure +//~^ ERROR attribute cannot be used on mod inline { - //~^ NOTE not a function or closure - //~| NOTE the inner attribute doesn't annotate this module - //~| NOTE the inner attribute doesn't annotate this module - //~| NOTE the inner attribute doesn't annotate this module + //~^ NOTE the inner attribute doesn't annotate this module //~| NOTE the inner attribute doesn't annotate this module //~| NOTE the inner attribute doesn't annotate this module mod inner { #![inline] } - //~^ ERROR attribute should be applied to function or closure - //~| NOTE not a function or closure + //~^ ERROR attribute cannot be used on #[inline = "2100"] fn f() { } //~^ ERROR valid forms for the attribute are @@ -50,16 +44,13 @@ mod inline { //~| NOTE for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> #[inline] struct S; - //~^ ERROR attribute should be applied to function or closure - //~| NOTE not a function or closure + //~^ ERROR attribute cannot be used on #[inline] type T = S; - //~^ ERROR attribute should be applied to function or closure - //~| NOTE not a function or closure + //~^ ERROR attribute cannot be used on #[inline] impl S { } - //~^ ERROR attribute should be applied to function or closure - //~| NOTE not a function or closure + //~^ ERROR attribute cannot be used on } #[no_link] @@ -89,36 +80,27 @@ mod no_link { } #[export_name = "2200"] -//~^ ERROR attribute should be applied to a free function, impl method or static +//~^ ERROR attribute cannot be used on mod export_name { - //~^ NOTE not a free function, impl method or static - mod inner { #![export_name="2200"] } - //~^ ERROR attribute should be applied to a free function, impl method or static - //~| NOTE not a free function, impl method or static + //~^ ERROR attribute cannot be used on #[export_name = "2200"] fn f() { } #[export_name = "2200"] struct S; - //~^ ERROR attribute should be applied to a free function, impl method or static - //~| NOTE not a free function, impl method or static + //~^ ERROR attribute cannot be used on #[export_name = "2200"] type T = S; - //~^ ERROR attribute should be applied to a free function, impl method or static - //~| NOTE not a free function, impl method or static + //~^ ERROR attribute cannot be used on #[export_name = "2200"] impl S { } - //~^ ERROR attribute should be applied to a free function, impl method or static - //~| NOTE not a free function, impl method or static + //~^ ERROR attribute cannot be used on trait Tr { #[export_name = "2200"] fn foo(); - //~^ ERROR attribute should be applied to a free function, impl method or static - //~| NOTE not a free function, impl method or static + //~^ ERROR attribute cannot be used on #[export_name = "2200"] fn bar() {} - //~^ ERROR attribute should be applied to a free function, impl method or static - //~| NOTE not a free function, impl method or static } } diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr index 7550e26f4a7..13dce72a882 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr @@ -1,5 +1,5 @@ error[E0658]: use of an internal attribute - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:14:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:12:1 | LL | #![rustc_main] | ^^^^^^^^^^^^^^ @@ -8,19 +8,128 @@ LL | #![rustc_main] = note: the `#[rustc_main]` attribute is an internal implementation detail that will never be stable = note: the `#[rustc_main]` attribute is used internally to specify test entry point function -error[E0518]: attribute should be applied to function or closure - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:32:1 +error: `#[path]` attribute cannot be used on crates + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:19:1 | -LL | #[inline] - | ^^^^^^^^^ -LL | -LL | / mod inline { -... | -LL | | } - | |_- not a function or closure +LL | #![path = "3800"] + | ^^^^^^^^^^^^^^^^^ + | + = help: `#[path]` can only be applied to modules + +error: `#[automatically_derived]` attribute cannot be used on crates + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:21:1 + | +LL | #![automatically_derived] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[automatically_derived]` can only be applied to trait impl blocks + +error: `#[export_name]` attribute cannot be used on crates + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:26:1 + | +LL | #![export_name = "2200"] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[export_name]` can be applied to functions, statics + +error: `#[inline]` attribute cannot be used on crates + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:28:1 + | +LL | #![inline] + | ^^^^^^^^^^ + | + = help: `#[inline]` can only be applied to functions + +error: `#[inline]` attribute cannot be used on modules + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:30:1 + | +LL | #[inline] + | ^^^^^^^^^ + | + = help: `#[inline]` can only be applied to functions + +error: `#[inline]` attribute cannot be used on modules + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:37:17 + | +LL | mod inner { #![inline] } + | ^^^^^^^^^^ + | + = help: `#[inline]` can only be applied to functions + +error: `#[inline]` attribute cannot be used on structs + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:46:5 + | +LL | #[inline] struct S; + | ^^^^^^^^^ + | + = help: `#[inline]` can only be applied to functions + +error: `#[inline]` attribute cannot be used on type aliases + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:49:5 + | +LL | #[inline] type T = S; + | ^^^^^^^^^ + | + = help: `#[inline]` can only be applied to functions + +error: `#[inline]` attribute cannot be used on inherent impl blocks + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:52:5 + | +LL | #[inline] impl S { } + | ^^^^^^^^^ + | + = help: `#[inline]` can only be applied to functions + +error: `#[export_name]` attribute cannot be used on modules + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:82:1 + | +LL | #[export_name = "2200"] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[export_name]` can be applied to functions, statics + +error: `#[export_name]` attribute cannot be used on modules + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:85:17 + | +LL | mod inner { #![export_name="2200"] } + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[export_name]` can be applied to functions, statics + +error: `#[export_name]` attribute cannot be used on structs + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:90:5 + | +LL | #[export_name = "2200"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[export_name]` can be applied to functions, statics + +error: `#[export_name]` attribute cannot be used on type aliases + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:93:5 + | +LL | #[export_name = "2200"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[export_name]` can be applied to functions, statics + +error: `#[export_name]` attribute cannot be used on inherent impl blocks + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:96:5 + | +LL | #[export_name = "2200"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[export_name]` can be applied to functions, statics + +error: `#[export_name]` attribute cannot be used on required trait methods + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:100:9 + | +LL | #[export_name = "2200"] fn foo(); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[export_name]` can be applied to statics, functions, inherent methods, provided trait methods, trait methods in impl blocks error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:65:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:56:1 | LL | #[no_link] | ^^^^^^^^^^ @@ -33,22 +142,8 @@ LL | | mod inner { #![no_link] } LL | | } | |_- not an `extern crate` item -error: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:91:1 - | -LL | #[export_name = "2200"] - | ^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | / mod export_name { -LL | | -LL | | -LL | | mod inner { #![export_name="2200"] } -... | -LL | | } - | |_- not a free function, impl method or static - error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:125:8 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:107:8 | LL | #[repr(C)] | ^ @@ -61,7 +156,7 @@ LL | | } | |_- not a struct, enum, or union error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:149:8 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:131:8 | LL | #[repr(Rust)] | ^^^^ @@ -74,25 +169,13 @@ LL | | } | |_- not a struct, enum, or union error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:26:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:24:1 | LL | #![no_link] | ^^^^^^^^^^^ not an `extern crate` item -error: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:28:1 - | -LL | #![export_name = "2200"] - | ^^^^^^^^^^^^^^^^^^^^^^^^ not a free function, impl method or static - -error[E0518]: attribute should be applied to function or closure - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:30:1 - | -LL | #![inline] - | ^^^^^^^^^^ not a function or closure - error: `macro_export` attribute cannot be used at crate level - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:12:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:10:1 | LL | #![macro_export] | ^^^^^^^^^^^^^^^^ @@ -107,7 +190,7 @@ LL + #[macro_export] | error: `rustc_main` attribute cannot be used at crate level - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:14:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:12:1 | LL | #![rustc_main] | ^^^^^^^^^^^^^^ @@ -122,7 +205,7 @@ LL + #[rustc_main] | error: `repr` attribute cannot be used at crate level - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:19:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:17:1 | LL | #![repr()] | ^^^^^^^^^^ @@ -136,176 +219,86 @@ LL - #![repr()] LL + #[repr()] | -error: `path` attribute cannot be used at crate level - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:21:1 - | -LL | #![path = "3800"] - | ^^^^^^^^^^^^^^^^^ -... -LL | mod inline { - | ------ the inner attribute doesn't annotate this module - | -help: perhaps you meant to use an outer attribute - | -LL - #![path = "3800"] -LL + #[path = "3800"] - | - -error: `automatically_derived` attribute cannot be used at crate level - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:23:1 - | -LL | #![automatically_derived] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | mod inline { - | ------ the inner attribute doesn't annotate this module - | -help: perhaps you meant to use an outer attribute - | -LL - #![automatically_derived] -LL + #[automatically_derived] - | - -error[E0518]: attribute should be applied to function or closure - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:42:17 - | -LL | mod inner { #![inline] } - | ------------^^^^^^^^^^-- not a function or closure - -error[E0518]: attribute should be applied to function or closure - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:52:5 - | -LL | #[inline] struct S; - | ^^^^^^^^^ --------- not a function or closure - -error[E0518]: attribute should be applied to function or closure - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:56:5 - | -LL | #[inline] type T = S; - | ^^^^^^^^^ ----------- not a function or closure - -error[E0518]: attribute should be applied to function or closure - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:60:5 - | -LL | #[inline] impl S { } - | ^^^^^^^^^ ---------- not a function or closure - error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:70:17 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:61:17 | LL | mod inner { #![no_link] } | ------------^^^^^^^^^^^-- not an `extern crate` item error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:74:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:65:5 | LL | #[no_link] fn f() { } | ^^^^^^^^^^ ---------- not an `extern crate` item error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:78:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:69:5 | LL | #[no_link] struct S; | ^^^^^^^^^^ --------- not an `extern crate` item error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:82:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:73:5 | LL | #[no_link]type T = S; | ^^^^^^^^^^----------- not an `extern crate` item error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:86:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:77:5 | LL | #[no_link] impl S { } | ^^^^^^^^^^ ---------- not an `extern crate` item -error: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:96:17 - | -LL | mod inner { #![export_name="2200"] } - | ------------^^^^^^^^^^^^^^^^^^^^^^-- not a free function, impl method or static - -error: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:102:5 - | -LL | #[export_name = "2200"] struct S; - | ^^^^^^^^^^^^^^^^^^^^^^^ --------- not a free function, impl method or static - -error: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:106:5 - | -LL | #[export_name = "2200"] type T = S; - | ^^^^^^^^^^^^^^^^^^^^^^^ ----------- not a free function, impl method or static - -error: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:110:5 - | -LL | #[export_name = "2200"] impl S { } - | ^^^^^^^^^^^^^^^^^^^^^^^ ---------- not a free function, impl method or static - -error: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:115:9 - | -LL | #[export_name = "2200"] fn foo(); - | ^^^^^^^^^^^^^^^^^^^^^^^ --------- not a free function, impl method or static - -error: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:119:9 - | -LL | #[export_name = "2200"] fn bar() {} - | ^^^^^^^^^^^^^^^^^^^^^^^ ----------- not a free function, impl method or static - error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:129:25 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:111:25 | LL | mod inner { #![repr(C)] } | --------------------^---- not a struct, enum, or union error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:133:12 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:115:12 | LL | #[repr(C)] fn f() { } | ^ ---------- not a struct, enum, or union error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:139:12 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:121:12 | LL | #[repr(C)] type T = S; | ^ ----------- not a struct, enum, or union error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:143:12 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:125:12 | LL | #[repr(C)] impl S { } | ^ ---------- not a struct, enum, or union error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:153:25 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:135:25 | LL | mod inner { #![repr(Rust)] } | --------------------^^^^---- not a struct, enum, or union error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:157:12 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:139:12 | LL | #[repr(Rust)] fn f() { } | ^^^^ ---------- not a struct, enum, or union error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:163:12 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:145:12 | LL | #[repr(Rust)] type T = S; | ^^^^ ----------- not a struct, enum, or union error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:167:12 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:149:12 | LL | #[repr(Rust)] impl S { } | ^^^^ ---------- not a struct, enum, or union error: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]` - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:46:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:40:5 | LL | #[inline = "2100"] fn f() { } | ^^^^^^^^^^^^^^^^^^ @@ -314,13 +307,13 @@ LL | #[inline = "2100"] fn f() { } = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> = note: `#[deny(ill_formed_attribute_input)]` on by default -error: aborting due to 38 previous errors +error: aborting due to 37 previous errors -Some errors have detailed explanations: E0517, E0518, E0658. +Some errors have detailed explanations: E0517, E0658. For more information about an error, try `rustc --explain E0517`. Future incompatibility report: Future breakage diagnostic: error: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]` - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:46:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:40:5 | LL | #[inline = "2100"] fn f() { } | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs index b93cb2ea006..8702d852a89 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs @@ -1,7 +1,4 @@ -//~ NOTE not a function -//~| NOTE not a foreign function or static -//~| NOTE cannot be applied to crates -//~| NOTE not an `extern` block +//~ NOTE not an `extern` block // This test enumerates as many compiler-builtin ungated attributes as // possible (that is, all the mutually compatible ones), and checks // that we get "expected" (*) warnings for each in the various weird @@ -50,27 +47,37 @@ #![macro_use] // (allowed if no argument; see issue-43160-gating-of-macro_use.rs) // skipping testing of cfg // skipping testing of cfg_attr -#![should_panic] //~ WARN `#[should_panic]` only has an effect -#![ignore] //~ WARN `#[ignore]` only has an effect on functions +#![should_panic] //~ WARN attribute cannot be used on +//~| WARN previously accepted +//~| HELP can only be applied to +#![ignore] //~ WARN attribute cannot be used on +//~| WARN previously accepted +//~| HELP can only be applied to #![no_implicit_prelude] #![reexport_test_harness_main = "2900"] // see gated-link-args.rs // see issue-43106-gating-of-macro_escape.rs for crate-level; but non crate-level is below at "2700" // (cannot easily test gating of crate-level #[no_std]; but non crate-level is below at "2600") -#![proc_macro_derive(Test)] //~ WARN `#[proc_macro_derive]` only has an effect +#![proc_macro_derive(Test)] //~ WARN attribute cannot be used on +//~| WARN previously accepted +//~| HELP can only be applied to #![doc = "2400"] -#![cold] //~ WARN attribute should be applied to a function -//~^ WARN this was previously accepted +#![cold] //~ WARN attribute cannot be used on +//~| WARN previously accepted +//~| HELP can only be applied to #![link()] //~ WARN attribute should be applied to an `extern` block //~^ WARN this was previously accepted #![link_name = "1900"] -//~^ WARN attribute should be applied to a foreign function -//~^^ WARN this was previously accepted by the compiler +//~^ WARN attribute cannot be used on +//~| WARN previously accepted +//~| HELP can be applied to #![link_section = "1800"] -//~^ WARN attribute should be applied to a function or static -//~^^ WARN this was previously accepted by the compiler +//~^ WARN attribute cannot be used on +//~| WARN previously accepted +//~| HELP can be applied to #![must_use] //~^ WARN `#[must_use]` has no effect +//~| HELP remove the attribute // see issue-43106-gating-of-stable.rs // see issue-43106-gating-of-unstable.rs // see issue-43106-gating-of-deprecated.rs @@ -174,16 +181,24 @@ mod macro_use { mod inner { #![macro_use] } #[macro_use] fn f() { } - //~^ WARN `#[macro_use]` only has an effect + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can be applied to #[macro_use] struct S; - //~^ WARN `#[macro_use]` only has an effect + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can be applied to #[macro_use] type T = S; - //~^ WARN `#[macro_use]` only has an effect + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can be applied to #[macro_use] impl S { } - //~^ WARN `#[macro_use]` only has an effect + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can be applied to } #[macro_export] @@ -242,116 +257,158 @@ mod path { mod inner { #![path="3800"] } #[path = "3800"] fn f() { } - //~^ WARN `#[path]` only has an effect + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can only be applied to #[path = "3800"] struct S; - //~^ WARN `#[path]` only has an effect + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can only be applied to #[path = "3800"] type T = S; - //~^ WARN `#[path]` only has an effect + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can only be applied to #[path = "3800"] impl S { } - //~^ WARN `#[path]` only has an effect + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can only be applied to } #[automatically_derived] -//~^ WARN `#[automatically_derived]` only has an effect +//~^ WARN attribute cannot be used on +//~| WARN previously accepted +//~| HELP can only be applied to mod automatically_derived { mod inner { #![automatically_derived] } - //~^ WARN `#[automatically_derived] + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can only be applied to #[automatically_derived] fn f() { } - //~^ WARN `#[automatically_derived] + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can only be applied to #[automatically_derived] struct S; - //~^ WARN `#[automatically_derived] + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can only be applied to #[automatically_derived] type T = S; - //~^ WARN `#[automatically_derived] + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can only be applied to #[automatically_derived] trait W { } - //~^ WARN `#[automatically_derived] + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can only be applied to #[automatically_derived] impl S { } - //~^ WARN `#[automatically_derived] + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can only be applied to #[automatically_derived] impl W for S { } } #[no_mangle] -//~^ WARN attribute should be applied to a free function, impl method or static [unused_attributes] -//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +//~^ WARN attribute cannot be used on +//~| WARN previously accepted +//~| HELP can be applied to mod no_mangle { - //~^ NOTE not a free function, impl method or static mod inner { #![no_mangle] } - //~^ WARN attribute should be applied to a free function, impl method or static [unused_attributes] - //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - //~| NOTE not a free function, impl method or static + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can be applied to #[no_mangle] fn f() { } #[no_mangle] struct S; - //~^ WARN attribute should be applied to a free function, impl method or static [unused_attributes] - //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - //~| NOTE not a free function, impl method or static + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can be applied to #[no_mangle] type T = S; - //~^ WARN attribute should be applied to a free function, impl method or static [unused_attributes] - //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - //~| NOTE not a free function, impl method or static + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can be applied to #[no_mangle] impl S { } - //~^ WARN attribute should be applied to a free function, impl method or static [unused_attributes] - //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - //~| NOTE not a free function, impl method or static + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can be applied to trait Tr { #[no_mangle] fn foo(); - //~^ WARN attribute should be applied to a free function, impl method or static [unused_attributes] - //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - //~| NOTE not a free function, impl method or static + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can be applied to #[no_mangle] fn bar() {} - //~^ WARN attribute should be applied to a free function, impl method or static [unused_attributes] - //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - //~| NOTE not a free function, impl method or static + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can be applied to } } #[should_panic] -//~^ WARN `#[should_panic]` only has an effect on +//~^ WARN attribute cannot be used on +//~| WARN previously accepted +//~| HELP can only be applied to mod should_panic { mod inner { #![should_panic] } - //~^ WARN `#[should_panic]` only has an effect on + //~^ WARN attribute cannot be used on + //~| WARN previously accepted + //~| HELP can only be applied to #[should_panic] fn f() { } #[should_panic] struct S; - //~^ WARN `#[should_panic]` only has an effect on + //~^ WARN attribute cannot be used on + //~| WARN previously accepted + //~| HELP can only be applied to #[should_panic] type T = S; - //~^ WARN `#[should_panic]` only has an effect on + //~^ WARN attribute cannot be used on + //~| WARN previously accepted + //~| HELP can only be applied to #[should_panic] impl S { } - //~^ WARN `#[should_panic]` only has an effect on + //~^ WARN attribute cannot be used on + //~| WARN previously accepted + //~| HELP can only be applied to } #[ignore] -//~^ WARN `#[ignore]` only has an effect on functions +//~^ WARN attribute cannot be used on +//~| WARN previously accepted +//~| HELP can only be applied to mod ignore { mod inner { #![ignore] } - //~^ WARN `#[ignore]` only has an effect on functions + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can only be applied to #[ignore] fn f() { } #[ignore] struct S; - //~^ WARN `#[ignore]` only has an effect on functions + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can only be applied to #[ignore] type T = S; - //~^ WARN `#[ignore]` only has an effect on functions + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can only be applied to #[ignore] impl S { } - //~^ WARN `#[ignore]` only has an effect on functions + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can only be applied to } #[no_implicit_prelude] @@ -359,16 +416,24 @@ mod no_implicit_prelude { mod inner { #![no_implicit_prelude] } #[no_implicit_prelude] fn f() { } - //~^ WARN `#[no_implicit_prelude]` only has an effect + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can be applied to #[no_implicit_prelude] struct S; - //~^ WARN `#[no_implicit_prelude]` only has an effect + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can be applied to #[no_implicit_prelude] type T = S; - //~^ WARN `#[no_implicit_prelude]` only has an effect + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can be applied to #[no_implicit_prelude] impl S { } - //~^ WARN `#[no_implicit_prelude]` only has an effect + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can be applied to } #[reexport_test_harness_main = "2900"] @@ -399,16 +464,24 @@ mod macro_escape { //~| HELP try an outer attribute: `#[macro_use]` #[macro_escape] fn f() { } - //~^ WARN `#[macro_escape]` only has an effect + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can be applied to #[macro_escape] struct S; - //~^ WARN `#[macro_escape]` only has an effect + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can be applied to #[macro_escape] type T = S; - //~^ WARN `#[macro_escape]` only has an effect + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can be applied to #[macro_escape] impl S { } - //~^ WARN `#[macro_escape]` only has an effect + //~^ WARN attribute cannot be used on +//~| WARN previously accepted + //~| HELP can be applied to } #[no_std] @@ -448,100 +521,97 @@ mod doc { } #[cold] -//~^ WARN attribute should be applied to a function -//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +//~^ WARN attribute cannot be used on +//~| WARN previously accepted +//~| HELP can only be applied to mod cold { - //~^ NOTE not a function mod inner { #![cold] } - //~^ WARN attribute should be applied to a function - //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - //~| NOTE not a function + //~^ WARN attribute cannot be used on + //~| WARN previously accepted + //~| HELP can only be applied to #[cold] fn f() { } #[cold] struct S; - //~^ WARN attribute should be applied to a function - //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - //~| NOTE not a function + //~^ WARN attribute cannot be used on + //~| WARN previously accepted + //~| HELP can only be applied to #[cold] type T = S; - //~^ WARN attribute should be applied to a function - //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - //~| NOTE not a function + //~^ WARN attribute cannot be used on + //~| WARN previously accepted + //~| HELP can only be applied to #[cold] impl S { } - //~^ WARN attribute should be applied to a function - //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - //~| NOTE not a function + //~^ WARN attribute cannot be used on + //~| WARN previously accepted + //~| HELP can only be applied to } #[link_name = "1900"] -//~^ WARN attribute should be applied to a foreign function or static [unused_attributes] -//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +//~^ WARN attribute cannot be used on +//~| WARN previously accepted +//~| HELP can be applied to mod link_name { - //~^ NOTE not a foreign function or static - #[link_name = "1900"] - //~^ WARN attribute should be applied to a foreign function or static [unused_attributes] - //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - //~| HELP try `#[link(name = "1900")]` instead + //~^ WARN attribute cannot be used on + //~| WARN previously accepted + //~| HELP can be applied to extern "C" { } - //~^ NOTE not a foreign function or static mod inner { #![link_name="1900"] } - //~^ WARN attribute should be applied to a foreign function or static [unused_attributes] - //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - //~| NOTE not a foreign function or static + //~^ WARN attribute cannot be used on + //~| WARN previously accepted + //~| HELP can be applied to #[link_name = "1900"] fn f() { } - //~^ WARN attribute should be applied to a foreign function or static [unused_attributes] - //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - //~| NOTE not a foreign function or static + //~^ WARN attribute cannot be used on + //~| WARN previously accepted + //~| HELP can be applied to #[link_name = "1900"] struct S; - //~^ WARN attribute should be applied to a foreign function or static [unused_attributes] - //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - //~| NOTE not a foreign function or static + //~^ WARN attribute cannot be used on + //~| WARN previously accepted + //~| HELP can be applied to #[link_name = "1900"] type T = S; - //~^ WARN attribute should be applied to a foreign function or static [unused_attributes] - //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - //~| NOTE not a foreign function or static + //~^ WARN attribute cannot be used on + //~| WARN previously accepted + //~| HELP can be applied to #[link_name = "1900"] impl S { } - //~^ WARN attribute should be applied to a foreign function or static [unused_attributes] - //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - //~| NOTE not a foreign function or static + //~^ WARN attribute cannot be used on + //~| WARN previously accepted + //~| HELP can be applied to } #[link_section = "1800"] -//~^ WARN attribute should be applied to a function or static [unused_attributes] -//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +//~^ WARN attribute cannot be used on +//~| WARN previously accepted +//~| HELP can be applied to mod link_section { - //~^ NOTE not a function or static - mod inner { #![link_section="1800"] } - //~^ WARN attribute should be applied to a function or static [unused_attributes] - //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - //~| NOTE not a function or static + //~^ WARN attribute cannot be used on + //~| WARN previously accepted + //~| HELP can be applied to #[link_section = "1800"] fn f() { } #[link_section = "1800"] struct S; - //~^ WARN attribute should be applied to a function or static [unused_attributes] - //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - //~| NOTE not a function or static + //~^ WARN attribute cannot be used on + //~| WARN previously accepted + //~| HELP can be applied to #[link_section = "1800"] type T = S; - //~^ WARN attribute should be applied to a function or static [unused_attributes] - //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - //~| NOTE not a function or static + //~^ WARN attribute cannot be used on + //~| WARN previously accepted + //~| HELP can be applied to #[link_section = "1800"] impl S { } - //~^ WARN attribute should be applied to a function or static [unused_attributes] - //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - //~| NOTE not a function or static + //~^ WARN attribute cannot be used on + //~| WARN previously accepted + //~| HELP can be applied to } @@ -599,16 +669,20 @@ mod deprecated { } #[must_use] //~ WARN `#[must_use]` has no effect +//~^ HELP remove the attribute mod must_use { mod inner { #![must_use] } //~ WARN `#[must_use]` has no effect + //~^ HELP remove the attribute #[must_use] fn f() { } #[must_use] struct S; #[must_use] type T = S; //~ WARN `#[must_use]` has no effect + //~^ HELP remove the attribute #[must_use] impl S { } //~ WARN `#[must_use]` has no effect + //~^ HELP remove the attribute } #[windows_subsystem = "windows"] diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr index f2ae50b75a3..8e2bffb91ca 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr @@ -1,5 +1,5 @@ warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:397:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:462:17 | LL | mod inner { #![macro_escape] } | ^^^^^^^^^^^^^^^^ @@ -7,292 +7,211 @@ LL | mod inner { #![macro_escape] } = help: try an outer attribute: `#[macro_use]` warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:394:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:459:1 | LL | #[macro_escape] | ^^^^^^^^^^^^^^^ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:46:9 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:43:9 | LL | #![warn(x5400)] | ^^^^^ | note: the lint level is defined here - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:40:28 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:37:28 | LL | #![warn(unused_attributes, unknown_lints)] | ^^^^^^^^^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:47:10 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:44:10 | LL | #![allow(x5300)] | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:48:11 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:45:11 | LL | #![forbid(x5200)] | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:49:9 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:46:9 | LL | #![deny(x5100)] | ^^^^^ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:96:8 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:103:8 | LL | #[warn(x5400)] | ^^^^^ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:99:25 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:106:25 | LL | mod inner { #![warn(x5400)] } | ^^^^^ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:102:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:109:12 | LL | #[warn(x5400)] fn f() { } | ^^^^^ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:105:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:112:12 | LL | #[warn(x5400)] struct S; | ^^^^^ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:108:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:115:12 | LL | #[warn(x5400)] type T = S; | ^^^^^ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:111:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:118:12 | LL | #[warn(x5400)] impl S { } | ^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:115:9 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:122:9 | LL | #[allow(x5300)] | ^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:118:26 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:125:26 | LL | mod inner { #![allow(x5300)] } | ^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:121:13 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:128:13 | LL | #[allow(x5300)] fn f() { } | ^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:124:13 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:131:13 | LL | #[allow(x5300)] struct S; | ^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:127:13 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:134:13 | LL | #[allow(x5300)] type T = S; | ^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:130:13 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:137:13 | LL | #[allow(x5300)] impl S { } | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:134:10 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:141:10 | LL | #[forbid(x5200)] | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:137:27 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:144:27 | LL | mod inner { #![forbid(x5200)] } | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:140:14 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:147:14 | LL | #[forbid(x5200)] fn f() { } | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:143:14 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:150:14 | LL | #[forbid(x5200)] struct S; | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:146:14 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:153:14 | LL | #[forbid(x5200)] type T = S; | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:149:14 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:156:14 | LL | #[forbid(x5200)] impl S { } | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:153:8 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:160:8 | LL | #[deny(x5100)] | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:156:25 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:163:25 | LL | mod inner { #![deny(x5100)] } | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:159:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:166:12 | LL | #[deny(x5100)] fn f() { } | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:162:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:169:12 | LL | #[deny(x5100)] struct S; | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:165:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:172:12 | LL | #[deny(x5100)] type T = S; | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:168:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:175:12 | LL | #[deny(x5100)] impl S { } | ^^^^^ warning: `#[macro_export]` only has an effect on macro definitions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:189:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:204:1 | LL | #[macro_export] | ^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:40:9 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:37:9 | LL | #![warn(unused_attributes, unknown_lints)] | ^^^^^^^^^^^^^^^^^ -warning: `#[automatically_derived]` only has an effect on trait implementation blocks - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:257:1 - | -LL | #[automatically_derived] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:281:1 - | -LL | #[no_mangle] - | ^^^^^^^^^^^^ -... -LL | / mod no_mangle { -LL | | -LL | | mod inner { #![no_mangle] } -... | -LL | | } - | |_- not a free function, impl method or static - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - -warning: `#[should_panic]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:321:1 - | -LL | #[should_panic] - | ^^^^^^^^^^^^^^^ - -warning: `#[ignore]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:339:1 - | -LL | #[ignore] - | ^^^^^^^^^ - warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:374:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:439:1 | LL | #[reexport_test_harness_main = "2900"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:414:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:487:1 | LL | #[no_std] | ^^^^^^^^^ -warning: attribute should be applied to a function definition - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:450:1 - | -LL | #[cold] - | ^^^^^^^ -... -LL | / mod cold { -LL | | -LL | | -LL | | mod inner { #![cold] } -... | -LL | | } - | |_- not a function definition - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - -warning: attribute should be applied to a foreign function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:479:1 - | -LL | #[link_name = "1900"] - | ^^^^^^^^^^^^^^^^^^^^^ -... -LL | / mod link_name { -LL | | -LL | | -LL | | #[link_name = "1900"] -... | -LL | | } - | |_- not a foreign function or static - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - -warning: attribute should be applied to a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:518:1 - | -LL | #[link_section = "1800"] - | ^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | / mod link_section { -LL | | -LL | | -LL | | mod inner { #![link_section="1800"] } -... | -LL | | } - | |_- not a function or static - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - warning: attribute should be applied to an `extern` block with non-Rust ABI - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:550:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:620:1 | LL | #[link()] | ^^^^^^^^^ @@ -307,564 +226,174 @@ LL | | } | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -warning: `#[must_use]` has no effect when applied to a module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:601:1 +warning: `#[must_use]` has no effect when applied to modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:671:1 | LL | #[must_use] | ^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:614:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:1 | LL | #[windows_subsystem = "windows"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:635:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:709:1 | LL | #[crate_name = "0900"] | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:654:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:728:1 | LL | #[crate_type = "0800"] | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:673:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:747:1 | LL | #[feature(x0600)] | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:693:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:767:1 | LL | #[no_main] | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:712:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:786:1 | LL | #[no_builtins] | ^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:731:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:805:1 | LL | #[recursion_limit="0200"] | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:750:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:824:1 | LL | #[type_length_limit="0100"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: attribute should be applied to an `extern` block with non-Rust ABI - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:64:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:68:1 | LL | #![link()] | ^^^^^^^^^^ not an `extern` block | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -warning: `#[ignore]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:54:1 - | -LL | #![ignore] - | ^^^^^^^^^^ - -warning: attribute should be applied to a foreign function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:66:1 - | -LL | #![link_name = "1900"] - | ^^^^^^^^^^^^^^^^^^^^^^ not a foreign function or static - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - -warning: attribute should be applied to a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:69:1 - | -LL | #![link_section = "1800"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ not a function or static - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - -warning: `#[must_use]` has no effect when applied to a module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:72:1 +warning: `#[must_use]` has no effect when applied to modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:78:1 | LL | #![must_use] | ^^^^^^^^^^^^ -warning: `#[proc_macro_derive]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:60:1 - | -LL | #![proc_macro_derive(Test)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: `#[should_panic]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:53:1 - | -LL | #![should_panic] - | ^^^^^^^^^^^^^^^^ - -warning: attribute should be applied to a function definition - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:62:1 - | -LL | #![cold] - | ^^^^^^^^ cannot be applied to crates - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - warning: the feature `rust1` has been stable since 1.0.0 and no longer requires an attribute to enable - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:85:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:92:12 | LL | #![feature(rust1)] | ^^^^^ | = note: `#[warn(stable_features)]` on by default -warning: `#[macro_use]` only has an effect on `extern crate` and modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:176:5 - | -LL | #[macro_use] fn f() { } - | ^^^^^^^^^^^^ - -warning: `#[macro_use]` only has an effect on `extern crate` and modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:179:5 - | -LL | #[macro_use] struct S; - | ^^^^^^^^^^^^ - -warning: `#[macro_use]` only has an effect on `extern crate` and modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:182:5 - | -LL | #[macro_use] type T = S; - | ^^^^^^^^^^^^ - -warning: `#[macro_use]` only has an effect on `extern crate` and modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:185:5 - | -LL | #[macro_use] impl S { } - | ^^^^^^^^^^^^ - warning: `#[macro_export]` only has an effect on macro definitions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:192:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:207:17 | LL | mod inner { #![macro_export] } | ^^^^^^^^^^^^^^^^ warning: `#[macro_export]` only has an effect on macro definitions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:195:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:210:5 | LL | #[macro_export] fn f() { } | ^^^^^^^^^^^^^^^ warning: `#[macro_export]` only has an effect on macro definitions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:198:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:213:5 | LL | #[macro_export] struct S; | ^^^^^^^^^^^^^^^ warning: `#[macro_export]` only has an effect on macro definitions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:201:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:216:5 | LL | #[macro_export] type T = S; | ^^^^^^^^^^^^^^^ warning: `#[macro_export]` only has an effect on macro definitions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:204:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:219:5 | LL | #[macro_export] impl S { } | ^^^^^^^^^^^^^^^ -warning: `#[path]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:244:5 - | -LL | #[path = "3800"] fn f() { } - | ^^^^^^^^^^^^^^^^ - -warning: `#[path]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:247:5 - | -LL | #[path = "3800"] struct S; - | ^^^^^^^^^^^^^^^^ - -warning: `#[path]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:250:5 - | -LL | #[path = "3800"] type T = S; - | ^^^^^^^^^^^^^^^^ - -warning: `#[path]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:253:5 - | -LL | #[path = "3800"] impl S { } - | ^^^^^^^^^^^^^^^^ - -warning: `#[automatically_derived]` only has an effect on trait implementation blocks - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:260:17 - | -LL | mod inner { #![automatically_derived] } - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: `#[automatically_derived]` only has an effect on trait implementation blocks - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:263:5 - | -LL | #[automatically_derived] fn f() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: `#[automatically_derived]` only has an effect on trait implementation blocks - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:266:5 - | -LL | #[automatically_derived] struct S; - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: `#[automatically_derived]` only has an effect on trait implementation blocks - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:269:5 - | -LL | #[automatically_derived] type T = S; - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: `#[automatically_derived]` only has an effect on trait implementation blocks - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:272:5 - | -LL | #[automatically_derived] trait W { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: `#[automatically_derived]` only has an effect on trait implementation blocks - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:275:5 - | -LL | #[automatically_derived] impl S { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:286:17 - | -LL | mod inner { #![no_mangle] } - | ------------^^^^^^^^^^^^^-- not a free function, impl method or static - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - -warning: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:293:5 - | -LL | #[no_mangle] struct S; - | ^^^^^^^^^^^^ --------- not a free function, impl method or static - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - -warning: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:298:5 - | -LL | #[no_mangle] type T = S; - | ^^^^^^^^^^^^ ----------- not a free function, impl method or static - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - -warning: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:303:5 - | -LL | #[no_mangle] impl S { } - | ^^^^^^^^^^^^ ---------- not a free function, impl method or static - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - -warning: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:309:9 - | -LL | #[no_mangle] fn foo(); - | ^^^^^^^^^^^^ --------- not a free function, impl method or static - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - -warning: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:314:9 - | -LL | #[no_mangle] fn bar() {} - | ^^^^^^^^^^^^ ----------- not a free function, impl method or static - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - -warning: `#[should_panic]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:324:17 - | -LL | mod inner { #![should_panic] } - | ^^^^^^^^^^^^^^^^ - -warning: `#[should_panic]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:329:5 - | -LL | #[should_panic] struct S; - | ^^^^^^^^^^^^^^^ - -warning: `#[should_panic]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:332:5 - | -LL | #[should_panic] type T = S; - | ^^^^^^^^^^^^^^^ - -warning: `#[should_panic]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:335:5 - | -LL | #[should_panic] impl S { } - | ^^^^^^^^^^^^^^^ - -warning: `#[ignore]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:342:17 - | -LL | mod inner { #![ignore] } - | ^^^^^^^^^^ - -warning: `#[ignore]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:347:5 - | -LL | #[ignore] struct S; - | ^^^^^^^^^ - -warning: `#[ignore]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:350:5 - | -LL | #[ignore] type T = S; - | ^^^^^^^^^ - -warning: `#[ignore]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:353:5 - | -LL | #[ignore] impl S { } - | ^^^^^^^^^ - -warning: `#[no_implicit_prelude]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:361:5 - | -LL | #[no_implicit_prelude] fn f() { } - | ^^^^^^^^^^^^^^^^^^^^^^ - -warning: `#[no_implicit_prelude]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:364:5 - | -LL | #[no_implicit_prelude] struct S; - | ^^^^^^^^^^^^^^^^^^^^^^ - -warning: `#[no_implicit_prelude]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:367:5 - | -LL | #[no_implicit_prelude] type T = S; - | ^^^^^^^^^^^^^^^^^^^^^^ - -warning: `#[no_implicit_prelude]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:370:5 - | -LL | #[no_implicit_prelude] impl S { } - | ^^^^^^^^^^^^^^^^^^^^^^ - warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:377:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:442:17 | LL | mod inner { #![reexport_test_harness_main="2900"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:380:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:445:5 | LL | #[reexport_test_harness_main = "2900"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:383:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:448:5 | LL | #[reexport_test_harness_main = "2900"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:386:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:451:5 | LL | #[reexport_test_harness_main = "2900"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:389:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:454:5 | LL | #[reexport_test_harness_main = "2900"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: `#[macro_escape]` only has an effect on `extern crate` and modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:401:5 - | -LL | #[macro_escape] fn f() { } - | ^^^^^^^^^^^^^^^ - -warning: `#[macro_escape]` only has an effect on `extern crate` and modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:404:5 - | -LL | #[macro_escape] struct S; - | ^^^^^^^^^^^^^^^ - -warning: `#[macro_escape]` only has an effect on `extern crate` and modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:407:5 - | -LL | #[macro_escape] type T = S; - | ^^^^^^^^^^^^^^^ - -warning: `#[macro_escape]` only has an effect on `extern crate` and modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:410:5 - | -LL | #[macro_escape] impl S { } - | ^^^^^^^^^^^^^^^ - warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:417:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:490:17 | LL | mod inner { #![no_std] } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:420:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:493:5 | LL | #[no_std] fn f() { } | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:423:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:496:5 | LL | #[no_std] struct S; | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:426:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:499:5 | LL | #[no_std] type T = S; | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:429:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:502:5 | LL | #[no_std] impl S { } | ^^^^^^^^^ -warning: attribute should be applied to a function definition - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:456:17 - | -LL | mod inner { #![cold] } - | ------------^^^^^^^^-- not a function definition - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - -warning: attribute should be applied to a function definition - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:463:5 - | -LL | #[cold] struct S; - | ^^^^^^^ --------- not a function definition - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - -warning: attribute should be applied to a function definition - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:468:5 - | -LL | #[cold] type T = S; - | ^^^^^^^ ----------- not a function definition - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - -warning: attribute should be applied to a function definition - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:473:5 - | -LL | #[cold] impl S { } - | ^^^^^^^ ---------- not a function definition - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - -warning: attribute should be applied to a foreign function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:485:5 - | -LL | #[link_name = "1900"] - | ^^^^^^^^^^^^^^^^^^^^^ -... -LL | extern "C" { } - | -------------- not a foreign function or static - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -help: try `#[link(name = "1900")]` instead - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:485:5 - | -LL | #[link_name = "1900"] - | ^^^^^^^^^^^^^^^^^^^^^ - -warning: attribute should be applied to a foreign function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:492:17 - | -LL | mod inner { #![link_name="1900"] } - | ------------^^^^^^^^^^^^^^^^^^^^-- not a foreign function or static - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - -warning: attribute should be applied to a foreign function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:497:5 - | -LL | #[link_name = "1900"] fn f() { } - | ^^^^^^^^^^^^^^^^^^^^^ ---------- not a foreign function or static - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - -warning: attribute should be applied to a foreign function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:502:5 - | -LL | #[link_name = "1900"] struct S; - | ^^^^^^^^^^^^^^^^^^^^^ --------- not a foreign function or static - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - -warning: attribute should be applied to a foreign function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:507:5 - | -LL | #[link_name = "1900"] type T = S; - | ^^^^^^^^^^^^^^^^^^^^^ ----------- not a foreign function or static - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - -warning: attribute should be applied to a foreign function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:512:5 - | -LL | #[link_name = "1900"] impl S { } - | ^^^^^^^^^^^^^^^^^^^^^ ---------- not a foreign function or static - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - -warning: attribute should be applied to a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:524:17 - | -LL | mod inner { #![link_section="1800"] } - | ------------^^^^^^^^^^^^^^^^^^^^^^^-- not a function or static - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - -warning: attribute should be applied to a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:531:5 - | -LL | #[link_section = "1800"] struct S; - | ^^^^^^^^^^^^^^^^^^^^^^^^ --------- not a function or static - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - -warning: attribute should be applied to a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:536:5 - | -LL | #[link_section = "1800"] type T = S; - | ^^^^^^^^^^^^^^^^^^^^^^^^ ----------- not a function or static - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - -warning: attribute should be applied to a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:541:5 - | -LL | #[link_section = "1800"] impl S { } - | ^^^^^^^^^^^^^^^^^^^^^^^^ ---------- not a function or static - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - warning: attribute should be applied to an `extern` block with non-Rust ABI - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:556:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:626:17 | LL | mod inner { #![link()] } | ------------^^^^^^^^^^-- not an `extern` block @@ -872,7 +401,7 @@ LL | mod inner { #![link()] } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to an `extern` block with non-Rust ABI - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:561:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:631:5 | LL | #[link()] fn f() { } | ^^^^^^^^^ ---------- not an `extern` block @@ -880,7 +409,7 @@ LL | #[link()] fn f() { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to an `extern` block with non-Rust ABI - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:566:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:636:5 | LL | #[link()] struct S; | ^^^^^^^^^ --------- not an `extern` block @@ -888,7 +417,7 @@ LL | #[link()] struct S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to an `extern` block with non-Rust ABI - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:571:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:641:5 | LL | #[link()] type T = S; | ^^^^^^^^^ ----------- not an `extern` block @@ -896,7 +425,7 @@ LL | #[link()] type T = S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to an `extern` block with non-Rust ABI - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:576:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:646:5 | LL | #[link()] impl S { } | ^^^^^^^^^ ---------- not an `extern` block @@ -904,270 +433,837 @@ LL | #[link()] impl S { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to an `extern` block with non-Rust ABI - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:581:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:651:5 | LL | #[link()] extern "Rust" {} | ^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -warning: `#[must_use]` has no effect when applied to a module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:603:17 +warning: `#[must_use]` has no effect when applied to modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:674:17 | LL | mod inner { #![must_use] } | ^^^^^^^^^^^^ -warning: `#[must_use]` has no effect when applied to a type alias - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:609:5 +warning: `#[must_use]` has no effect when applied to type aliases + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:681:5 | LL | #[must_use] type T = S; | ^^^^^^^^^^^ -warning: `#[must_use]` has no effect when applied to an inherent implementation block - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:611:5 +warning: `#[must_use]` has no effect when applied to inherent impl blocks + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:684:5 | LL | #[must_use] impl S { } | ^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:617:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:691:17 | LL | mod inner { #![windows_subsystem="windows"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:620:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:694:5 | LL | #[windows_subsystem = "windows"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:623:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:697:5 | LL | #[windows_subsystem = "windows"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:626:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:700:5 | LL | #[windows_subsystem = "windows"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:629:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:703:5 | LL | #[windows_subsystem = "windows"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:638:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:712:17 | LL | mod inner { #![crate_name="0900"] } | ^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:641:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:715:5 | LL | #[crate_name = "0900"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:644:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:718:5 | LL | #[crate_name = "0900"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:647:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:721:5 | LL | #[crate_name = "0900"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:650:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:724:5 | LL | #[crate_name = "0900"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:657:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:731:17 | LL | mod inner { #![crate_type="0800"] } | ^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:660:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:734:5 | LL | #[crate_type = "0800"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:663:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:737:5 | LL | #[crate_type = "0800"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:666:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:740:5 | LL | #[crate_type = "0800"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:669:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:743:5 | LL | #[crate_type = "0800"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:676:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:750:17 | LL | mod inner { #![feature(x0600)] } | ^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:679:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:753:5 | LL | #[feature(x0600)] fn f() { } | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:682:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:756:5 | LL | #[feature(x0600)] struct S; | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:685:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:759:5 | LL | #[feature(x0600)] type T = S; | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:762:5 | LL | #[feature(x0600)] impl S { } | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:770:17 | LL | mod inner { #![no_main] } | ^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:699:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:773:5 | LL | #[no_main] fn f() { } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:702:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:776:5 | LL | #[no_main] struct S; | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:705:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:779:5 | LL | #[no_main] type T = S; | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:708:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:782:5 | LL | #[no_main] impl S { } | ^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:715:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:789:17 | LL | mod inner { #![no_builtins] } | ^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:718:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:792:5 | LL | #[no_builtins] fn f() { } | ^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:721:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:795:5 | LL | #[no_builtins] struct S; | ^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:724:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:798:5 | LL | #[no_builtins] type T = S; | ^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:727:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:801:5 | LL | #[no_builtins] impl S { } | ^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:734:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:808:17 | LL | mod inner { #![recursion_limit="0200"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:737:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:811:5 | LL | #[recursion_limit="0200"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:740:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:814:5 | LL | #[recursion_limit="0200"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:743:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:817:5 | LL | #[recursion_limit="0200"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:746:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:820:5 | LL | #[recursion_limit="0200"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:753:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:827:17 | LL | mod inner { #![type_length_limit="0100"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:756:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:830:5 | LL | #[type_length_limit="0100"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:759:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:833:5 | LL | #[type_length_limit="0100"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:762:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:836:5 | LL | #[type_length_limit="0100"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:765:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:839:5 | LL | #[type_length_limit="0100"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +warning: `#[macro_use]` attribute cannot be used on functions + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:183:5 + | +LL | #[macro_use] fn f() { } + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[macro_use]` can be applied to modules, extern crates, crates + +warning: `#[macro_use]` attribute cannot be used on structs + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:188:5 + | +LL | #[macro_use] struct S; + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[macro_use]` can be applied to modules, extern crates, crates + +warning: `#[macro_use]` attribute cannot be used on type aliases + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:193:5 + | +LL | #[macro_use] type T = S; + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[macro_use]` can be applied to modules, extern crates, crates + +warning: `#[macro_use]` attribute cannot be used on inherent impl blocks + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:198:5 + | +LL | #[macro_use] impl S { } + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[macro_use]` can be applied to modules, extern crates, crates + +warning: `#[path]` attribute cannot be used on functions + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:259:5 + | +LL | #[path = "3800"] fn f() { } + | ^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[path]` can only be applied to modules + +warning: `#[path]` attribute cannot be used on structs + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:264:5 + | +LL | #[path = "3800"] struct S; + | ^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[path]` can only be applied to modules + +warning: `#[path]` attribute cannot be used on type aliases + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:269:5 + | +LL | #[path = "3800"] type T = S; + | ^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[path]` can only be applied to modules + +warning: `#[path]` attribute cannot be used on inherent impl blocks + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:274:5 + | +LL | #[path = "3800"] impl S { } + | ^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[path]` can only be applied to modules + +warning: `#[automatically_derived]` attribute cannot be used on modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:280:1 + | +LL | #[automatically_derived] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[automatically_derived]` can only be applied to trait impl blocks + +warning: `#[automatically_derived]` attribute cannot be used on modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:285:17 + | +LL | mod inner { #![automatically_derived] } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[automatically_derived]` can only be applied to trait impl blocks + +warning: `#[automatically_derived]` attribute cannot be used on functions + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:290:5 + | +LL | #[automatically_derived] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[automatically_derived]` can only be applied to trait impl blocks + +warning: `#[automatically_derived]` attribute cannot be used on structs + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:295:5 + | +LL | #[automatically_derived] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[automatically_derived]` can only be applied to trait impl blocks + +warning: `#[automatically_derived]` attribute cannot be used on type aliases + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:300:5 + | +LL | #[automatically_derived] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[automatically_derived]` can only be applied to trait impl blocks + +warning: `#[automatically_derived]` attribute cannot be used on traits + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:305:5 + | +LL | #[automatically_derived] trait W { } + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[automatically_derived]` can only be applied to trait impl blocks + +warning: `#[automatically_derived]` attribute cannot be used on inherent impl blocks + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:310:5 + | +LL | #[automatically_derived] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[automatically_derived]` can only be applied to trait impl blocks + +warning: `#[no_mangle]` attribute cannot be used on modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:318:1 + | +LL | #[no_mangle] + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[no_mangle]` can be applied to functions, statics + +warning: `#[no_mangle]` attribute cannot be used on modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:323:17 + | +LL | mod inner { #![no_mangle] } + | ^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[no_mangle]` can be applied to functions, statics + +warning: `#[no_mangle]` attribute cannot be used on structs + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:330:5 + | +LL | #[no_mangle] struct S; + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[no_mangle]` can be applied to functions, statics + +warning: `#[no_mangle]` attribute cannot be used on type aliases + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:335:5 + | +LL | #[no_mangle] type T = S; + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[no_mangle]` can be applied to functions, statics + +warning: `#[no_mangle]` attribute cannot be used on inherent impl blocks + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:340:5 + | +LL | #[no_mangle] impl S { } + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[no_mangle]` can be applied to functions, statics + +warning: `#[no_mangle]` attribute cannot be used on required trait methods + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:346:9 + | +LL | #[no_mangle] fn foo(); + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[no_mangle]` can be applied to functions, statics, inherent methods, trait methods in impl blocks + +warning: `#[no_mangle]` attribute cannot be used on provided trait methods + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:351:9 + | +LL | #[no_mangle] fn bar() {} + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[no_mangle]` can be applied to functions, statics, inherent methods, trait methods in impl blocks + +warning: `#[should_panic]` attribute cannot be used on modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:358:1 + | +LL | #[should_panic] + | ^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[should_panic]` can only be applied to functions + +warning: `#[should_panic]` attribute cannot be used on modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:363:17 + | +LL | mod inner { #![should_panic] } + | ^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[should_panic]` can only be applied to functions + +warning: `#[should_panic]` attribute cannot be used on structs + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:370:5 + | +LL | #[should_panic] struct S; + | ^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[should_panic]` can only be applied to functions + +warning: `#[should_panic]` attribute cannot be used on type aliases + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:375:5 + | +LL | #[should_panic] type T = S; + | ^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[should_panic]` can only be applied to functions + +warning: `#[should_panic]` attribute cannot be used on inherent impl blocks + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:380:5 + | +LL | #[should_panic] impl S { } + | ^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[should_panic]` can only be applied to functions + +warning: `#[ignore]` attribute cannot be used on modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:386:1 + | +LL | #[ignore] + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[ignore]` can only be applied to functions + +warning: `#[ignore]` attribute cannot be used on modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:391:17 + | +LL | mod inner { #![ignore] } + | ^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[ignore]` can only be applied to functions + +warning: `#[ignore]` attribute cannot be used on structs + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:398:5 + | +LL | #[ignore] struct S; + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[ignore]` can only be applied to functions + +warning: `#[ignore]` attribute cannot be used on type aliases + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:403:5 + | +LL | #[ignore] type T = S; + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[ignore]` can only be applied to functions + +warning: `#[ignore]` attribute cannot be used on inherent impl blocks + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:408:5 + | +LL | #[ignore] impl S { } + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[ignore]` can only be applied to functions + +warning: `#[no_implicit_prelude]` attribute cannot be used on functions + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:418:5 + | +LL | #[no_implicit_prelude] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[no_implicit_prelude]` can be applied to modules, crates + +warning: `#[no_implicit_prelude]` attribute cannot be used on structs + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:423:5 + | +LL | #[no_implicit_prelude] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[no_implicit_prelude]` can be applied to modules, crates + +warning: `#[no_implicit_prelude]` attribute cannot be used on type aliases + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:428:5 + | +LL | #[no_implicit_prelude] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[no_implicit_prelude]` can be applied to modules, crates + +warning: `#[no_implicit_prelude]` attribute cannot be used on inherent impl blocks + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:433:5 + | +LL | #[no_implicit_prelude] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[no_implicit_prelude]` can be applied to modules, crates + +warning: `#[macro_escape]` attribute cannot be used on functions + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:466:5 + | +LL | #[macro_escape] fn f() { } + | ^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[macro_escape]` can be applied to modules, extern crates, crates + +warning: `#[macro_escape]` attribute cannot be used on structs + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:471:5 + | +LL | #[macro_escape] struct S; + | ^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[macro_escape]` can be applied to modules, extern crates, crates + +warning: `#[macro_escape]` attribute cannot be used on type aliases + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:476:5 + | +LL | #[macro_escape] type T = S; + | ^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[macro_escape]` can be applied to modules, extern crates, crates + +warning: `#[macro_escape]` attribute cannot be used on inherent impl blocks + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:481:5 + | +LL | #[macro_escape] impl S { } + | ^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[macro_escape]` can be applied to modules, extern crates, crates + +warning: `#[cold]` attribute cannot be used on modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:523:1 + | +LL | #[cold] + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[cold]` can only be applied to functions + +warning: `#[cold]` attribute cannot be used on modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:529:17 + | +LL | mod inner { #![cold] } + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[cold]` can only be applied to functions + +warning: `#[cold]` attribute cannot be used on structs + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:536:5 + | +LL | #[cold] struct S; + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[cold]` can only be applied to functions + +warning: `#[cold]` attribute cannot be used on type aliases + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:541:5 + | +LL | #[cold] type T = S; + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[cold]` can only be applied to functions + +warning: `#[cold]` attribute cannot be used on inherent impl blocks + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:546:5 + | +LL | #[cold] impl S { } + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[cold]` can only be applied to functions + +warning: `#[link_name]` attribute cannot be used on modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:552:1 + | +LL | #[link_name = "1900"] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[link_name]` can be applied to foreign functions, foreign statics + +warning: `#[link_name]` attribute cannot be used on foreign modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:557:5 + | +LL | #[link_name = "1900"] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[link_name]` can be applied to foreign functions, foreign statics + +warning: `#[link_name]` attribute cannot be used on modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:563:17 + | +LL | mod inner { #![link_name="1900"] } + | ^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[link_name]` can be applied to foreign functions, foreign statics + +warning: `#[link_name]` attribute cannot be used on functions + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:568:5 + | +LL | #[link_name = "1900"] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[link_name]` can be applied to foreign functions, foreign statics + +warning: `#[link_name]` attribute cannot be used on structs + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:573:5 + | +LL | #[link_name = "1900"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[link_name]` can be applied to foreign functions, foreign statics + +warning: `#[link_name]` attribute cannot be used on type aliases + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:578:5 + | +LL | #[link_name = "1900"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[link_name]` can be applied to foreign functions, foreign statics + +warning: `#[link_name]` attribute cannot be used on inherent impl blocks + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:583:5 + | +LL | #[link_name = "1900"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[link_name]` can be applied to foreign functions, foreign statics + +warning: `#[link_section]` attribute cannot be used on modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:589:1 + | +LL | #[link_section = "1800"] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[link_section]` can be applied to statics, functions + +warning: `#[link_section]` attribute cannot be used on modules + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:594:17 + | +LL | mod inner { #![link_section="1800"] } + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[link_section]` can be applied to statics, functions + +warning: `#[link_section]` attribute cannot be used on structs + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:601:5 + | +LL | #[link_section = "1800"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[link_section]` can be applied to statics, functions + +warning: `#[link_section]` attribute cannot be used on type aliases + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:606:5 + | +LL | #[link_section = "1800"] type T = S; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[link_section]` can be applied to statics, functions + +warning: `#[link_section]` attribute cannot be used on inherent impl blocks + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:611:5 + | +LL | #[link_section = "1800"] impl S { } + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[link_section]` can be applied to statics, functions + +warning: `#[should_panic]` attribute cannot be used on crates + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:50:1 + | +LL | #![should_panic] + | ^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[should_panic]` can only be applied to functions + +warning: `#[ignore]` attribute cannot be used on crates + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:53:1 + | +LL | #![ignore] + | ^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[ignore]` can only be applied to functions + +warning: `#[proc_macro_derive]` attribute cannot be used on crates + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:61:1 + | +LL | #![proc_macro_derive(Test)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[proc_macro_derive]` can only be applied to functions + +warning: `#[cold]` attribute cannot be used on crates + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:65:1 + | +LL | #![cold] + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[cold]` can only be applied to functions + +warning: `#[link_name]` attribute cannot be used on crates + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:70:1 + | +LL | #![link_name = "1900"] + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[link_name]` can be applied to foreign functions, foreign statics + +warning: `#[link_section]` attribute cannot be used on crates + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:74:1 + | +LL | #![link_section = "1800"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[link_section]` can be applied to statics, functions + warning: 173 warnings emitted diff --git a/tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.rs b/tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.rs index 392880e1b3b..35392b4eff6 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.rs +++ b/tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.rs @@ -1,34 +1,29 @@ -// At time of authorship, #[proc_macro_derive = "2500"] will emit an -// error when it occurs on a mod (apart from crate-level), but will -// not descend further into the mod for other occurrences of the same -// error. -// -// This file sits on its own because the "weird" occurrences here +// This file sits on its own because the occurrences here // signal errors, making it incompatible with the "warnings only" // nature of issue-43106-gating-of-builtin-attrs.rs #[proc_macro_derive(Test)] -//~^ ERROR the `#[proc_macro_derive]` attribute may only be used on bare functions +//~^ ERROR attribute cannot be used on mod proc_macro_derive1 { mod inner { #![proc_macro_derive(Test)] } - // (no error issued here if there was one on outer module) + //~^ ERROR attribute cannot be used on } mod proc_macro_derive2 { mod inner { #![proc_macro_derive(Test)] } - //~^ ERROR the `#[proc_macro_derive]` attribute may only be used on bare functions + //~^ ERROR attribute cannot be used on #[proc_macro_derive(Test)] fn f() { } //~^ ERROR the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` #[proc_macro_derive(Test)] struct S; - //~^ ERROR the `#[proc_macro_derive]` attribute may only be used on bare functions + //~^ ERROR attribute cannot be used on #[proc_macro_derive(Test)] type T = S; - //~^ ERROR the `#[proc_macro_derive]` attribute may only be used on bare functions + //~^ ERROR attribute cannot be used on #[proc_macro_derive(Test)] impl S { } - //~^ ERROR the `#[proc_macro_derive]` attribute may only be used on bare functions + //~^ ERROR attribute cannot be used on } fn main() {} diff --git a/tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.stderr b/tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.stderr index 537032d777f..753e3e2f21d 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.stderr @@ -1,38 +1,56 @@ -error: the `#[proc_macro_derive]` attribute may only be used on bare functions - --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:10:1 +error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type + --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:16:5 + | +LL | #[proc_macro_derive(Test)] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `#[proc_macro_derive]` attribute cannot be used on modules + --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:5:1 | LL | #[proc_macro_derive(Test)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[proc_macro_derive]` can only be applied to functions -error: the `#[proc_macro_derive]` attribute may only be used on bare functions - --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:18:17 +error: `#[proc_macro_derive]` attribute cannot be used on modules + --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:8:17 | LL | mod inner { #![proc_macro_derive(Test)] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[proc_macro_derive]` can only be applied to functions -error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type - --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:21:5 +error: `#[proc_macro_derive]` attribute cannot be used on modules + --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:13:17 | -LL | #[proc_macro_derive(Test)] fn f() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | mod inner { #![proc_macro_derive(Test)] } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[proc_macro_derive]` can only be applied to functions -error: the `#[proc_macro_derive]` attribute may only be used on bare functions - --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:24:5 +error: `#[proc_macro_derive]` attribute cannot be used on structs + --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:19:5 | LL | #[proc_macro_derive(Test)] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[proc_macro_derive]` can only be applied to functions -error: the `#[proc_macro_derive]` attribute may only be used on bare functions - --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:27:5 +error: `#[proc_macro_derive]` attribute cannot be used on type aliases + --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:22:5 | LL | #[proc_macro_derive(Test)] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[proc_macro_derive]` can only be applied to functions -error: the `#[proc_macro_derive]` attribute may only be used on bare functions - --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:30:5 +error: `#[proc_macro_derive]` attribute cannot be used on inherent impl blocks + --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:25:5 | LL | #[proc_macro_derive(Test)] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[proc_macro_derive]` can only be applied to functions -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors diff --git a/tests/ui/ffi-attrs/ffi_const.rs b/tests/ui/ffi-attrs/ffi_const.rs index dddc862b0fa..caeaf8a25a9 100644 --- a/tests/ui/ffi-attrs/ffi_const.rs +++ b/tests/ui/ffi-attrs/ffi_const.rs @@ -1,16 +1,16 @@ #![feature(ffi_const)] #![crate_type = "lib"] -#[unsafe(ffi_const)] //~ ERROR `#[ffi_const]` may only be used on foreign functions +#[unsafe(ffi_const)] //~ ERROR attribute cannot be used on pub fn foo() {} -#[unsafe(ffi_const)] //~ ERROR `#[ffi_const]` may only be used on foreign functions +#[unsafe(ffi_const)] //~ ERROR attribute cannot be used on macro_rules! bar { () => {}; } extern "C" { - #[unsafe(ffi_const)] //~ ERROR `#[ffi_const]` may only be used on foreign functions + #[unsafe(ffi_const)] //~ ERROR attribute cannot be used on static INT: i32; #[ffi_const] //~ ERROR unsafe attribute used without unsafe diff --git a/tests/ui/ffi-attrs/ffi_const.stderr b/tests/ui/ffi-attrs/ffi_const.stderr index 7f31237539d..f3be9254318 100644 --- a/tests/ui/ffi-attrs/ffi_const.stderr +++ b/tests/ui/ffi-attrs/ffi_const.stderr @@ -9,24 +9,29 @@ help: wrap the attribute in `unsafe(...)` LL | #[unsafe(ffi_const)] | +++++++ + -error[E0756]: `#[ffi_const]` may only be used on foreign functions +error: `#[ffi_const]` attribute cannot be used on functions --> $DIR/ffi_const.rs:4:1 | LL | #[unsafe(ffi_const)] | ^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[ffi_const]` can only be applied to foreign functions -error[E0756]: `#[ffi_const]` may only be used on foreign functions +error: `#[ffi_const]` attribute cannot be used on macro defs --> $DIR/ffi_const.rs:7:1 | LL | #[unsafe(ffi_const)] | ^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[ffi_const]` can only be applied to foreign functions -error[E0756]: `#[ffi_const]` may only be used on foreign functions +error: `#[ffi_const]` attribute cannot be used on foreign statics --> $DIR/ffi_const.rs:13:5 | LL | #[unsafe(ffi_const)] | ^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[ffi_const]` can only be applied to foreign functions error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0756`. diff --git a/tests/ui/ffi-attrs/ffi_pure.rs b/tests/ui/ffi-attrs/ffi_pure.rs index 1f4812f55cf..c56be793919 100644 --- a/tests/ui/ffi-attrs/ffi_pure.rs +++ b/tests/ui/ffi-attrs/ffi_pure.rs @@ -1,16 +1,16 @@ #![feature(ffi_pure)] #![crate_type = "lib"] -#[unsafe(ffi_pure)] //~ ERROR `#[ffi_pure]` may only be used on foreign functions +#[unsafe(ffi_pure)] //~ ERROR attribute cannot be used on pub fn foo() {} -#[unsafe(ffi_pure)] //~ ERROR `#[ffi_pure]` may only be used on foreign functions +#[unsafe(ffi_pure)] //~ ERROR attribute cannot be used on macro_rules! bar { () => {}; } extern "C" { - #[unsafe(ffi_pure)] //~ ERROR `#[ffi_pure]` may only be used on foreign functions + #[unsafe(ffi_pure)] //~ ERROR attribute cannot be used on static INT: i32; #[ffi_pure] //~ ERROR unsafe attribute used without unsafe diff --git a/tests/ui/ffi-attrs/ffi_pure.stderr b/tests/ui/ffi-attrs/ffi_pure.stderr index bd1177c01e2..da1eae975ac 100644 --- a/tests/ui/ffi-attrs/ffi_pure.stderr +++ b/tests/ui/ffi-attrs/ffi_pure.stderr @@ -9,24 +9,29 @@ help: wrap the attribute in `unsafe(...)` LL | #[unsafe(ffi_pure)] | +++++++ + -error[E0755]: `#[ffi_pure]` may only be used on foreign functions +error: `#[ffi_pure]` attribute cannot be used on functions --> $DIR/ffi_pure.rs:4:1 | LL | #[unsafe(ffi_pure)] | ^^^^^^^^^^^^^^^^^^^ + | + = help: `#[ffi_pure]` can only be applied to foreign functions -error[E0755]: `#[ffi_pure]` may only be used on foreign functions +error: `#[ffi_pure]` attribute cannot be used on macro defs --> $DIR/ffi_pure.rs:7:1 | LL | #[unsafe(ffi_pure)] | ^^^^^^^^^^^^^^^^^^^ + | + = help: `#[ffi_pure]` can only be applied to foreign functions -error[E0755]: `#[ffi_pure]` may only be used on foreign functions +error: `#[ffi_pure]` attribute cannot be used on foreign statics --> $DIR/ffi_pure.rs:13:5 | LL | #[unsafe(ffi_pure)] | ^^^^^^^^^^^^^^^^^^^ + | + = help: `#[ffi_pure]` can only be applied to foreign functions error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0755`. diff --git a/tests/ui/force-inlining/invalid.rs b/tests/ui/force-inlining/invalid.rs index e9f5712413e..6047739992f 100644 --- a/tests/ui/force-inlining/invalid.rs +++ b/tests/ui/force-inlining/invalid.rs @@ -28,110 +28,110 @@ pub fn forced4() { } #[rustc_force_inline] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on extern crate std as other_std; #[rustc_force_inline] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on use std::collections::HashMap; #[rustc_force_inline] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on static _FOO: &'static str = "FOO"; #[rustc_force_inline] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on const _BAR: u32 = 3; #[rustc_force_inline] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on mod foo { } #[rustc_force_inline] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on unsafe extern "C" { #[rustc_force_inline] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on static X: &'static u32; #[rustc_force_inline] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on type Y; #[rustc_force_inline] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on fn foo(); } #[rustc_force_inline] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on type Foo = u32; #[rustc_force_inline] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on enum Bar<#[rustc_force_inline] T> { -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on #[rustc_force_inline] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on Baz(std::marker::PhantomData<T>), } #[rustc_force_inline] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on struct Qux { #[rustc_force_inline] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on field: u32, } #[rustc_force_inline] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on union FooBar { x: u32, y: u32, } #[rustc_force_inline] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on trait FooBaz { #[rustc_force_inline] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on type Foo; #[rustc_force_inline] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on const Bar: i32; #[rustc_force_inline] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on fn foo() {} } #[rustc_force_inline] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on trait FooQux = FooBaz; #[rustc_force_inline] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on impl<T> Bar<T> { #[rustc_force_inline] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on fn foo() {} } #[rustc_force_inline] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on impl<T> FooBaz for Bar<T> { type Foo = u32; const Bar: i32 = 3; } #[rustc_force_inline] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on macro_rules! barqux { ($foo:tt) => { $foo }; } fn barqux(#[rustc_force_inline] _x: u32) {} //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters -//~^^ ERROR attribute should be applied to a function +//~^^ ERROR attribute cannot be used on #[rustc_force_inline] //~^ ERROR attribute cannot be applied to a `async`, `gen` or `async gen` function @@ -147,16 +147,16 @@ async gen fn async_gen_foo() {} fn main() { let _x = #[rustc_force_inline] || { }; -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on let _y = #[rustc_force_inline] 3 + 4; -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on #[rustc_force_inline] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on let _z = 3; match _z { #[rustc_force_inline] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on 1 => (), _ => (), } diff --git a/tests/ui/force-inlining/invalid.stderr b/tests/ui/force-inlining/invalid.stderr index 3b3da00ae88..299a3ed4a46 100644 --- a/tests/ui/force-inlining/invalid.stderr +++ b/tests/ui/force-inlining/invalid.stderr @@ -64,322 +64,272 @@ LL - #[rustc_force_inline = 2] LL + #[rustc_force_inline] | -error: attribute should be applied to a function +error: `#[rustc_force_inline]` attribute cannot be used on extern crates --> $DIR/invalid.rs:30:1 | LL | #[rustc_force_inline] | ^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | extern crate std as other_std; - | ------------------------------ not a function definition + | + = help: `#[rustc_force_inline]` can only be applied to functions -error: attribute should be applied to a function +error: `#[rustc_force_inline]` attribute cannot be used on use statements --> $DIR/invalid.rs:34:1 | LL | #[rustc_force_inline] | ^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | use std::collections::HashMap; - | ------------------------------ not a function definition + | + = help: `#[rustc_force_inline]` can only be applied to functions -error: attribute should be applied to a function +error: `#[rustc_force_inline]` attribute cannot be used on statics --> $DIR/invalid.rs:38:1 | LL | #[rustc_force_inline] | ^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | static _FOO: &'static str = "FOO"; - | ---------------------------------- not a function definition + | + = help: `#[rustc_force_inline]` can only be applied to functions -error: attribute should be applied to a function +error: `#[rustc_force_inline]` attribute cannot be used on constants --> $DIR/invalid.rs:42:1 | LL | #[rustc_force_inline] | ^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | const _BAR: u32 = 3; - | -------------------- not a function definition + | + = help: `#[rustc_force_inline]` can only be applied to functions -error: attribute should be applied to a function +error: `#[rustc_force_inline]` attribute cannot be used on modules --> $DIR/invalid.rs:46:1 | LL | #[rustc_force_inline] | ^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | mod foo { } - | ----------- not a function definition + | + = help: `#[rustc_force_inline]` can only be applied to functions -error: attribute should be applied to a function +error: `#[rustc_force_inline]` attribute cannot be used on foreign modules --> $DIR/invalid.rs:50:1 | -LL | #[rustc_force_inline] - | ^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | / unsafe extern "C" { -LL | | #[rustc_force_inline] -LL | | -LL | | static X: &'static u32; -... | -LL | | fn foo(); -LL | | } - | |_- not a function definition - -error: attribute should be applied to a function +LL | #[rustc_force_inline] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_force_inline]` can only be applied to functions + +error: `#[rustc_force_inline]` attribute cannot be used on foreign statics + --> $DIR/invalid.rs:53:5 + | +LL | #[rustc_force_inline] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_force_inline]` can only be applied to functions + +error: `#[rustc_force_inline]` attribute cannot be used on foreign types + --> $DIR/invalid.rs:57:5 + | +LL | #[rustc_force_inline] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_force_inline]` can only be applied to functions + +error: `#[rustc_force_inline]` attribute cannot be used on foreign functions + --> $DIR/invalid.rs:61:5 + | +LL | #[rustc_force_inline] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_force_inline]` can only be applied to functions + +error: `#[rustc_force_inline]` attribute cannot be used on type aliases --> $DIR/invalid.rs:66:1 | LL | #[rustc_force_inline] | ^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | type Foo = u32; - | --------------- not a function definition + | + = help: `#[rustc_force_inline]` can only be applied to functions -error: attribute should be applied to a function +error: `#[rustc_force_inline]` attribute cannot be used on enums --> $DIR/invalid.rs:70:1 | -LL | #[rustc_force_inline] - | ^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | / enum Bar<#[rustc_force_inline] T> { -LL | | -LL | | #[rustc_force_inline] -... | -LL | | } - | |_- not a function definition - -error: attribute should be applied to a function +LL | #[rustc_force_inline] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_force_inline]` can only be applied to functions + +error: `#[rustc_force_inline]` attribute cannot be used on function params --> $DIR/invalid.rs:72:10 | LL | enum Bar<#[rustc_force_inline] T> { - | ^^^^^^^^^^^^^^^^^^^^^ - not a function definition + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_force_inline]` can only be applied to functions -error: attribute should be applied to a function +error: `#[rustc_force_inline]` attribute cannot be used on enum variants --> $DIR/invalid.rs:74:5 | LL | #[rustc_force_inline] | ^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | Baz(std::marker::PhantomData<T>), - | -------------------------------- not a function definition + | + = help: `#[rustc_force_inline]` can only be applied to functions -error: attribute should be applied to a function +error: `#[rustc_force_inline]` attribute cannot be used on structs --> $DIR/invalid.rs:79:1 | -LL | #[rustc_force_inline] - | ^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | / struct Qux { -LL | | #[rustc_force_inline] -LL | | -LL | | field: u32, -LL | | } - | |_- not a function definition - -error: attribute should be applied to a function +LL | #[rustc_force_inline] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_force_inline]` can only be applied to functions + +error: `#[rustc_force_inline]` attribute cannot be used on struct fields --> $DIR/invalid.rs:82:5 | LL | #[rustc_force_inline] | ^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | field: u32, - | ---------- not a function definition + | + = help: `#[rustc_force_inline]` can only be applied to functions -error: attribute should be applied to a function +error: `#[rustc_force_inline]` attribute cannot be used on unions --> $DIR/invalid.rs:87:1 | -LL | #[rustc_force_inline] - | ^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | / union FooBar { -LL | | x: u32, -LL | | y: u32, -LL | | } - | |_- not a function definition +LL | #[rustc_force_inline] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_force_inline]` can only be applied to functions -error: attribute should be applied to a function +error: `#[rustc_force_inline]` attribute cannot be used on traits --> $DIR/invalid.rs:94:1 | -LL | #[rustc_force_inline] - | ^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | / trait FooBaz { -LL | | #[rustc_force_inline] -LL | | -LL | | type Foo; -... | -LL | | fn foo() {} -LL | | } - | |_- not a function definition - -error: attribute should be applied to a function - --> $DIR/invalid.rs:109:1 - | LL | #[rustc_force_inline] | ^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | trait FooQux = FooBaz; - | ---------------------- not a function definition + | + = help: `#[rustc_force_inline]` can only be applied to functions -error: attribute should be applied to a function - --> $DIR/invalid.rs:113:1 +error: `#[rustc_force_inline]` attribute cannot be used on associated types + --> $DIR/invalid.rs:97:5 | -LL | #[rustc_force_inline] - | ^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | / impl<T> Bar<T> { -LL | | #[rustc_force_inline] -LL | | -LL | | fn foo() {} -LL | | } - | |_- not a function definition - -error: attribute should be applied to a function - --> $DIR/invalid.rs:121:1 +LL | #[rustc_force_inline] + | ^^^^^^^^^^^^^^^^^^^^^ | -LL | #[rustc_force_inline] - | ^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | / impl<T> FooBaz for Bar<T> { -LL | | type Foo = u32; -LL | | const Bar: i32 = 3; -LL | | } - | |_- not a function definition + = help: `#[rustc_force_inline]` can only be applied to functions -error: attribute should be applied to a function - --> $DIR/invalid.rs:128:1 +error: `#[rustc_force_inline]` attribute cannot be used on associated consts + --> $DIR/invalid.rs:100:5 + | +LL | #[rustc_force_inline] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_force_inline]` can only be applied to functions + +error: `#[rustc_force_inline]` attribute cannot be used on provided trait methods + --> $DIR/invalid.rs:104:5 + | +LL | #[rustc_force_inline] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_force_inline]` can only be applied to functions + +error: `#[rustc_force_inline]` attribute cannot be used on trait aliases + --> $DIR/invalid.rs:109:1 | LL | #[rustc_force_inline] | ^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | macro_rules! barqux { ($foo:tt) => { $foo }; } - | ---------------------------------------------- not a function definition - -error: attribute should be applied to a function - --> $DIR/invalid.rs:132:11 | -LL | fn barqux(#[rustc_force_inline] _x: u32) {} - | ^^^^^^^^^^^^^^^^^^^^^-------- - | | - | not a function definition + = help: `#[rustc_force_inline]` can only be applied to functions -error: attribute cannot be applied to a `async`, `gen` or `async gen` function - --> $DIR/invalid.rs:136:1 +error: `#[rustc_force_inline]` attribute cannot be used on inherent impl blocks + --> $DIR/invalid.rs:113:1 | LL | #[rustc_force_inline] | ^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | async fn async_foo() {} - | -------------------- `async`, `gen` or `async gen` function + | + = help: `#[rustc_force_inline]` can only be applied to functions -error: attribute cannot be applied to a `async`, `gen` or `async gen` function - --> $DIR/invalid.rs:140:1 +error: `#[rustc_force_inline]` attribute cannot be used on inherent methods + --> $DIR/invalid.rs:116:5 + | +LL | #[rustc_force_inline] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_force_inline]` can only be applied to functions + +error: `#[rustc_force_inline]` attribute cannot be used on trait impl blocks + --> $DIR/invalid.rs:121:1 | LL | #[rustc_force_inline] | ^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | gen fn gen_foo() {} - | ---------------- `async`, `gen` or `async gen` function + | + = help: `#[rustc_force_inline]` can only be applied to functions -error: attribute cannot be applied to a `async`, `gen` or `async gen` function - --> $DIR/invalid.rs:144:1 +error: `#[rustc_force_inline]` attribute cannot be used on macro defs + --> $DIR/invalid.rs:128:1 | LL | #[rustc_force_inline] | ^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | async gen fn async_gen_foo() {} - | ---------------------------- `async`, `gen` or `async gen` function + | + = help: `#[rustc_force_inline]` can only be applied to functions -error: attribute should be applied to a function +error: `#[rustc_force_inline]` attribute cannot be used on function params + --> $DIR/invalid.rs:132:11 + | +LL | fn barqux(#[rustc_force_inline] _x: u32) {} + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_force_inline]` can only be applied to functions + +error: `#[rustc_force_inline]` attribute cannot be used on closures --> $DIR/invalid.rs:149:14 | LL | let _x = #[rustc_force_inline] || { }; - | ^^^^^^^^^^^^^^^^^^^^^ ------ not a function definition + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_force_inline]` can only be applied to functions -error: attribute should be applied to a function +error: `#[rustc_force_inline]` attribute cannot be used on expressions --> $DIR/invalid.rs:151:14 | LL | let _y = #[rustc_force_inline] 3 + 4; - | ^^^^^^^^^^^^^^^^^^^^^ - not a function definition + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_force_inline]` can only be applied to functions -error: attribute should be applied to a function +error: `#[rustc_force_inline]` attribute cannot be used on statements --> $DIR/invalid.rs:153:5 | LL | #[rustc_force_inline] | ^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | let _z = 3; - | ----------- not a function definition + | + = help: `#[rustc_force_inline]` can only be applied to functions -error: attribute should be applied to a function +error: `#[rustc_force_inline]` attribute cannot be used on match arms --> $DIR/invalid.rs:158:9 | LL | #[rustc_force_inline] | ^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | 1 => (), - | ------- not a function definition - -error: attribute should be applied to a function - --> $DIR/invalid.rs:97:5 - | -LL | #[rustc_force_inline] - | ^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | type Foo; - | --------- not a function definition - -error: attribute should be applied to a function - --> $DIR/invalid.rs:100:5 - | -LL | #[rustc_force_inline] - | ^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | const Bar: i32; - | --------------- not a function definition - -error: attribute should be applied to a function - --> $DIR/invalid.rs:104:5 - | -LL | #[rustc_force_inline] - | ^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | fn foo() {} - | ----------- not a function definition - -error: attribute should be applied to a function - --> $DIR/invalid.rs:116:5 | -LL | #[rustc_force_inline] - | ^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | fn foo() {} - | ----------- not a function definition + = help: `#[rustc_force_inline]` can only be applied to functions -error: attribute should be applied to a function - --> $DIR/invalid.rs:53:5 +error: attribute cannot be applied to a `async`, `gen` or `async gen` function + --> $DIR/invalid.rs:136:1 | -LL | #[rustc_force_inline] - | ^^^^^^^^^^^^^^^^^^^^^ +LL | #[rustc_force_inline] + | ^^^^^^^^^^^^^^^^^^^^^ LL | -LL | static X: &'static u32; - | ----------------------- not a function definition +LL | async fn async_foo() {} + | -------------------- `async`, `gen` or `async gen` function -error: attribute should be applied to a function - --> $DIR/invalid.rs:57:5 +error: attribute cannot be applied to a `async`, `gen` or `async gen` function + --> $DIR/invalid.rs:140:1 | -LL | #[rustc_force_inline] - | ^^^^^^^^^^^^^^^^^^^^^ +LL | #[rustc_force_inline] + | ^^^^^^^^^^^^^^^^^^^^^ LL | -LL | type Y; - | ------- not a function definition +LL | gen fn gen_foo() {} + | ---------------- `async`, `gen` or `async gen` function -error: attribute should be applied to a function - --> $DIR/invalid.rs:61:5 +error: attribute cannot be applied to a `async`, `gen` or `async gen` function + --> $DIR/invalid.rs:144:1 | -LL | #[rustc_force_inline] - | ^^^^^^^^^^^^^^^^^^^^^ +LL | #[rustc_force_inline] + | ^^^^^^^^^^^^^^^^^^^^^ LL | -LL | fn foo(); - | --------- not a function definition +LL | async gen fn async_gen_foo() {} + | ---------------------------- `async`, `gen` or `async gen` function error: aborting due to 37 previous errors diff --git a/tests/ui/hygiene/arguments.stderr b/tests/ui/hygiene/arguments.stderr index 0d8d652b6f3..fe92daf6437 100644 --- a/tests/ui/hygiene/arguments.stderr +++ b/tests/ui/hygiene/arguments.stderr @@ -1,6 +1,9 @@ error[E0412]: cannot find type `S` in this scope --> $DIR/arguments.rs:14:8 | +LL | struct S; + | - you might have meant to refer to this struct +... LL | m!(S, S); | ^ not found in this scope diff --git a/tests/ui/hygiene/cross-crate-name-hiding-2.stderr b/tests/ui/hygiene/cross-crate-name-hiding-2.stderr index a5d509fab99..fe3a12e93a7 100644 --- a/tests/ui/hygiene/cross-crate-name-hiding-2.stderr +++ b/tests/ui/hygiene/cross-crate-name-hiding-2.stderr @@ -3,6 +3,11 @@ error[E0422]: cannot find struct, variant or union type `MyStruct` in this scope | LL | let x = MyStruct {}; | ^^^^^^^^ not found in this scope + | + ::: $DIR/auxiliary/use_by_macro.rs:15:1 + | +LL | x!(my_struct); + | ------------- you might have meant to refer to this struct error: aborting due to 1 previous error diff --git a/tests/ui/hygiene/globs.stderr b/tests/ui/hygiene/globs.stderr index 31f25b182f1..85946bf34bc 100644 --- a/tests/ui/hygiene/globs.stderr +++ b/tests/ui/hygiene/globs.stderr @@ -48,7 +48,10 @@ error[E0425]: cannot find function `f` in this scope --> $DIR/globs.rs:61:12 | LL | n!(f); - | ----- in this macro invocation + | ----- + | | | + | | you might have meant to refer to this function + | in this macro invocation ... LL | $j(); | -- due to this macro variable @@ -56,15 +59,16 @@ LL | $j(); LL | n!(f); | ^ not found in this scope | - = help: consider importing this function: - foo::f = note: this error originates in the macro `n` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0425]: cannot find function `f` in this scope --> $DIR/globs.rs:65:17 | LL | n!(f); - | ----- in this macro invocation + | ----- + | | | + | | you might have meant to refer to this function + | in this macro invocation ... LL | $j(); | -- due to this macro variable @@ -72,8 +76,6 @@ LL | $j(); LL | f | ^ not found in this scope | - = help: consider importing this function: - foo::f = note: this error originates in the macro `n` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/tests/ui/imports/issue-109148.rs b/tests/ui/imports/issue-109148.rs index 9d657a87381..49fc2fe0f5b 100644 --- a/tests/ui/imports/issue-109148.rs +++ b/tests/ui/imports/issue-109148.rs @@ -10,6 +10,7 @@ macro_rules! m { m!(); -use std::mem; +use std::mem; //~ ERROR `std` is ambiguous +use ::std::mem as _; //~ ERROR `std` is ambiguous fn main() {} diff --git a/tests/ui/imports/issue-109148.stderr b/tests/ui/imports/issue-109148.stderr index b7f1f69dc8f..ee047385ae3 100644 --- a/tests/ui/imports/issue-109148.stderr +++ b/tests/ui/imports/issue-109148.stderr @@ -9,5 +9,43 @@ LL | m!(); | = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 1 previous error +error[E0659]: `std` is ambiguous + --> $DIR/issue-109148.rs:13:5 + | +LL | use std::mem; + | ^^^ ambiguous name + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution + = note: `std` could refer to a built-in crate +note: `std` could also refer to the crate imported here + --> $DIR/issue-109148.rs:6:9 + | +LL | extern crate core as std; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | m!(); + | ---- in this macro invocation + = help: use `crate::std` to refer to this crate unambiguously + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0659]: `std` is ambiguous + --> $DIR/issue-109148.rs:14:7 + | +LL | use ::std::mem as _; + | ^^^ ambiguous name + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution + = note: `std` could refer to a built-in crate +note: `std` could also refer to the crate imported here + --> $DIR/issue-109148.rs:6:9 + | +LL | extern crate core as std; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | m!(); + | ---- in this macro invocation + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/intrinsics/bad-intrinsic-monomorphization.stderr b/tests/ui/intrinsics/bad-intrinsic-monomorphization.stderr index f49d95e9cfc..51ef71c9e29 100644 --- a/tests/ui/intrinsics/bad-intrinsic-monomorphization.stderr +++ b/tests/ui/intrinsics/bad-intrinsic-monomorphization.stderr @@ -1,8 +1,8 @@ -error[E0511]: invalid monomorphization of `cttz` intrinsic: expected basic integer type, found `Foo` - --> $DIR/bad-intrinsic-monomorphization.rs:16:5 +error[E0511]: invalid monomorphization of `simd_add` intrinsic: expected SIMD input type, found non-SIMD `Foo` + --> $DIR/bad-intrinsic-monomorphization.rs:26:5 | -LL | intrinsics::cttz(v) - | ^^^^^^^^^^^^^^^^^^^ +LL | intrinsics::simd::simd_add(a, b) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `fadd_fast` intrinsic: expected basic float type, found `Foo` --> $DIR/bad-intrinsic-monomorphization.rs:21:5 @@ -10,11 +10,11 @@ error[E0511]: invalid monomorphization of `fadd_fast` intrinsic: expected basic LL | intrinsics::fadd_fast(a, b) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `simd_add` intrinsic: expected SIMD input type, found non-SIMD `Foo` - --> $DIR/bad-intrinsic-monomorphization.rs:26:5 +error[E0511]: invalid monomorphization of `cttz` intrinsic: expected basic integer type, found `Foo` + --> $DIR/bad-intrinsic-monomorphization.rs:16:5 | -LL | intrinsics::simd::simd_add(a, b) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | intrinsics::cttz(v) + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs index 15f4a9a778e..ed15f5bba96 100644 --- a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs +++ b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs @@ -1,3 +1,4 @@ +//@ normalize-stderr: "[[:xdigit:]]{2} __ ([[:xdigit:]]{2}\s){2}" -> "HEX_DUMP" #![feature(core_intrinsics)] const RAW_EQ_PADDING: bool = unsafe { diff --git a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr index 5f4ef14d586..329da35297e 100644 --- a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr +++ b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr @@ -1,15 +1,15 @@ error[E0080]: reading memory at ALLOC0[0x0..0x4], but memory is uninitialized at [0x1..0x2], and this operation requires initialized memory - --> $DIR/intrinsic-raw_eq-const-bad.rs:4:5 + --> $DIR/intrinsic-raw_eq-const-bad.rs:5:5 | LL | std::intrinsics::raw_eq(&(1_u8, 2_u16), &(1_u8, 2_u16)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `RAW_EQ_PADDING` failed here | = note: the raw bytes of the constant (size: 4, align: 2) { - 01 __ 02 00 │ .░.. + HEX_DUMP │ .░.. } error[E0080]: unable to turn pointer into integer - --> $DIR/intrinsic-raw_eq-const-bad.rs:9:5 + --> $DIR/intrinsic-raw_eq-const-bad.rs:10:5 | LL | std::intrinsics::raw_eq(&(&0), &(&1)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `RAW_EQ_PTR` failed here @@ -18,7 +18,7 @@ LL | std::intrinsics::raw_eq(&(&0), &(&1)) = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: accessing memory with alignment 1, but alignment 4 is required - --> $DIR/intrinsic-raw_eq-const-bad.rs:16:5 + --> $DIR/intrinsic-raw_eq-const-bad.rs:17:5 | LL | std::intrinsics::raw_eq(aref, aref) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `RAW_EQ_NOT_ALIGNED` failed here diff --git a/tests/ui/intrinsics/non-integer-atomic.stderr b/tests/ui/intrinsics/non-integer-atomic.stderr index b96ee7ba846..330d313639d 100644 --- a/tests/ui/intrinsics/non-integer-atomic.stderr +++ b/tests/ui/intrinsics/non-integer-atomic.stderr @@ -1,59 +1,53 @@ -error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer or pointer type, found `bool` - --> $DIR/non-integer-atomic.rs:15:5 +error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer or pointer type, found `&dyn Fn()` + --> $DIR/non-integer-atomic.rs:55:5 | LL | intrinsics::atomic_load::<_, { SeqCst }>(p); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer or pointer type, found `bool` - --> $DIR/non-integer-atomic.rs:20:5 +error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer or pointer type, found `Foo` + --> $DIR/non-integer-atomic.rs:35:5 + | +LL | intrinsics::atomic_load::<_, { SeqCst }>(p); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer or pointer type, found `&dyn Fn()` + --> $DIR/non-integer-atomic.rs:60:5 | LL | intrinsics::atomic_store::<_, { SeqCst }>(p, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer or pointer type, found `bool` - --> $DIR/non-integer-atomic.rs:25:5 +error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer or pointer type, found `[u8; 100]` + --> $DIR/non-integer-atomic.rs:85:5 | LL | intrinsics::atomic_xchg::<_, { SeqCst }>(p, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer or pointer type, found `bool` - --> $DIR/non-integer-atomic.rs:30:5 +error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer or pointer type, found `&dyn Fn()` + --> $DIR/non-integer-atomic.rs:70:5 | LL | intrinsics::atomic_cxchg::<_, { SeqCst }, { SeqCst }>(p, v, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer or pointer type, found `Foo` - --> $DIR/non-integer-atomic.rs:35:5 - | -LL | intrinsics::atomic_load::<_, { SeqCst }>(p); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer or pointer type, found `Foo` --> $DIR/non-integer-atomic.rs:40:5 | LL | intrinsics::atomic_store::<_, { SeqCst }>(p, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer or pointer type, found `Foo` - --> $DIR/non-integer-atomic.rs:45:5 - | -LL | intrinsics::atomic_xchg::<_, { SeqCst }>(p, v); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer or pointer type, found `Foo` - --> $DIR/non-integer-atomic.rs:50:5 +error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer or pointer type, found `[u8; 100]` + --> $DIR/non-integer-atomic.rs:90:5 | LL | intrinsics::atomic_cxchg::<_, { SeqCst }, { SeqCst }>(p, v, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer or pointer type, found `&dyn Fn()` - --> $DIR/non-integer-atomic.rs:55:5 +error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer or pointer type, found `[u8; 100]` + --> $DIR/non-integer-atomic.rs:80:5 | -LL | intrinsics::atomic_load::<_, { SeqCst }>(p); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | intrinsics::atomic_store::<_, { SeqCst }>(p, v); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer or pointer type, found `&dyn Fn()` - --> $DIR/non-integer-atomic.rs:60:5 +error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer or pointer type, found `bool` + --> $DIR/non-integer-atomic.rs:20:5 | LL | intrinsics::atomic_store::<_, { SeqCst }>(p, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -64,36 +58,42 @@ error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basi LL | intrinsics::atomic_xchg::<_, { SeqCst }>(p, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer or pointer type, found `&dyn Fn()` - --> $DIR/non-integer-atomic.rs:70:5 - | -LL | intrinsics::atomic_cxchg::<_, { SeqCst }, { SeqCst }>(p, v, v); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer or pointer type, found `[u8; 100]` --> $DIR/non-integer-atomic.rs:75:5 | LL | intrinsics::atomic_load::<_, { SeqCst }>(p); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer or pointer type, found `[u8; 100]` - --> $DIR/non-integer-atomic.rs:80:5 +error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer or pointer type, found `bool` + --> $DIR/non-integer-atomic.rs:15:5 | -LL | intrinsics::atomic_store::<_, { SeqCst }>(p, v); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | intrinsics::atomic_load::<_, { SeqCst }>(p); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer or pointer type, found `[u8; 100]` - --> $DIR/non-integer-atomic.rs:85:5 +error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer or pointer type, found `bool` + --> $DIR/non-integer-atomic.rs:30:5 | -LL | intrinsics::atomic_xchg::<_, { SeqCst }>(p, v); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | intrinsics::atomic_cxchg::<_, { SeqCst }, { SeqCst }>(p, v, v); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer or pointer type, found `[u8; 100]` - --> $DIR/non-integer-atomic.rs:90:5 +error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer or pointer type, found `Foo` + --> $DIR/non-integer-atomic.rs:50:5 | LL | intrinsics::atomic_cxchg::<_, { SeqCst }, { SeqCst }>(p, v, v); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer or pointer type, found `Foo` + --> $DIR/non-integer-atomic.rs:45:5 + | +LL | intrinsics::atomic_xchg::<_, { SeqCst }>(p, v); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer or pointer type, found `bool` + --> $DIR/non-integer-atomic.rs:25:5 + | +LL | intrinsics::atomic_xchg::<_, { SeqCst }>(p, v); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: aborting due to 16 previous errors For more information about this error, try `rustc --explain E0511`. diff --git a/tests/ui/invalid/invalid_rustc_layout_scalar_valid_range.stderr b/tests/ui/invalid/invalid_rustc_layout_scalar_valid_range.stderr index 8b9ad78db37..6d5a22e4ced 100644 --- a/tests/ui/invalid/invalid_rustc_layout_scalar_valid_range.stderr +++ b/tests/ui/invalid/invalid_rustc_layout_scalar_valid_range.stderr @@ -25,6 +25,14 @@ LL | #[rustc_layout_scalar_valid_range_end(a = "a")] | | expected an integer literal here | help: must be of the form: `#[rustc_layout_scalar_valid_range_end(end)]` +error: `#[rustc_layout_scalar_valid_range_end]` attribute cannot be used on enums + --> $DIR/invalid_rustc_layout_scalar_valid_range.rs:12:1 + | +LL | #[rustc_layout_scalar_valid_range_end(1)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_layout_scalar_valid_range_end]` can only be applied to structs + error[E0539]: malformed `rustc_layout_scalar_valid_range_start` attribute input --> $DIR/invalid_rustc_layout_scalar_valid_range.rs:18:1 | @@ -34,17 +42,6 @@ LL | #[rustc_layout_scalar_valid_range_start(rustc_layout_scalar_valid_range_sta | | expected an integer literal here | help: must be of the form: `#[rustc_layout_scalar_valid_range_start(start)]` -error: attribute should be applied to a struct - --> $DIR/invalid_rustc_layout_scalar_valid_range.rs:12:1 - | -LL | #[rustc_layout_scalar_valid_range_end(1)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | / enum E { -LL | | X = 1, -LL | | Y = 14, -LL | | } - | |_- not a struct - error: aborting due to 5 previous errors Some errors have detailed explanations: E0539, E0805. diff --git a/tests/ui/issues/issue-31769.rs b/tests/ui/issues/issue-31769.rs index f56c6ea5656..354c1be9ed5 100644 --- a/tests/ui/issues/issue-31769.rs +++ b/tests/ui/issues/issue-31769.rs @@ -1,4 +1,4 @@ fn main() { - #[inline] struct Foo; //~ ERROR attribute should be applied to function or closure + #[inline] struct Foo; //~ ERROR attribute cannot be used on #[repr(C)] fn foo() {} //~ ERROR attribute should be applied to a struct, enum, or union } diff --git a/tests/ui/issues/issue-31769.stderr b/tests/ui/issues/issue-31769.stderr index 03e2f931c84..0f75e84f2a7 100644 --- a/tests/ui/issues/issue-31769.stderr +++ b/tests/ui/issues/issue-31769.stderr @@ -1,8 +1,10 @@ -error[E0518]: attribute should be applied to function or closure +error: `#[inline]` attribute cannot be used on structs --> $DIR/issue-31769.rs:2:5 | LL | #[inline] struct Foo; - | ^^^^^^^^^ ----------- not a function or closure + | ^^^^^^^^^ + | + = help: `#[inline]` can only be applied to functions error[E0517]: attribute should be applied to a struct, enum, or union --> $DIR/issue-31769.rs:3:12 @@ -12,5 +14,4 @@ LL | #[repr(C)] fn foo() {} error: aborting due to 2 previous errors -Some errors have detailed explanations: E0517, E0518. -For more information about an error, try `rustc --explain E0517`. +For more information about this error, try `rustc --explain E0517`. diff --git a/tests/ui/issues/issue-4335.stderr b/tests/ui/issues/issue-4335.stderr index b6d8f086163..d1a64e3dd46 100644 --- a/tests/ui/issues/issue-4335.stderr +++ b/tests/ui/issues/issue-4335.stderr @@ -10,7 +10,7 @@ LL | id(Box::new(|| *v)) | | | captured by this `FnMut` closure | - = help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once + = help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once help: if `T` implemented `Clone`, you could clone the value --> $DIR/issue-4335.rs:5:10 | diff --git a/tests/ui/issues/issue-43988.rs b/tests/ui/issues/issue-43988.rs index 5fea5576b7f..bd23e0e2457 100644 --- a/tests/ui/issues/issue-43988.rs +++ b/tests/ui/issues/issue-43988.rs @@ -4,12 +4,13 @@ fn main() { #[inline] let _a = 4; - //~^^ ERROR attribute should be applied to function or closure + //~^^ ERROR attribute cannot be used on #[inline(XYZ)] let _b = 4; //~^^ ERROR malformed `inline` attribute + //~| ERROR attribute cannot be used on #[repr(nothing)] let _x = 0; @@ -30,6 +31,7 @@ fn main() { #[inline(ABC)] foo(); //~^^ ERROR malformed `inline` attribute + //~| ERROR attribute cannot be used on let _z = #[repr] 1; //~^ ERROR malformed `repr` attribute diff --git a/tests/ui/issues/issue-43988.stderr b/tests/ui/issues/issue-43988.stderr index b50d691e685..0219eeb693e 100644 --- a/tests/ui/issues/issue-43988.stderr +++ b/tests/ui/issues/issue-43988.stderr @@ -1,3 +1,11 @@ +error: `#[inline]` attribute cannot be used on statements + --> $DIR/issue-43988.rs:5:5 + | +LL | #[inline] + | ^^^^^^^^^ + | + = help: `#[inline]` can only be applied to functions + error[E0539]: malformed `inline` attribute input --> $DIR/issue-43988.rs:10:5 | @@ -19,8 +27,16 @@ LL - #[inline(XYZ)] LL + #[inline] | +error: `#[inline]` attribute cannot be used on statements + --> $DIR/issue-43988.rs:10:5 + | +LL | #[inline(XYZ)] + | ^^^^^^^^^^^^^^ + | + = help: `#[inline]` can only be applied to functions + error[E0552]: unrecognized representation hint - --> $DIR/issue-43988.rs:14:12 + --> $DIR/issue-43988.rs:15:12 | LL | #[repr(nothing)] | ^^^^^^^ @@ -29,7 +45,7 @@ LL | #[repr(nothing)] = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html?highlight=repr#representations> error[E0552]: unrecognized representation hint - --> $DIR/issue-43988.rs:18:12 + --> $DIR/issue-43988.rs:19:12 | LL | #[repr(something_not_real)] | ^^^^^^^^^^^^^^^^^^ @@ -38,7 +54,7 @@ LL | #[repr(something_not_real)] = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html?highlight=repr#representations> error[E0539]: malformed `repr` attribute input - --> $DIR/issue-43988.rs:24:5 + --> $DIR/issue-43988.rs:25:5 | LL | #[repr] | ^^^^^^^ expected this to be a list @@ -57,7 +73,7 @@ LL | #[repr(align(...))] = and 2 other candidates error[E0539]: malformed `inline` attribute input - --> $DIR/issue-43988.rs:30:5 + --> $DIR/issue-43988.rs:31:5 | LL | #[inline(ABC)] | ^^^^^^^^^---^^ @@ -77,8 +93,16 @@ LL - #[inline(ABC)] LL + #[inline] | +error: `#[inline]` attribute cannot be used on expressions + --> $DIR/issue-43988.rs:31:5 + | +LL | #[inline(ABC)] + | ^^^^^^^^^^^^^^ + | + = help: `#[inline]` can only be applied to functions + error[E0539]: malformed `repr` attribute input - --> $DIR/issue-43988.rs:34:14 + --> $DIR/issue-43988.rs:36:14 | LL | let _z = #[repr] 1; | ^^^^^^^ expected this to be a list @@ -96,15 +120,7 @@ LL | let _z = #[repr(align(...))] 1; | ++++++++++++ = and 2 other candidates -error[E0518]: attribute should be applied to function or closure - --> $DIR/issue-43988.rs:5:5 - | -LL | #[inline] - | ^^^^^^^^^ -LL | let _a = 4; - | ----------- not a function or closure - -error: aborting due to 7 previous errors +error: aborting due to 9 previous errors -Some errors have detailed explanations: E0518, E0539, E0552. -For more information about an error, try `rustc --explain E0518`. +Some errors have detailed explanations: E0539, E0552. +For more information about an error, try `rustc --explain E0539`. diff --git a/tests/ui/issues/issue-78957.rs b/tests/ui/issues/issue-78957.rs index 567c59fd560..2ff92612e18 100644 --- a/tests/ui/issues/issue-78957.rs +++ b/tests/ui/issues/issue-78957.rs @@ -3,26 +3,26 @@ use std::marker::PhantomData; pub struct Foo<#[inline] const N: usize>; -//~^ ERROR attribute should be applied to function or closure +//~^ ERROR attribute cannot be used on pub struct Bar<#[cold] const N: usize>; -//~^ ERROR attribute should be applied to a function -//~| WARN this was previously accepted +//~^ ERROR attribute cannot be used on +//~| WARN previously accepted pub struct Baz<#[repr(C)] const N: usize>; //~^ ERROR attribute should be applied to a struct, enum, or union // pub struct Foo2<#[inline] 'a>(PhantomData<&'a ()>); -//~^ ERROR attribute should be applied to function or closure +//~^ ERROR attribute cannot be used on pub struct Bar2<#[cold] 'a>(PhantomData<&'a ()>); -//~^ ERROR attribute should be applied to a function -//~| WARN this was previously accepted +//~^ ERROR attribute cannot be used on +//~| WARN previously accepted pub struct Baz2<#[repr(C)] 'a>(PhantomData<&'a ()>); //~^ ERROR attribute should be applied to a struct, enum, or union // pub struct Foo3<#[inline] T>(PhantomData<T>); -//~^ ERROR attribute should be applied to function or closure +//~^ ERROR attribute cannot be used on pub struct Bar3<#[cold] T>(PhantomData<T>); -//~^ ERROR attribute should be applied to a function -//~| WARN this was previously accepted +//~^ ERROR attribute cannot be used on +//~| WARN previously accepted pub struct Baz3<#[repr(C)] T>(PhantomData<T>); //~^ ERROR attribute should be applied to a struct, enum, or union diff --git a/tests/ui/issues/issue-78957.stderr b/tests/ui/issues/issue-78957.stderr index 6de22d6bf79..d271b1840fb 100644 --- a/tests/ui/issues/issue-78957.stderr +++ b/tests/ui/issues/issue-78957.stderr @@ -1,21 +1,26 @@ -error[E0518]: attribute should be applied to function or closure +error: `#[inline]` attribute cannot be used on function params --> $DIR/issue-78957.rs:5:16 | LL | pub struct Foo<#[inline] const N: usize>; - | ^^^^^^^^^ -------------- not a function or closure + | ^^^^^^^^^ + | + = help: `#[inline]` can only be applied to functions -error: attribute should be applied to a function definition - --> $DIR/issue-78957.rs:7:16 +error: `#[inline]` attribute cannot be used on function params + --> $DIR/issue-78957.rs:13:17 | -LL | pub struct Bar<#[cold] const N: usize>; - | ^^^^^^^ -------------- not a function definition +LL | pub struct Foo2<#[inline] 'a>(PhantomData<&'a ()>); + | ^^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -note: the lint level is defined here - --> $DIR/issue-78957.rs:1:9 + = help: `#[inline]` can only be applied to functions + +error: `#[inline]` attribute cannot be used on function params + --> $DIR/issue-78957.rs:21:17 | -LL | #![deny(unused_attributes)] - | ^^^^^^^^^^^^^^^^^ +LL | pub struct Foo3<#[inline] T>(PhantomData<T>); + | ^^^^^^^^^ + | + = help: `#[inline]` can only be applied to functions error[E0517]: attribute should be applied to a struct, enum, or union --> $DIR/issue-78957.rs:10:23 @@ -23,47 +28,50 @@ error[E0517]: attribute should be applied to a struct, enum, or union LL | pub struct Baz<#[repr(C)] const N: usize>; | ^ -------------- not a struct, enum, or union -error[E0518]: attribute should be applied to function or closure - --> $DIR/issue-78957.rs:13:17 +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/issue-78957.rs:18:24 | -LL | pub struct Foo2<#[inline] 'a>(PhantomData<&'a ()>); - | ^^^^^^^^^ -- not a function or closure +LL | pub struct Baz2<#[repr(C)] 'a>(PhantomData<&'a ()>); + | ^ -- not a struct, enum, or union -error: attribute should be applied to a function definition - --> $DIR/issue-78957.rs:15:17 +error[E0517]: attribute should be applied to a struct, enum, or union + --> $DIR/issue-78957.rs:26:24 | -LL | pub struct Bar2<#[cold] 'a>(PhantomData<&'a ()>); - | ^^^^^^^ -- not a function definition +LL | pub struct Baz3<#[repr(C)] T>(PhantomData<T>); + | ^ - not a struct, enum, or union + +error: `#[cold]` attribute cannot be used on function params + --> $DIR/issue-78957.rs:7:16 + | +LL | pub struct Bar<#[cold] const N: usize>; + | ^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - -error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-78957.rs:18:24 + = help: `#[cold]` can only be applied to functions +note: the lint level is defined here + --> $DIR/issue-78957.rs:1:9 | -LL | pub struct Baz2<#[repr(C)] 'a>(PhantomData<&'a ()>); - | ^ -- not a struct, enum, or union +LL | #![deny(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ -error[E0518]: attribute should be applied to function or closure - --> $DIR/issue-78957.rs:21:17 +error: `#[cold]` attribute cannot be used on function params + --> $DIR/issue-78957.rs:15:17 | -LL | pub struct Foo3<#[inline] T>(PhantomData<T>); - | ^^^^^^^^^ - not a function or closure +LL | pub struct Bar2<#[cold] 'a>(PhantomData<&'a ()>); + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[cold]` can only be applied to functions -error: attribute should be applied to a function definition +error: `#[cold]` attribute cannot be used on function params --> $DIR/issue-78957.rs:23:17 | LL | pub struct Bar3<#[cold] T>(PhantomData<T>); - | ^^^^^^^ - not a function definition + | ^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - -error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-78957.rs:26:24 - | -LL | pub struct Baz3<#[repr(C)] T>(PhantomData<T>); - | ^ - not a struct, enum, or union + = help: `#[cold]` can only be applied to functions error: aborting due to 9 previous errors -Some errors have detailed explanations: E0517, E0518. -For more information about an error, try `rustc --explain E0517`. +For more information about this error, try `rustc --explain E0517`. diff --git a/tests/ui/linkage-attr/linkage3.rs b/tests/ui/linkage-attr/linkage3.rs index f95e5eecc48..74a6fd6600b 100644 --- a/tests/ui/linkage-attr/linkage3.rs +++ b/tests/ui/linkage-attr/linkage3.rs @@ -5,7 +5,7 @@ extern "C" { #[linkage = "foo"] static foo: *const i32; -//~^ ERROR: invalid linkage specified +//~^^ ERROR: malformed `linkage` attribute input [E0539] } fn main() { diff --git a/tests/ui/linkage-attr/linkage3.stderr b/tests/ui/linkage-attr/linkage3.stderr index 5f7b7ef227c..f1215f09aea 100644 --- a/tests/ui/linkage-attr/linkage3.stderr +++ b/tests/ui/linkage-attr/linkage3.stderr @@ -1,8 +1,27 @@ -error: invalid linkage specified - --> $DIR/linkage3.rs:7:5 +error[E0539]: malformed `linkage` attribute input + --> $DIR/linkage3.rs:6:5 | -LL | static foo: *const i32; - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | #[linkage = "foo"] + | ^^^^^^^^^^^^-----^ + | | + | valid arguments are `available_externally`, `common`, `extern_weak`, `external`, `internal`, `linkonce`, `linkonce_odr`, `weak` or `weak_odr` + | +help: try changing it to one of the following valid forms of the attribute + | +LL - #[linkage = "foo"] +LL + #[linkage = "available_externally"] + | +LL - #[linkage = "foo"] +LL + #[linkage = "common"] + | +LL - #[linkage = "foo"] +LL + #[linkage = "extern_weak"] + | +LL - #[linkage = "foo"] +LL + #[linkage = "external"] + | + = and 5 other candidates error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0539`. diff --git a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.rs index 5982c771033..301e690be38 100644 --- a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.rs +++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.rs @@ -1,13 +1,13 @@ #[link_ordinal(123)] -//~^ ERROR attribute should be applied to a foreign function or static +//~^ ERROR attribute cannot be used on struct Foo {} #[link_ordinal(123)] -//~^ ERROR attribute should be applied to a foreign function or static +//~^ ERROR attribute cannot be used on fn test() {} #[link_ordinal(42)] -//~^ ERROR attribute should be applied to a foreign function or static +//~^ ERROR attribute cannot be used on static mut imported_val: i32 = 123; #[link(name = "exporter", kind = "raw-dylib")] diff --git a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.stderr index 8f279508720..c561373db77 100644 --- a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.stderr +++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.stderr @@ -1,20 +1,26 @@ -error: attribute should be applied to a foreign function or static +error: `#[link_ordinal]` attribute cannot be used on structs --> $DIR/link-ordinal-not-foreign-fn.rs:1:1 | LL | #[link_ordinal(123)] | ^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[link_ordinal]` can be applied to foreign functions, foreign statics -error: attribute should be applied to a foreign function or static +error: `#[link_ordinal]` attribute cannot be used on functions --> $DIR/link-ordinal-not-foreign-fn.rs:5:1 | LL | #[link_ordinal(123)] | ^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[link_ordinal]` can be applied to foreign functions, foreign statics -error: attribute should be applied to a foreign function or static +error: `#[link_ordinal]` attribute cannot be used on statics --> $DIR/link-ordinal-not-foreign-fn.rs:9:1 | LL | #[link_ordinal(42)] | ^^^^^^^^^^^^^^^^^^^ + | + = help: `#[link_ordinal]` can be applied to foreign functions, foreign statics error: aborting due to 3 previous errors diff --git a/tests/ui/lint/inline-trait-and-foreign-items.rs b/tests/ui/lint/inline-trait-and-foreign-items.rs index 39bc01f71b5..d41a09dee96 100644 --- a/tests/ui/lint/inline-trait-and-foreign-items.rs +++ b/tests/ui/lint/inline-trait-and-foreign-items.rs @@ -4,33 +4,33 @@ #![warn(unused_attributes)] trait Trait { - #[inline] //~ WARN `#[inline]` is ignored on constants - //~^ WARN this was previously accepted + #[inline] //~ WARN attribute cannot be used on +//~| WARN previously accepted const X: u32; - #[inline] //~ ERROR attribute should be applied to function or closure + #[inline] //~ ERROR attribute cannot be used on type T; type U; } impl Trait for () { - #[inline] //~ WARN `#[inline]` is ignored on constants - //~^ WARN this was previously accepted + #[inline] //~ WARN attribute cannot be used on +//~| WARN previously accepted const X: u32 = 0; - #[inline] //~ ERROR attribute should be applied to function or closure + #[inline] //~ ERROR attribute cannot be used on type T = Self; - #[inline] //~ ERROR attribute should be applied to function or closure + #[inline] //~ ERROR attribute cannot be used on type U = impl Trait; //~ ERROR unconstrained opaque type } extern "C" { - #[inline] //~ ERROR attribute should be applied to function or closure + #[inline] //~ ERROR attribute cannot be used on static X: u32; - #[inline] //~ ERROR attribute should be applied to function or closure + #[inline] //~ ERROR attribute cannot be used on type T; } diff --git a/tests/ui/lint/inline-trait-and-foreign-items.stderr b/tests/ui/lint/inline-trait-and-foreign-items.stderr index 2f1fb4c46c0..4bde4bc590a 100644 --- a/tests/ui/lint/inline-trait-and-foreign-items.stderr +++ b/tests/ui/lint/inline-trait-and-foreign-items.stderr @@ -1,65 +1,42 @@ -warning: `#[inline]` is ignored on constants - --> $DIR/inline-trait-and-foreign-items.rs:7:5 - | -LL | #[inline] - | ^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: see issue #65833 <https://github.com/rust-lang/rust/issues/65833> for more information -note: the lint level is defined here - --> $DIR/inline-trait-and-foreign-items.rs:4:9 - | -LL | #![warn(unused_attributes)] - | ^^^^^^^^^^^^^^^^^ - -error[E0518]: attribute should be applied to function or closure +error: `#[inline]` attribute cannot be used on associated types --> $DIR/inline-trait-and-foreign-items.rs:11:5 | LL | #[inline] | ^^^^^^^^^ -LL | type T; - | ------- not a function or closure - -warning: `#[inline]` is ignored on constants - --> $DIR/inline-trait-and-foreign-items.rs:18:5 - | -LL | #[inline] - | ^^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: see issue #65833 <https://github.com/rust-lang/rust/issues/65833> for more information + = help: `#[inline]` can only be applied to functions -error[E0518]: attribute should be applied to function or closure +error: `#[inline]` attribute cannot be used on associated types --> $DIR/inline-trait-and-foreign-items.rs:22:5 | LL | #[inline] | ^^^^^^^^^ -LL | type T = Self; - | -------------- not a function or closure + | + = help: `#[inline]` can only be applied to functions -error[E0518]: attribute should be applied to function or closure +error: `#[inline]` attribute cannot be used on associated types --> $DIR/inline-trait-and-foreign-items.rs:25:5 | LL | #[inline] | ^^^^^^^^^ -LL | type U = impl Trait; - | -------------------- not a function or closure + | + = help: `#[inline]` can only be applied to functions -error[E0518]: attribute should be applied to function or closure +error: `#[inline]` attribute cannot be used on foreign statics --> $DIR/inline-trait-and-foreign-items.rs:30:5 | LL | #[inline] | ^^^^^^^^^ -LL | static X: u32; - | -------------- not a function or closure + | + = help: `#[inline]` can only be applied to functions -error[E0518]: attribute should be applied to function or closure +error: `#[inline]` attribute cannot be used on foreign types --> $DIR/inline-trait-and-foreign-items.rs:33:5 | LL | #[inline] | ^^^^^^^^^ -LL | type T; - | ------- not a function or closure + | + = help: `#[inline]` can only be applied to functions error: unconstrained opaque type --> $DIR/inline-trait-and-foreign-items.rs:26:14 @@ -69,6 +46,28 @@ LL | type U = impl Trait; | = note: `U` must be used in combination with a concrete type within the same impl +warning: `#[inline]` attribute cannot be used on associated consts + --> $DIR/inline-trait-and-foreign-items.rs:7:5 + | +LL | #[inline] + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[inline]` can only be applied to functions +note: the lint level is defined here + --> $DIR/inline-trait-and-foreign-items.rs:4:9 + | +LL | #![warn(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +warning: `#[inline]` attribute cannot be used on associated consts + --> $DIR/inline-trait-and-foreign-items.rs:18:5 + | +LL | #[inline] + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[inline]` can only be applied to functions + error: aborting due to 6 previous errors; 2 warnings emitted -For more information about this error, try `rustc --explain E0518`. diff --git a/tests/ui/lint/unused/unused-attr-macro-rules.rs b/tests/ui/lint/unused/unused-attr-macro-rules.rs index 7a8a1bb1ae5..96f2834a296 100644 --- a/tests/ui/lint/unused/unused-attr-macro-rules.rs +++ b/tests/ui/lint/unused/unused-attr-macro-rules.rs @@ -4,8 +4,10 @@ // A sample of various built-in attributes. #[macro_export] -#[macro_use] //~ ERROR `#[macro_use]` only has an effect -#[path="foo"] //~ ERROR #[path]` only has an effect +#[macro_use] //~ ERROR attribute cannot be used on +//~| WARN previously accepted +#[path="foo"] //~ ERROR attribute cannot be used on +//~| WARN previously accepted #[recursion_limit="1"] //~ ERROR crate-level attribute should be an inner attribute macro_rules! foo { () => {}; diff --git a/tests/ui/lint/unused/unused-attr-macro-rules.stderr b/tests/ui/lint/unused/unused-attr-macro-rules.stderr index 1e1211af5e2..0c55ae678e9 100644 --- a/tests/ui/lint/unused/unused-attr-macro-rules.stderr +++ b/tests/ui/lint/unused/unused-attr-macro-rules.stderr @@ -1,5 +1,5 @@ error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/unused-attr-macro-rules.rs:9:1 + --> $DIR/unused-attr-macro-rules.rs:11:1 | LL | #[recursion_limit="1"] | ^^^^^^^^^^^^^^^^^^^^^^ @@ -10,17 +10,23 @@ note: the lint level is defined here LL | #![deny(unused_attributes)] | ^^^^^^^^^^^^^^^^^ -error: `#[macro_use]` only has an effect on `extern crate` and modules +error: `#[macro_use]` attribute cannot be used on macro defs --> $DIR/unused-attr-macro-rules.rs:7:1 | LL | #[macro_use] | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[macro_use]` can be applied to modules, extern crates, crates -error: `#[path]` only has an effect on modules - --> $DIR/unused-attr-macro-rules.rs:8:1 +error: `#[path]` attribute cannot be used on macro defs + --> $DIR/unused-attr-macro-rules.rs:9:1 | LL | #[path="foo"] | ^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[path]` can only be applied to modules error: aborting due to 3 previous errors diff --git a/tests/ui/lint/unused/unused_attributes-must_use.fixed b/tests/ui/lint/unused/unused_attributes-must_use.fixed new file mode 100644 index 00000000000..80d488296ea --- /dev/null +++ b/tests/ui/lint/unused/unused_attributes-must_use.fixed @@ -0,0 +1,139 @@ +//@ run-rustfix + +#![allow(dead_code, path_statements)] +#![deny(unused_attributes, unused_must_use)] +#![feature(asm_experimental_arch, stmt_expr_attributes, trait_alias)] + + //~ ERROR `#[must_use]` has no effect +extern crate std as std2; + + //~ ERROR `#[must_use]` has no effect +mod test_mod {} + + //~ ERROR `#[must_use]` has no effect +use std::arch::global_asm; + + //~ ERROR `#[must_use]` has no effect +const CONST: usize = 4; + //~ ERROR `#[must_use]` has no effect +#[no_mangle] +static STATIC: usize = 4; + +#[must_use] +struct X; + +#[must_use] +enum Y { + Z, +} + +#[must_use] +union U { + unit: (), +} + + //~ ERROR `#[must_use]` has no effect +impl U { + #[must_use] + fn method() -> i32 { + 4 + } +} + +#[must_use] +#[no_mangle] +fn foo() -> i64 { + 4 +} + + //~ ERROR `#[must_use]` has no effect +extern "Rust" { + #[link_name = "STATIC"] + //~ ERROR `#[must_use]` has no effect + static FOREIGN_STATIC: usize; + + #[link_name = "foo"] + #[must_use] + fn foreign_foo() -> i64; +} + + //~ ERROR unused attribute +global_asm!(""); + + //~ ERROR `#[must_use]` has no effect +type UseMe = (); + +fn qux< T>(_: T) {} //~ ERROR `#[must_use]` has no effect + +#[must_use] +trait Use { + //~ ERROR `#[must_use]` has no effect + const ASSOC_CONST: usize = 4; + //~ ERROR `#[must_use]` has no effect + type AssocTy; + + #[must_use] + fn get_four(&self) -> usize { + 4 + } +} + + //~ ERROR `#[must_use]` has no effect +impl Use for () { + type AssocTy = (); + + //~ ERROR `#[must_use]` has no effect + fn get_four(&self) -> usize { + 4 + } +} + + //~ ERROR `#[must_use]` has no effect +trait Alias = Use; + + //~ ERROR `#[must_use]` has no effect +macro_rules! cool_macro { + () => { + 4 + }; +} + +fn main() { + //~ ERROR `#[must_use]` has no effect + let x = || {}; + x(); + + let x = //~ ERROR `#[must_use]` has no effect + || {}; + x(); + + let _ = X; //~ ERROR that must be used + let _ = Y::Z; //~ ERROR that must be used + let _ = U { unit: () }; //~ ERROR that must be used + let _ = U::method(); //~ ERROR that must be used + let _ = foo(); //~ ERROR that must be used + + unsafe { + let _ = foreign_foo(); //~ ERROR that must be used + }; + + CONST; + STATIC; + unsafe { FOREIGN_STATIC }; + cool_macro!(); + qux(4); + let _ = ().get_four(); //~ ERROR that must be used + + match Some(4) { + //~ ERROR `#[must_use]` has no effect + Some(res) => res, + None => 0, + }; + + struct PatternField { + foo: i32, + } + let s = PatternField { foo: 123 }; //~ ERROR `#[must_use]` has no effect + let PatternField { foo } = s; //~ ERROR `#[must_use]` has no effect + let _ = foo; +} diff --git a/tests/ui/lint/unused/unused_attributes-must_use.rs b/tests/ui/lint/unused/unused_attributes-must_use.rs index 860fc5046d1..edefe8ed65e 100644 --- a/tests/ui/lint/unused/unused_attributes-must_use.rs +++ b/tests/ui/lint/unused/unused_attributes-must_use.rs @@ -1,3 +1,5 @@ +//@ run-rustfix + #![allow(dead_code, path_statements)] #![deny(unused_attributes, unused_must_use)] #![feature(asm_experimental_arch, stmt_expr_attributes, trait_alias)] @@ -133,4 +135,5 @@ fn main() { } let s = PatternField { #[must_use] foo: 123 }; //~ ERROR `#[must_use]` has no effect let PatternField { #[must_use] foo } = s; //~ ERROR `#[must_use]` has no effect + let _ = foo; } diff --git a/tests/ui/lint/unused/unused_attributes-must_use.stderr b/tests/ui/lint/unused/unused_attributes-must_use.stderr index 862ffa42d80..9e37f6504cc 100644 --- a/tests/ui/lint/unused/unused_attributes-must_use.stderr +++ b/tests/ui/lint/unused/unused_attributes-must_use.stderr @@ -1,154 +1,154 @@ error: unused attribute `must_use` - --> $DIR/unused_attributes-must_use.rs:58:1 + --> $DIR/unused_attributes-must_use.rs:60:1 | LL | #[must_use] | ^^^^^^^^^^^ | note: the built-in attribute `must_use` will be ignored, since it's applied to the macro invocation `global_asm` - --> $DIR/unused_attributes-must_use.rs:59:1 + --> $DIR/unused_attributes-must_use.rs:61:1 | LL | global_asm!(""); | ^^^^^^^^^^ note: the lint level is defined here - --> $DIR/unused_attributes-must_use.rs:2:9 + --> $DIR/unused_attributes-must_use.rs:4:9 | LL | #![deny(unused_attributes, unused_must_use)] | ^^^^^^^^^^^^^^^^^ -error: `#[must_use]` has no effect when applied to an extern crate - --> $DIR/unused_attributes-must_use.rs:5:1 +error: `#[must_use]` has no effect when applied to extern crates + --> $DIR/unused_attributes-must_use.rs:7:1 | LL | #[must_use] | ^^^^^^^^^^^ -error: `#[must_use]` has no effect when applied to a module - --> $DIR/unused_attributes-must_use.rs:8:1 +error: `#[must_use]` has no effect when applied to modules + --> $DIR/unused_attributes-must_use.rs:10:1 | LL | #[must_use] | ^^^^^^^^^^^ -error: `#[must_use]` has no effect when applied to a use - --> $DIR/unused_attributes-must_use.rs:11:1 +error: `#[must_use]` has no effect when applied to use statements + --> $DIR/unused_attributes-must_use.rs:13:1 | LL | #[must_use] | ^^^^^^^^^^^ -error: `#[must_use]` has no effect when applied to a constant item - --> $DIR/unused_attributes-must_use.rs:14:1 +error: `#[must_use]` has no effect when applied to constants + --> $DIR/unused_attributes-must_use.rs:16:1 | LL | #[must_use] | ^^^^^^^^^^^ -error: `#[must_use]` has no effect when applied to a static item - --> $DIR/unused_attributes-must_use.rs:16:1 +error: `#[must_use]` has no effect when applied to statics + --> $DIR/unused_attributes-must_use.rs:18:1 | LL | #[must_use] | ^^^^^^^^^^^ -error: `#[must_use]` has no effect when applied to an inherent implementation block - --> $DIR/unused_attributes-must_use.rs:33:1 +error: `#[must_use]` has no effect when applied to inherent impl blocks + --> $DIR/unused_attributes-must_use.rs:35:1 | LL | #[must_use] | ^^^^^^^^^^^ -error: `#[must_use]` has no effect when applied to a foreign module - --> $DIR/unused_attributes-must_use.rs:47:1 +error: `#[must_use]` has no effect when applied to foreign modules + --> $DIR/unused_attributes-must_use.rs:49:1 | LL | #[must_use] | ^^^^^^^^^^^ -error: `#[must_use]` has no effect when applied to a type alias - --> $DIR/unused_attributes-must_use.rs:61:1 +error: `#[must_use]` has no effect when applied to type aliases + --> $DIR/unused_attributes-must_use.rs:63:1 | LL | #[must_use] | ^^^^^^^^^^^ -error: `#[must_use]` has no effect when applied to a type parameter - --> $DIR/unused_attributes-must_use.rs:64:8 +error: `#[must_use]` has no effect when applied to type parameters + --> $DIR/unused_attributes-must_use.rs:66:8 | LL | fn qux<#[must_use] T>(_: T) {} | ^^^^^^^^^^^ -error: `#[must_use]` has no effect when applied to an trait implementation block - --> $DIR/unused_attributes-must_use.rs:79:1 +error: `#[must_use]` has no effect when applied to trait impl blocks + --> $DIR/unused_attributes-must_use.rs:81:1 | LL | #[must_use] | ^^^^^^^^^^^ -error: `#[must_use]` has no effect when applied to a trait alias - --> $DIR/unused_attributes-must_use.rs:89:1 +error: `#[must_use]` has no effect when applied to trait aliases + --> $DIR/unused_attributes-must_use.rs:91:1 | LL | #[must_use] | ^^^^^^^^^^^ -error: `#[must_use]` has no effect when applied to a macro def - --> $DIR/unused_attributes-must_use.rs:92:1 +error: `#[must_use]` has no effect when applied to macro defs + --> $DIR/unused_attributes-must_use.rs:94:1 | LL | #[must_use] | ^^^^^^^^^^^ -error: `#[must_use]` has no effect when applied to a statement - --> $DIR/unused_attributes-must_use.rs:100:5 +error: `#[must_use]` has no effect when applied to statements + --> $DIR/unused_attributes-must_use.rs:102:5 | LL | #[must_use] | ^^^^^^^^^^^ -error: `#[must_use]` has no effect when applied to a closure - --> $DIR/unused_attributes-must_use.rs:104:13 +error: `#[must_use]` has no effect when applied to closures + --> $DIR/unused_attributes-must_use.rs:106:13 | LL | let x = #[must_use] | ^^^^^^^^^^^ -error: `#[must_use]` has no effect when applied to an match arm - --> $DIR/unused_attributes-must_use.rs:126:9 +error: `#[must_use]` has no effect when applied to match arms + --> $DIR/unused_attributes-must_use.rs:128:9 | LL | #[must_use] | ^^^^^^^^^^^ -error: `#[must_use]` has no effect when applied to a struct field - --> $DIR/unused_attributes-must_use.rs:134:28 +error: `#[must_use]` has no effect when applied to struct fields + --> $DIR/unused_attributes-must_use.rs:136:28 | LL | let s = PatternField { #[must_use] foo: 123 }; | ^^^^^^^^^^^ -error: `#[must_use]` has no effect when applied to a pattern field - --> $DIR/unused_attributes-must_use.rs:135:24 +error: `#[must_use]` has no effect when applied to pattern fields + --> $DIR/unused_attributes-must_use.rs:137:24 | LL | let PatternField { #[must_use] foo } = s; | ^^^^^^^^^^^ -error: `#[must_use]` has no effect when applied to an associated const - --> $DIR/unused_attributes-must_use.rs:68:5 +error: `#[must_use]` has no effect when applied to associated consts + --> $DIR/unused_attributes-must_use.rs:70:5 | LL | #[must_use] | ^^^^^^^^^^^ -error: `#[must_use]` has no effect when applied to an associated type - --> $DIR/unused_attributes-must_use.rs:70:5 +error: `#[must_use]` has no effect when applied to associated types + --> $DIR/unused_attributes-must_use.rs:72:5 | LL | #[must_use] | ^^^^^^^^^^^ -error: `#[must_use]` has no effect when applied to a provided trait method - --> $DIR/unused_attributes-must_use.rs:83:5 +error: `#[must_use]` has no effect when applied to provided trait methods + --> $DIR/unused_attributes-must_use.rs:85:5 | LL | #[must_use] | ^^^^^^^^^^^ -error: `#[must_use]` has no effect when applied to a foreign static item - --> $DIR/unused_attributes-must_use.rs:50:5 +error: `#[must_use]` has no effect when applied to foreign statics + --> $DIR/unused_attributes-must_use.rs:52:5 | LL | #[must_use] | ^^^^^^^^^^^ error: unused `X` that must be used - --> $DIR/unused_attributes-must_use.rs:108:5 + --> $DIR/unused_attributes-must_use.rs:110:5 | LL | X; | ^ | note: the lint level is defined here - --> $DIR/unused_attributes-must_use.rs:2:28 + --> $DIR/unused_attributes-must_use.rs:4:28 | LL | #![deny(unused_attributes, unused_must_use)] | ^^^^^^^^^^^^^^^ @@ -158,7 +158,7 @@ LL | let _ = X; | +++++++ error: unused `Y` that must be used - --> $DIR/unused_attributes-must_use.rs:109:5 + --> $DIR/unused_attributes-must_use.rs:111:5 | LL | Y::Z; | ^^^^ @@ -169,7 +169,7 @@ LL | let _ = Y::Z; | +++++++ error: unused `U` that must be used - --> $DIR/unused_attributes-must_use.rs:110:5 + --> $DIR/unused_attributes-must_use.rs:112:5 | LL | U { unit: () }; | ^^^^^^^^^^^^^^ @@ -180,7 +180,7 @@ LL | let _ = U { unit: () }; | +++++++ error: unused return value of `U::method` that must be used - --> $DIR/unused_attributes-must_use.rs:111:5 + --> $DIR/unused_attributes-must_use.rs:113:5 | LL | U::method(); | ^^^^^^^^^^^ @@ -191,7 +191,7 @@ LL | let _ = U::method(); | +++++++ error: unused return value of `foo` that must be used - --> $DIR/unused_attributes-must_use.rs:112:5 + --> $DIR/unused_attributes-must_use.rs:114:5 | LL | foo(); | ^^^^^ @@ -202,7 +202,7 @@ LL | let _ = foo(); | +++++++ error: unused return value of `foreign_foo` that must be used - --> $DIR/unused_attributes-must_use.rs:115:9 + --> $DIR/unused_attributes-must_use.rs:117:9 | LL | foreign_foo(); | ^^^^^^^^^^^^^ @@ -213,7 +213,7 @@ LL | let _ = foreign_foo(); | +++++++ error: unused return value of `Use::get_four` that must be used - --> $DIR/unused_attributes-must_use.rs:123:5 + --> $DIR/unused_attributes-must_use.rs:125:5 | LL | ().get_four(); | ^^^^^^^^^^^^^ diff --git a/tests/ui/lint/warn-unused-inline-on-fn-prototypes.rs b/tests/ui/lint/warn-unused-inline-on-fn-prototypes.rs index 4684fe14577..bef607a4ec5 100644 --- a/tests/ui/lint/warn-unused-inline-on-fn-prototypes.rs +++ b/tests/ui/lint/warn-unused-inline-on-fn-prototypes.rs @@ -1,12 +1,14 @@ #![deny(unused_attributes)] trait Trait { - #[inline] //~ ERROR `#[inline]` is ignored on function prototypes + #[inline] //~ ERROR attribute cannot be used on + //~^ WARN previously accepted fn foo(); } extern "C" { - #[inline] //~ ERROR `#[inline]` is ignored on function prototypes + #[inline] //~ ERROR attribute cannot be used on + //~^ WARN previously accepted fn foo(); } diff --git a/tests/ui/lint/warn-unused-inline-on-fn-prototypes.stderr b/tests/ui/lint/warn-unused-inline-on-fn-prototypes.stderr index ab19d80e732..336366042f9 100644 --- a/tests/ui/lint/warn-unused-inline-on-fn-prototypes.stderr +++ b/tests/ui/lint/warn-unused-inline-on-fn-prototypes.stderr @@ -1,20 +1,25 @@ -error: `#[inline]` is ignored on function prototypes +error: `#[inline]` attribute cannot be used on required trait methods --> $DIR/warn-unused-inline-on-fn-prototypes.rs:4:5 | LL | #[inline] | ^^^^^^^^^ | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[inline]` can be applied to functions, inherent methods, provided trait methods, trait methods in impl blocks, closures note: the lint level is defined here --> $DIR/warn-unused-inline-on-fn-prototypes.rs:1:9 | LL | #![deny(unused_attributes)] | ^^^^^^^^^^^^^^^^^ -error: `#[inline]` is ignored on function prototypes - --> $DIR/warn-unused-inline-on-fn-prototypes.rs:9:5 +error: `#[inline]` attribute cannot be used on foreign functions + --> $DIR/warn-unused-inline-on-fn-prototypes.rs:10:5 | LL | #[inline] | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[inline]` can be applied to methods, functions, closures error: aborting due to 2 previous errors diff --git a/tests/ui/loop-match/invalid-attribute.rs b/tests/ui/loop-match/invalid-attribute.rs index d8d2f605eb4..a5d7daac583 100644 --- a/tests/ui/loop-match/invalid-attribute.rs +++ b/tests/ui/loop-match/invalid-attribute.rs @@ -3,17 +3,17 @@ #![allow(incomplete_features)] #![feature(loop_match)] -#![loop_match] //~ ERROR should be applied to a loop -#![const_continue] //~ ERROR should be applied to a break expression +#![loop_match] //~ ERROR attribute cannot be used on +#![const_continue] //~ ERROR attribute cannot be used on extern "C" { - #[loop_match] //~ ERROR should be applied to a loop - #[const_continue] //~ ERROR should be applied to a break expression + #[loop_match] //~ ERROR attribute cannot be used on + #[const_continue] //~ ERROR attribute cannot be used on fn f(); } -#[loop_match] //~ ERROR should be applied to a loop -#[const_continue] //~ ERROR should be applied to a break expression +#[loop_match] //~ ERROR attribute cannot be used on +#[const_continue] //~ ERROR attribute cannot be used on #[repr(C)] struct S { a: u32, @@ -21,18 +21,18 @@ struct S { } trait Invoke { - #[loop_match] //~ ERROR should be applied to a loop - #[const_continue] //~ ERROR should be applied to a break expression + #[loop_match] //~ ERROR attribute cannot be used on + #[const_continue] //~ ERROR attribute cannot be used on extern "C" fn invoke(&self); } -#[loop_match] //~ ERROR should be applied to a loop -#[const_continue] //~ ERROR should be applied to a break expression +#[loop_match] //~ ERROR attribute cannot be used on +#[const_continue] //~ ERROR attribute cannot be used on extern "C" fn ok() {} fn main() { - #[loop_match] //~ ERROR should be applied to a loop - #[const_continue] //~ ERROR should be applied to a break expression + #[loop_match] //~ ERROR attribute cannot be used on + #[const_continue] //~ ERROR attribute cannot be used on || {}; { diff --git a/tests/ui/loop-match/invalid-attribute.stderr b/tests/ui/loop-match/invalid-attribute.stderr index 07015311f9c..ddb68aea31b 100644 --- a/tests/ui/loop-match/invalid-attribute.stderr +++ b/tests/ui/loop-match/invalid-attribute.stderr @@ -1,54 +1,98 @@ -error: `#[const_continue]` should be applied to a break expression - --> $DIR/invalid-attribute.rs:16:1 +error: `#[loop_match]` attribute cannot be used on crates + --> $DIR/invalid-attribute.rs:6:1 | -LL | #[const_continue] - | ^^^^^^^^^^^^^^^^^ -LL | #[repr(C)] -LL | struct S { - | -------- not a break expression +LL | #![loop_match] + | ^^^^^^^^^^^^^^ + | + = help: `#[loop_match]` can be applied to -error: `#[loop_match]` should be applied to a loop +error: `#[const_continue]` attribute cannot be used on crates + --> $DIR/invalid-attribute.rs:7:1 + | +LL | #![const_continue] + | ^^^^^^^^^^^^^^^^^^ + | + = help: `#[const_continue]` can be applied to + +error: `#[loop_match]` attribute cannot be used on foreign functions + --> $DIR/invalid-attribute.rs:10:5 + | +LL | #[loop_match] + | ^^^^^^^^^^^^^ + | + = help: `#[loop_match]` can be applied to + +error: `#[const_continue]` attribute cannot be used on foreign functions + --> $DIR/invalid-attribute.rs:11:5 + | +LL | #[const_continue] + | ^^^^^^^^^^^^^^^^^ + | + = help: `#[const_continue]` can be applied to + +error: `#[loop_match]` attribute cannot be used on structs --> $DIR/invalid-attribute.rs:15:1 | LL | #[loop_match] | ^^^^^^^^^^^^^ -... -LL | struct S { - | -------- not a loop + | + = help: `#[loop_match]` can be applied to -error: `#[const_continue]` should be applied to a break expression - --> $DIR/invalid-attribute.rs:30:1 +error: `#[const_continue]` attribute cannot be used on structs + --> $DIR/invalid-attribute.rs:16:1 | LL | #[const_continue] | ^^^^^^^^^^^^^^^^^ -LL | extern "C" fn ok() {} - | ------------------ not a break expression + | + = help: `#[const_continue]` can be applied to -error: `#[loop_match]` should be applied to a loop +error: `#[loop_match]` attribute cannot be used on required trait methods + --> $DIR/invalid-attribute.rs:24:5 + | +LL | #[loop_match] + | ^^^^^^^^^^^^^ + | + = help: `#[loop_match]` can be applied to + +error: `#[const_continue]` attribute cannot be used on required trait methods + --> $DIR/invalid-attribute.rs:25:5 + | +LL | #[const_continue] + | ^^^^^^^^^^^^^^^^^ + | + = help: `#[const_continue]` can be applied to + +error: `#[loop_match]` attribute cannot be used on functions --> $DIR/invalid-attribute.rs:29:1 | LL | #[loop_match] | ^^^^^^^^^^^^^ -LL | #[const_continue] -LL | extern "C" fn ok() {} - | ------------------ not a loop + | + = help: `#[loop_match]` can be applied to -error: `#[const_continue]` should be applied to a break expression - --> $DIR/invalid-attribute.rs:35:5 +error: `#[const_continue]` attribute cannot be used on functions + --> $DIR/invalid-attribute.rs:30:1 | -LL | #[const_continue] - | ^^^^^^^^^^^^^^^^^ -LL | || {}; - | -- not a break expression +LL | #[const_continue] + | ^^^^^^^^^^^^^^^^^ + | + = help: `#[const_continue]` can be applied to -error: `#[loop_match]` should be applied to a loop +error: `#[loop_match]` attribute cannot be used on closures --> $DIR/invalid-attribute.rs:34:5 | LL | #[loop_match] | ^^^^^^^^^^^^^ + | + = help: `#[loop_match]` can be applied to + +error: `#[const_continue]` attribute cannot be used on closures + --> $DIR/invalid-attribute.rs:35:5 + | LL | #[const_continue] -LL | || {}; - | -- not a loop + | ^^^^^^^^^^^^^^^^^ + | + = help: `#[const_continue]` can be applied to error: `#[const_continue]` should be applied to a break expression --> $DIR/invalid-attribute.rs:40:9 @@ -67,65 +111,5 @@ LL | #[const_continue] LL | 5 | - not a loop -error: `#[const_continue]` should be applied to a break expression - --> $DIR/invalid-attribute.rs:25:5 - | -LL | #[const_continue] - | ^^^^^^^^^^^^^^^^^ -LL | extern "C" fn invoke(&self); - | ---------------------------- not a break expression - -error: `#[loop_match]` should be applied to a loop - --> $DIR/invalid-attribute.rs:24:5 - | -LL | #[loop_match] - | ^^^^^^^^^^^^^ -LL | #[const_continue] -LL | extern "C" fn invoke(&self); - | ---------------------------- not a loop - -error: `#[const_continue]` should be applied to a break expression - --> $DIR/invalid-attribute.rs:11:5 - | -LL | #[const_continue] - | ^^^^^^^^^^^^^^^^^ -LL | fn f(); - | ------- not a break expression - -error: `#[loop_match]` should be applied to a loop - --> $DIR/invalid-attribute.rs:10:5 - | -LL | #[loop_match] - | ^^^^^^^^^^^^^ -LL | #[const_continue] -LL | fn f(); - | ------- not a loop - -error: `#[const_continue]` should be applied to a break expression - --> $DIR/invalid-attribute.rs:7:1 - | -LL | / #![allow(incomplete_features)] -LL | | #![feature(loop_match)] -LL | | #![loop_match] -LL | | #![const_continue] - | | ^^^^^^^^^^^^^^^^^^ -... | -LL | | }; -LL | | } - | |_- not a break expression - -error: `#[loop_match]` should be applied to a loop - --> $DIR/invalid-attribute.rs:6:1 - | -LL | / #![allow(incomplete_features)] -LL | | #![feature(loop_match)] -LL | | #![loop_match] - | | ^^^^^^^^^^^^^^ -LL | | #![const_continue] -... | -LL | | }; -LL | | } - | |_- not a loop - error: aborting due to 14 previous errors diff --git a/tests/ui/macros/cfg_select.rs b/tests/ui/macros/cfg_select.rs index 461d2e0e8c1..9241141ef9a 100644 --- a/tests/ui/macros/cfg_select.rs +++ b/tests/ui/macros/cfg_select.rs @@ -8,10 +8,42 @@ fn print() { }); } -fn arm_rhs_must_be_in_braces() -> i32 { +fn print_2() { + println!(cfg_select! { + unix => "unix", + _ => "not unix", + }); +} + +fn arm_rhs_expr_1() -> i32 { cfg_select! { true => 1 - //~^ ERROR: expected `{`, found `1` + } +} + +fn arm_rhs_expr_2() -> i32 { + cfg_select! { + true => 1, + false => 2 + } +} + +fn arm_rhs_expr_3() -> i32 { + cfg_select! { + true => 1, + false => 2, + true => { 42 } + false => -1 as i32, + true => 2 + 2, + false => "", + true => if true { 42 } else { 84 } + false => if true { 42 } else { 84 }, + true => return 42, + false => loop {} + true => (1, 2), + false => (1, 2,), + true => todo!(), + false => println!("hello"), } } diff --git a/tests/ui/macros/cfg_select.stderr b/tests/ui/macros/cfg_select.stderr index 6c18a7c189d..7280f35c16f 100644 --- a/tests/ui/macros/cfg_select.stderr +++ b/tests/ui/macros/cfg_select.stderr @@ -1,11 +1,5 @@ -error: expected `{`, found `1` - --> $DIR/cfg_select.rs:13:17 - | -LL | true => 1 - | ^ expected `{` - warning: unreachable predicate - --> $DIR/cfg_select.rs:20:5 + --> $DIR/cfg_select.rs:52:5 | LL | _ => {} | - always matches @@ -13,7 +7,7 @@ LL | true => {} | ^^^^ this predicate is never reached error: none of the predicates in this `cfg_select` evaluated to true - --> $DIR/cfg_select.rs:24:1 + --> $DIR/cfg_select.rs:56:1 | LL | / cfg_select! { LL | | @@ -22,10 +16,10 @@ LL | | } | |_^ error: none of the predicates in this `cfg_select` evaluated to true - --> $DIR/cfg_select.rs:29:1 + --> $DIR/cfg_select.rs:61:1 | LL | cfg_select! {} | ^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 2 previous errors; 1 warning emitted diff --git a/tests/ui/macros/issue-68060.rs b/tests/ui/macros/issue-68060.rs index 4eddb96848c..2edf9861743 100644 --- a/tests/ui/macros/issue-68060.rs +++ b/tests/ui/macros/issue-68060.rs @@ -2,13 +2,12 @@ fn main() { (0..) .map( #[target_feature(enable = "")] - //~^ ERROR: attribute should be applied to a function + //~^ ERROR: attribute cannot be used on #[track_caller] //~^ ERROR: `#[track_caller]` on closures is currently unstable //~| NOTE: see issue #87417 //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |_| (), - //~^ NOTE: not a function ) .next(); } diff --git a/tests/ui/macros/issue-68060.stderr b/tests/ui/macros/issue-68060.stderr index ef2246d5bd6..c701e50f054 100644 --- a/tests/ui/macros/issue-68060.stderr +++ b/tests/ui/macros/issue-68060.stderr @@ -1,11 +1,10 @@ -error: attribute should be applied to a function definition +error: `#[target_feature]` attribute cannot be used on closures --> $DIR/issue-68060.rs:4:13 | LL | #[target_feature(enable = "")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | |_| (), - | ------ not a function definition + | + = help: `#[target_feature]` can be applied to methods, functions error[E0658]: `#[track_caller]` on closures is currently unstable --> $DIR/issue-68060.rs:6:13 diff --git a/tests/ui/macros/issue-78325-inconsistent-resolution.rs b/tests/ui/macros/issue-78325-inconsistent-resolution.rs index 919eca4f9bf..021ba599d12 100644 --- a/tests/ui/macros/issue-78325-inconsistent-resolution.rs +++ b/tests/ui/macros/issue-78325-inconsistent-resolution.rs @@ -1,3 +1,5 @@ +//@ edition: 2018 + macro_rules! define_other_core { ( ) => { extern crate std as core; @@ -6,7 +8,8 @@ macro_rules! define_other_core { } fn main() { - core::panic!(); + core::panic!(); //~ ERROR `core` is ambiguous + ::core::panic!(); //~ ERROR `core` is ambiguous } define_other_core!(); diff --git a/tests/ui/macros/issue-78325-inconsistent-resolution.stderr b/tests/ui/macros/issue-78325-inconsistent-resolution.stderr index b75e4a9c9e0..7c745040640 100644 --- a/tests/ui/macros/issue-78325-inconsistent-resolution.stderr +++ b/tests/ui/macros/issue-78325-inconsistent-resolution.stderr @@ -1,5 +1,5 @@ error: macro-expanded `extern crate` items cannot shadow names passed with `--extern` - --> $DIR/issue-78325-inconsistent-resolution.rs:3:9 + --> $DIR/issue-78325-inconsistent-resolution.rs:5:9 | LL | extern crate std as core; | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,5 +9,43 @@ LL | define_other_core!(); | = note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 1 previous error +error[E0659]: `core` is ambiguous + --> $DIR/issue-78325-inconsistent-resolution.rs:11:5 + | +LL | core::panic!(); + | ^^^^ ambiguous name + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution + = note: `core` could refer to a built-in crate +note: `core` could also refer to the crate imported here + --> $DIR/issue-78325-inconsistent-resolution.rs:5:9 + | +LL | extern crate std as core; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | define_other_core!(); + | -------------------- in this macro invocation + = help: use `crate::core` to refer to this crate unambiguously + = note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0659]: `core` is ambiguous + --> $DIR/issue-78325-inconsistent-resolution.rs:12:7 + | +LL | ::core::panic!(); + | ^^^^ ambiguous name + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution + = note: `core` could refer to a built-in crate +note: `core` could also refer to the crate imported here + --> $DIR/issue-78325-inconsistent-resolution.rs:5:9 + | +LL | extern crate std as core; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | define_other_core!(); + | -------------------- in this macro invocation + = note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/macros/macro-rules-attr-error.rs b/tests/ui/macros/macro-rules-attr-error.rs index 1c8bb251e20..81eadb6692f 100644 --- a/tests/ui/macros/macro-rules-attr-error.rs +++ b/tests/ui/macros/macro-rules-attr-error.rs @@ -7,9 +7,46 @@ macro_rules! local_attr { //~^^ ERROR: local_attr } +//~v NOTE: `fn_only` exists, but has no `attr` rules +macro_rules! fn_only { + {} => {} +} + +//~v NOTE: `attr_only` exists, but has no rules for function-like invocation +macro_rules! attr_only { + attr() {} => {} +} + fn main() { + //~v NOTE: in this expansion of #[local_attr] #[local_attr] struct S; - local_attr!(arg); //~ ERROR: macro has no rules for function-like invocation + //~vv ERROR: cannot find macro `local_attr` in this scope + //~| NOTE: `local_attr` is in scope, but it is an attribute + local_attr!(arg); + + //~v ERROR: cannot find attribute `fn_only` in this scope + #[fn_only] + struct S; + + attr_only!(); //~ ERROR: cannot find macro `attr_only` in this scope +} + +//~vv ERROR: cannot find attribute `forward_referenced_attr` in this scope +//~| NOTE: consider moving the definition of `forward_referenced_attr` before this call +#[forward_referenced_attr] +struct S; + +//~v NOTE: a macro with the same name exists, but it appears later +macro_rules! forward_referenced_attr { + attr() {} => {} +} + +//~vv ERROR: cannot find attribute `cyclic_attr` in this scope +//~| NOTE: consider moving the definition of `cyclic_attr` before this call +#[cyclic_attr] +//~v NOTE: a macro with the same name exists, but it appears later +macro_rules! cyclic_attr { + attr() {} => {} } diff --git a/tests/ui/macros/macro-rules-attr-error.stderr b/tests/ui/macros/macro-rules-attr-error.stderr index 177b7009384..674d35091b6 100644 --- a/tests/ui/macros/macro-rules-attr-error.stderr +++ b/tests/ui/macros/macro-rules-attr-error.stderr @@ -9,14 +9,55 @@ LL | #[local_attr] | = note: this error originates in the attribute macro `local_attr` (in Nightly builds, run with -Z macro-backtrace for more info) -error: macro has no rules for function-like invocation `local_attr!` - --> $DIR/macro-rules-attr-error.rs:14:5 +error: cannot find macro `local_attr` in this scope + --> $DIR/macro-rules-attr-error.rs:27:5 | -LL | macro_rules! local_attr { - | ----------------------- this macro has no rules for function-like invocation -... LL | local_attr!(arg); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^ + | + = note: `local_attr` is in scope, but it is an attribute: `#[local_attr]` + +error: cannot find attribute `fn_only` in this scope + --> $DIR/macro-rules-attr-error.rs:30:7 + | +LL | macro_rules! fn_only { + | ------- `fn_only` exists, but has no `attr` rules +... +LL | #[fn_only] + | ^^^^^^^ + +error: cannot find macro `attr_only` in this scope + --> $DIR/macro-rules-attr-error.rs:33:5 + | +LL | macro_rules! attr_only { + | --------- `attr_only` exists, but has no rules for function-like invocation +... +LL | attr_only!(); + | ^^^^^^^^^ + +error: cannot find attribute `forward_referenced_attr` in this scope + --> $DIR/macro-rules-attr-error.rs:38:3 + | +LL | #[forward_referenced_attr] + | ^^^^^^^^^^^^^^^^^^^^^^^ consider moving the definition of `forward_referenced_attr` before this call + | +note: a macro with the same name exists, but it appears later + --> $DIR/macro-rules-attr-error.rs:42:14 + | +LL | macro_rules! forward_referenced_attr { + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: cannot find attribute `cyclic_attr` in this scope + --> $DIR/macro-rules-attr-error.rs:48:3 + | +LL | #[cyclic_attr] + | ^^^^^^^^^^^ consider moving the definition of `cyclic_attr` before this call + | +note: a macro with the same name exists, but it appears later + --> $DIR/macro-rules-attr-error.rs:50:14 + | +LL | macro_rules! cyclic_attr { + | ^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 6 previous errors diff --git a/tests/ui/marker_trait_attr/marker-attribute-on-non-trait.rs b/tests/ui/marker_trait_attr/marker-attribute-on-non-trait.rs index 0bf620934ec..1fb206d628f 100644 --- a/tests/ui/marker_trait_attr/marker-attribute-on-non-trait.rs +++ b/tests/ui/marker_trait_attr/marker-attribute-on-non-trait.rs @@ -1,23 +1,23 @@ #![feature(marker_trait_attr)] -#[marker] //~ ERROR attribute should be applied to a trait +#[marker] //~ ERROR attribute cannot be used on struct Struct {} -#[marker] //~ ERROR attribute should be applied to a trait +#[marker] //~ ERROR attribute cannot be used on impl Struct {} -#[marker] //~ ERROR attribute should be applied to a trait +#[marker] //~ ERROR attribute cannot be used on union Union { x: i32, } -#[marker] //~ ERROR attribute should be applied to a trait +#[marker] //~ ERROR attribute cannot be used on const CONST: usize = 10; -#[marker] //~ ERROR attribute should be applied to a trait +#[marker] //~ ERROR attribute cannot be used on fn function() {} -#[marker] //~ ERROR attribute should be applied to a trait +#[marker] //~ ERROR attribute cannot be used on type Type = (); fn main() {} diff --git a/tests/ui/marker_trait_attr/marker-attribute-on-non-trait.stderr b/tests/ui/marker_trait_attr/marker-attribute-on-non-trait.stderr index 19a5290dd7e..71abe7f39df 100644 --- a/tests/ui/marker_trait_attr/marker-attribute-on-non-trait.stderr +++ b/tests/ui/marker_trait_attr/marker-attribute-on-non-trait.stderr @@ -1,52 +1,50 @@ -error: attribute should be applied to a trait +error: `#[marker]` attribute cannot be used on structs --> $DIR/marker-attribute-on-non-trait.rs:3:1 | LL | #[marker] | ^^^^^^^^^ -LL | struct Struct {} - | ---------------- not a trait + | + = help: `#[marker]` can only be applied to traits -error: attribute should be applied to a trait +error: `#[marker]` attribute cannot be used on inherent impl blocks --> $DIR/marker-attribute-on-non-trait.rs:6:1 | LL | #[marker] | ^^^^^^^^^ -LL | impl Struct {} - | -------------- not a trait + | + = help: `#[marker]` can only be applied to traits -error: attribute should be applied to a trait +error: `#[marker]` attribute cannot be used on unions --> $DIR/marker-attribute-on-non-trait.rs:9:1 | -LL | #[marker] - | ^^^^^^^^^ -LL | / union Union { -LL | | x: i32, -LL | | } - | |_- not a trait +LL | #[marker] + | ^^^^^^^^^ + | + = help: `#[marker]` can only be applied to traits -error: attribute should be applied to a trait +error: `#[marker]` attribute cannot be used on constants --> $DIR/marker-attribute-on-non-trait.rs:14:1 | LL | #[marker] | ^^^^^^^^^ -LL | const CONST: usize = 10; - | ------------------------ not a trait + | + = help: `#[marker]` can only be applied to traits -error: attribute should be applied to a trait +error: `#[marker]` attribute cannot be used on functions --> $DIR/marker-attribute-on-non-trait.rs:17:1 | LL | #[marker] | ^^^^^^^^^ -LL | fn function() {} - | ---------------- not a trait + | + = help: `#[marker]` can only be applied to traits -error: attribute should be applied to a trait +error: `#[marker]` attribute cannot be used on type aliases --> $DIR/marker-attribute-on-non-trait.rs:20:1 | LL | #[marker] | ^^^^^^^^^ -LL | type Type = (); - | --------------- not a trait + | + = help: `#[marker]` can only be applied to traits error: aborting due to 6 previous errors diff --git a/tests/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr b/tests/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr index dfc983bf487..e2aa5718cb6 100644 --- a/tests/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr +++ b/tests/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr @@ -10,7 +10,7 @@ LL | let _f = to_fn(|| test(i)); | | | captured by this `Fn` closure | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/moves-based-on-type-move-out-of-closure-env-issue-1965.rs:3:33 | LL | fn to_fn<A:std::marker::Tuple,F:Fn<A>>(f: F) -> F { f } diff --git a/tests/ui/nll/issue-52663-span-decl-captured-variable.stderr b/tests/ui/nll/issue-52663-span-decl-captured-variable.stderr index 7f9a8e50dae..4749e3b8e45 100644 --- a/tests/ui/nll/issue-52663-span-decl-captured-variable.stderr +++ b/tests/ui/nll/issue-52663-span-decl-captured-variable.stderr @@ -10,7 +10,7 @@ LL | expect_fn(|| drop(x.0)); | | | captured by this `Fn` closure | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/issue-52663-span-decl-captured-variable.rs:1:33 | LL | fn expect_fn<F>(f: F) where F : Fn() { diff --git a/tests/ui/or-patterns/issue-64879-trailing-before-guard.fixed b/tests/ui/or-patterns/issue-64879-trailing-before-guard.fixed new file mode 100644 index 00000000000..0c65f709d66 --- /dev/null +++ b/tests/ui/or-patterns/issue-64879-trailing-before-guard.fixed @@ -0,0 +1,18 @@ +// In this regression test we check that a trailing `|` in an or-pattern just +// before the `if` token of a `match` guard will receive parser recovery with +// an appropriate error message. +//@ run-rustfix +#![allow(dead_code)] + +enum E { A, B } + +fn main() { + match E::A { + E::A | + E::B //~ ERROR a trailing `|` is not allowed in an or-pattern + if true => { + let _recovery_witness: i32 = 0i32; //~ ERROR mismatched types + } + _ => {} + } +} diff --git a/tests/ui/or-patterns/issue-64879-trailing-before-guard.rs b/tests/ui/or-patterns/issue-64879-trailing-before-guard.rs index 181c770096a..d7da564c2e1 100644 --- a/tests/ui/or-patterns/issue-64879-trailing-before-guard.rs +++ b/tests/ui/or-patterns/issue-64879-trailing-before-guard.rs @@ -1,6 +1,8 @@ // In this regression test we check that a trailing `|` in an or-pattern just // before the `if` token of a `match` guard will receive parser recovery with // an appropriate error message. +//@ run-rustfix +#![allow(dead_code)] enum E { A, B } @@ -9,7 +11,8 @@ fn main() { E::A | E::B | //~ ERROR a trailing `|` is not allowed in an or-pattern if true => { - let recovery_witness: bool = 0; //~ ERROR mismatched types + let _recovery_witness: i32 = 0u32; //~ ERROR mismatched types } + _ => {} } } diff --git a/tests/ui/or-patterns/issue-64879-trailing-before-guard.stderr b/tests/ui/or-patterns/issue-64879-trailing-before-guard.stderr index 91db3d049f6..238c76080dc 100644 --- a/tests/ui/or-patterns/issue-64879-trailing-before-guard.stderr +++ b/tests/ui/or-patterns/issue-64879-trailing-before-guard.stderr @@ -1,24 +1,24 @@ error: a trailing `|` is not allowed in an or-pattern - --> $DIR/issue-64879-trailing-before-guard.rs:10:14 + --> $DIR/issue-64879-trailing-before-guard.rs:12:14 | LL | E::A | | ---- while parsing this or-pattern starting here LL | E::B | | ^ + +error[E0308]: mismatched types + --> $DIR/issue-64879-trailing-before-guard.rs:14:42 | -help: remove the `|` +LL | let _recovery_witness: i32 = 0u32; + | --- ^^^^ expected `i32`, found `u32` + | | + | expected due to this | -LL - E::B | -LL + E::B +help: change the type of the numeric literal from `u32` to `i32` | - -error[E0308]: mismatched types - --> $DIR/issue-64879-trailing-before-guard.rs:12:42 +LL - let _recovery_witness: i32 = 0u32; +LL + let _recovery_witness: i32 = 0i32; | -LL | let recovery_witness: bool = 0; - | ---- ^ expected `bool`, found integer - | | - | expected due to this error: aborting due to 2 previous errors diff --git a/tests/ui/or-patterns/remove-leading-vert.fixed b/tests/ui/or-patterns/remove-leading-vert.fixed index 2851b8f18c5..aa7975dc508 100644 --- a/tests/ui/or-patterns/remove-leading-vert.fixed +++ b/tests/ui/or-patterns/remove-leading-vert.fixed @@ -23,26 +23,26 @@ fn leading() { #[cfg(false)] fn trailing() { - let ( A ): E; //~ ERROR a trailing `|` is not allowed in an or-pattern - let (a ,): (E,); //~ ERROR a trailing `|` is not allowed in an or-pattern - let ( A | B ): E; //~ ERROR a trailing `|` is not allowed in an or-pattern - let [ A | B ]: [E; 1]; //~ ERROR a trailing `|` is not allowed in an or-pattern - let S { f: B }; //~ ERROR a trailing `|` is not allowed in an or-pattern - let ( A | B ): E; //~ ERROR unexpected token `||` in pattern + let ( A ): E; //~ ERROR a trailing `|` is not allowed in an or-pattern + let (a,): (E,); //~ ERROR a trailing `|` is not allowed in an or-pattern + let ( A | B ): E; //~ ERROR a trailing `|` is not allowed in an or-pattern + let [ A | B ]: [E; 1]; //~ ERROR a trailing `|` is not allowed in an or-pattern + let S { f: B }; //~ ERROR a trailing `|` is not allowed in an or-pattern + let ( A | B ): E; //~ ERROR unexpected token `||` in pattern //~^ ERROR a trailing `|` is not allowed in an or-pattern match A { - A => {} //~ ERROR a trailing `|` is not allowed in an or-pattern - A => {} //~ ERROR a trailing `|` is not allowed in an or-pattern - A | B => {} //~ ERROR unexpected token `||` in pattern + A => {} //~ ERROR a trailing `|` is not allowed in an or-pattern + A => {} //~ ERROR a trailing `||` is not allowed in an or-pattern + A | B => {} //~ ERROR unexpected token `||` in pattern //~^ ERROR a trailing `|` is not allowed in an or-pattern - | A | B => {} + | A | B => {} //~^ ERROR a trailing `|` is not allowed in an or-pattern } // These test trailing-vert in `let` bindings, but they also test that we don't emit a // duplicate suggestion that would confuse rustfix. - let a : u8 = 0; //~ ERROR a trailing `|` is not allowed in an or-pattern - let a = 0; //~ ERROR a trailing `|` is not allowed in an or-pattern - let a ; //~ ERROR a trailing `|` is not allowed in an or-pattern + let a : u8 = 0; //~ ERROR a trailing `|` is not allowed in an or-pattern + let a = 0; //~ ERROR a trailing `|` is not allowed in an or-pattern + let a ; //~ ERROR a trailing `|` is not allowed in an or-pattern } diff --git a/tests/ui/or-patterns/remove-leading-vert.rs b/tests/ui/or-patterns/remove-leading-vert.rs index 1e1dbfbc6e6..1b4eb669fbb 100644 --- a/tests/ui/or-patterns/remove-leading-vert.rs +++ b/tests/ui/or-patterns/remove-leading-vert.rs @@ -32,7 +32,7 @@ fn trailing() { //~^ ERROR a trailing `|` is not allowed in an or-pattern match A { A | => {} //~ ERROR a trailing `|` is not allowed in an or-pattern - A || => {} //~ ERROR a trailing `|` is not allowed in an or-pattern + A || => {} //~ ERROR a trailing `||` is not allowed in an or-pattern A || B | => {} //~ ERROR unexpected token `||` in pattern //~^ ERROR a trailing `|` is not allowed in an or-pattern | A | B | => {} diff --git a/tests/ui/or-patterns/remove-leading-vert.stderr b/tests/ui/or-patterns/remove-leading-vert.stderr index 0323c64f042..29450153ba4 100644 --- a/tests/ui/or-patterns/remove-leading-vert.stderr +++ b/tests/ui/or-patterns/remove-leading-vert.stderr @@ -3,12 +3,6 @@ error: function parameters require top-level or-patterns in parentheses | LL | fn fun1( | A: E) {} | ^^^ - | -help: remove the `|` - | -LL - fn fun1( | A: E) {} -LL + fn fun1( A: E) {} - | error: unexpected `||` before function parameter --> $DIR/remove-leading-vert.rs:12:14 @@ -78,12 +72,6 @@ LL | let ( A | ): E; | - ^ | | | while parsing this or-pattern starting here - | -help: remove the `|` - | -LL - let ( A | ): E; -LL + let ( A ): E; - | error: a trailing `|` is not allowed in an or-pattern --> $DIR/remove-leading-vert.rs:27:12 @@ -92,12 +80,6 @@ LL | let (a |,): (E,); | - ^ | | | while parsing this or-pattern starting here - | -help: remove the `|` - | -LL - let (a |,): (E,); -LL + let (a ,): (E,); - | error: a trailing `|` is not allowed in an or-pattern --> $DIR/remove-leading-vert.rs:28:17 @@ -106,12 +88,6 @@ LL | let ( A | B | ): E; | - ^ | | | while parsing this or-pattern starting here - | -help: remove the `|` - | -LL - let ( A | B | ): E; -LL + let ( A | B ): E; - | error: a trailing `|` is not allowed in an or-pattern --> $DIR/remove-leading-vert.rs:29:17 @@ -120,12 +96,6 @@ LL | let [ A | B | ]: [E; 1]; | - ^ | | | while parsing this or-pattern starting here - | -help: remove the `|` - | -LL - let [ A | B | ]: [E; 1]; -LL + let [ A | B ]: [E; 1]; - | error: a trailing `|` is not allowed in an or-pattern --> $DIR/remove-leading-vert.rs:30:18 @@ -134,12 +104,6 @@ LL | let S { f: B | }; | - ^ | | | while parsing this or-pattern starting here - | -help: remove the `|` - | -LL - let S { f: B | }; -LL + let S { f: B }; - | error: unexpected token `||` in pattern --> $DIR/remove-leading-vert.rs:31:13 @@ -162,12 +126,6 @@ LL | let ( A || B | ): E; | - ^ | | | while parsing this or-pattern starting here - | -help: remove the `|` - | -LL - let ( A || B | ): E; -LL + let ( A || B ): E; - | error: a trailing `|` is not allowed in an or-pattern --> $DIR/remove-leading-vert.rs:34:11 @@ -176,14 +134,8 @@ LL | A | => {} | - ^ | | | while parsing this or-pattern starting here - | -help: remove the `|` - | -LL - A | => {} -LL + A => {} - | -error: a trailing `|` is not allowed in an or-pattern +error: a trailing `||` is not allowed in an or-pattern --> $DIR/remove-leading-vert.rs:35:11 | LL | A || => {} @@ -192,11 +144,6 @@ LL | A || => {} | while parsing this or-pattern starting here | = note: alternatives in or-patterns are separated with `|`, not `||` -help: remove the `||` - | -LL - A || => {} -LL + A => {} - | error: unexpected token `||` in pattern --> $DIR/remove-leading-vert.rs:36:11 @@ -219,12 +166,6 @@ LL | A || B | => {} | - ^ | | | while parsing this or-pattern starting here - | -help: remove the `|` - | -LL - A || B | => {} -LL + A || B => {} - | error: a trailing `|` is not allowed in an or-pattern --> $DIR/remove-leading-vert.rs:38:17 @@ -233,12 +174,6 @@ LL | | A | B | => {} | - ^ | | | while parsing this or-pattern starting here - | -help: remove the `|` - | -LL - | A | B | => {} -LL + | A | B => {} - | error: a trailing `|` is not allowed in an or-pattern --> $DIR/remove-leading-vert.rs:45:11 @@ -247,12 +182,6 @@ LL | let a | : u8 = 0; | - ^ | | | while parsing this or-pattern starting here - | -help: remove the `|` - | -LL - let a | : u8 = 0; -LL + let a : u8 = 0; - | error: a trailing `|` is not allowed in an or-pattern --> $DIR/remove-leading-vert.rs:46:11 @@ -261,12 +190,6 @@ LL | let a | = 0; | - ^ | | | while parsing this or-pattern starting here - | -help: remove the `|` - | -LL - let a | = 0; -LL + let a = 0; - | error: a trailing `|` is not allowed in an or-pattern --> $DIR/remove-leading-vert.rs:47:11 @@ -275,12 +198,6 @@ LL | let a | ; | - ^ | | | while parsing this or-pattern starting here - | -help: remove the `|` - | -LL - let a | ; -LL + let a ; - | error: aborting due to 21 previous errors diff --git a/tests/ui/panic-handler/panic-handler-wrong-location.stderr b/tests/ui/panic-handler/panic-handler-wrong-location.stderr index 66ee91aa4c1..9b361bf8d60 100644 --- a/tests/ui/panic-handler/panic-handler-wrong-location.stderr +++ b/tests/ui/panic-handler/panic-handler-wrong-location.stderr @@ -2,7 +2,7 @@ error[E0718]: `panic_impl` lang item must be applied to a function --> $DIR/panic-handler-wrong-location.rs:6:1 | LL | #[panic_handler] - | ^^^^^^^^^^^^^^^^ attribute should be applied to a function, not a static item + | ^^^^^^^^^^^^^^^^ attribute should be applied to a function, not a static error: `#[panic_handler]` function required, but not found diff --git a/tests/ui/proc-macro/illegal-proc-macro-derive-use.rs b/tests/ui/proc-macro/illegal-proc-macro-derive-use.rs index 4efd9e952fc..19473fb2caf 100644 --- a/tests/ui/proc-macro/illegal-proc-macro-derive-use.rs +++ b/tests/ui/proc-macro/illegal-proc-macro-derive-use.rs @@ -8,7 +8,7 @@ pub fn foo(a: proc_macro::TokenStream) -> proc_macro::TokenStream { // Issue #37590 #[proc_macro_derive(Foo)] -//~^ ERROR: the `#[proc_macro_derive]` attribute may only be used on bare functions +//~^ ERROR: attribute cannot be used on pub struct Foo { } diff --git a/tests/ui/proc-macro/illegal-proc-macro-derive-use.stderr b/tests/ui/proc-macro/illegal-proc-macro-derive-use.stderr index c0930ab7102..f01619b9195 100644 --- a/tests/ui/proc-macro/illegal-proc-macro-derive-use.stderr +++ b/tests/ui/proc-macro/illegal-proc-macro-derive-use.stderr @@ -4,11 +4,13 @@ error: the `#[proc_macro_derive]` attribute is only usable with crates of the `p LL | #[proc_macro_derive(Foo)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: the `#[proc_macro_derive]` attribute may only be used on bare functions +error: `#[proc_macro_derive]` attribute cannot be used on structs --> $DIR/illegal-proc-macro-derive-use.rs:10:1 | LL | #[proc_macro_derive(Foo)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[proc_macro_derive]` can only be applied to functions error: aborting due to 2 previous errors diff --git a/tests/ui/proc-macro/macro-namespace-reserved-2.stderr b/tests/ui/proc-macro/macro-namespace-reserved-2.stderr index 0471124061e..c8a7cc3ba91 100644 --- a/tests/ui/proc-macro/macro-namespace-reserved-2.stderr +++ b/tests/ui/proc-macro/macro-namespace-reserved-2.stderr @@ -95,14 +95,6 @@ error: expected derive macro, found macro `crate::my_macro` | LL | #[derive(crate::my_macro)] | ^^^^^^^^^^^^^^^ not a derive macro - | -help: remove from the surrounding `derive()` - --> $DIR/macro-namespace-reserved-2.rs:50:10 - | -LL | #[derive(crate::my_macro)] - | ^^^^^^^^^^^^^^^ - = help: add as non-Derive macro - `#[crate::my_macro]` error: cannot find macro `my_macro_attr` in this scope --> $DIR/macro-namespace-reserved-2.rs:28:5 diff --git a/tests/ui/proc-macro/proc-macro-attributes.stderr b/tests/ui/proc-macro/proc-macro-attributes.stderr index 2cc57383eb3..892728901fb 100644 --- a/tests/ui/proc-macro/proc-macro-attributes.stderr +++ b/tests/ui/proc-macro/proc-macro-attributes.stderr @@ -2,7 +2,13 @@ error: cannot find attribute `C` in this scope --> $DIR/proc-macro-attributes.rs:9:3 | LL | #[C] - | ^ help: a derive helper attribute with a similar name exists: `B` + | ^ + | +help: the derive macro `B` accepts the similarly named `B` attribute + | +LL - #[C] +LL + #[B] + | error[E0659]: `B` is ambiguous --> $DIR/proc-macro-attributes.rs:6:3 diff --git a/tests/ui/resolve/extern-prelude-speculative.rs b/tests/ui/resolve/extern-prelude-speculative.rs new file mode 100644 index 00000000000..afbc32d22ac --- /dev/null +++ b/tests/ui/resolve/extern-prelude-speculative.rs @@ -0,0 +1,10 @@ +// Non-existent path in `--extern` doesn't result in an error if it's shadowed by `extern crate`. + +//@ check-pass +//@ compile-flags: --extern something=/path/to/nowhere + +extern crate std as something; + +fn main() { + something::println!(); +} diff --git a/tests/ui/resolve/visibility-indeterminate.rs b/tests/ui/resolve/visibility-indeterminate.rs index 17e5fec4701..181bb290774 100644 --- a/tests/ui/resolve/visibility-indeterminate.rs +++ b/tests/ui/resolve/visibility-indeterminate.rs @@ -2,6 +2,6 @@ foo!(); //~ ERROR cannot find macro `foo` in this scope -pub(in ::bar) struct Baz {} //~ ERROR cannot determine resolution for the visibility +pub(in ::bar) struct Baz {} //~ ERROR failed to resolve: could not find `bar` in the list of imported crates fn main() {} diff --git a/tests/ui/resolve/visibility-indeterminate.stderr b/tests/ui/resolve/visibility-indeterminate.stderr index 84d82ce8522..bbe28747f7c 100644 --- a/tests/ui/resolve/visibility-indeterminate.stderr +++ b/tests/ui/resolve/visibility-indeterminate.stderr @@ -1,8 +1,8 @@ -error[E0578]: cannot determine resolution for the visibility - --> $DIR/visibility-indeterminate.rs:5:8 +error[E0433]: failed to resolve: could not find `bar` in the list of imported crates + --> $DIR/visibility-indeterminate.rs:5:10 | LL | pub(in ::bar) struct Baz {} - | ^^^^^ + | ^^^ could not find `bar` in the list of imported crates error: cannot find macro `foo` in this scope --> $DIR/visibility-indeterminate.rs:3:1 @@ -12,4 +12,4 @@ LL | foo!(); error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0578`. +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/ICE-130779-never-arm-no-oatherwise-block.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/ICE-130779-never-arm-no-oatherwise-block.stderr index 26731e29ffc..5f4a5f31e34 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/ICE-130779-never-arm-no-oatherwise-block.stderr +++ b/tests/ui/rfcs/rfc-0000-never_patterns/ICE-130779-never-arm-no-oatherwise-block.stderr @@ -5,12 +5,6 @@ LL | ! | | - ^ | | | while parsing this or-pattern starting here - | -help: remove the `|` - | -LL - ! | -LL + ! - | error: a never pattern is always unreachable --> $DIR/ICE-130779-never-arm-no-oatherwise-block.rs:10:20 diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.rs index 143f9a3009b..b538a97280d 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.rs +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.rs @@ -3,11 +3,11 @@ struct Foo; #[non_exhaustive] -//~^ ERROR attribute should be applied to a struct or enum [E0701] +//~^ ERROR attribute cannot be used on trait Bar { } #[non_exhaustive] -//~^ ERROR attribute should be applied to a struct or enum [E0701] +//~^ ERROR attribute cannot be used on union Baz { f1: u16, f2: u16 diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.stderr index 1ac017aa08b..3522c459977 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.stderr @@ -7,28 +7,22 @@ LL | #[non_exhaustive(anything)] | | didn't expect any arguments here | help: must be of the form: `#[non_exhaustive]` -error[E0701]: attribute should be applied to a struct or enum +error: `#[non_exhaustive]` attribute cannot be used on traits --> $DIR/invalid-attribute.rs:5:1 | LL | #[non_exhaustive] | ^^^^^^^^^^^^^^^^^ -LL | -LL | trait Bar { } - | ------------- not a struct or enum + | + = help: `#[non_exhaustive]` can be applied to data types, enum variants -error[E0701]: attribute should be applied to a struct or enum +error: `#[non_exhaustive]` attribute cannot be used on unions --> $DIR/invalid-attribute.rs:9:1 | -LL | #[non_exhaustive] - | ^^^^^^^^^^^^^^^^^ -LL | -LL | / union Baz { -LL | | f1: u16, -LL | | f2: u16 -LL | | } - | |_- not a struct or enum +LL | #[non_exhaustive] + | ^^^^^^^^^^^^^^^^^ + | + = help: `#[non_exhaustive]` can be applied to data types, enum variants error: aborting due to 3 previous errors -Some errors have detailed explanations: E0565, E0701. -For more information about an error, try `rustc --explain E0565`. +For more information about this error, try `rustc --explain E0565`. diff --git a/tests/ui/rfcs/rfc-2091-track-caller/only-for-fns.rs b/tests/ui/rfcs/rfc-2091-track-caller/only-for-fns.rs index 2d2b01b6f94..53a856e0df3 100644 --- a/tests/ui/rfcs/rfc-2091-track-caller/only-for-fns.rs +++ b/tests/ui/rfcs/rfc-2091-track-caller/only-for-fns.rs @@ -1,5 +1,5 @@ #[track_caller] struct S; -//~^^ ERROR attribute should be applied to a function definition +//~^^ ERROR attribute cannot be used on fn main() {} diff --git a/tests/ui/rfcs/rfc-2091-track-caller/only-for-fns.stderr b/tests/ui/rfcs/rfc-2091-track-caller/only-for-fns.stderr index f976b7f5210..6ff66be4e5c 100644 --- a/tests/ui/rfcs/rfc-2091-track-caller/only-for-fns.stderr +++ b/tests/ui/rfcs/rfc-2091-track-caller/only-for-fns.stderr @@ -1,11 +1,10 @@ -error[E0739]: attribute should be applied to a function definition +error: `#[track_caller]` attribute cannot be used on structs --> $DIR/only-for-fns.rs:1:1 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ -LL | struct S; - | --------- not a function definition + | + = help: `#[track_caller]` can only be applied to functions error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0739`. diff --git a/tests/ui/rust-2018/uniform-paths/deadlock.rs b/tests/ui/rust-2018/uniform-paths/deadlock.rs index 4011ba3ee28..d2296c51bdd 100644 --- a/tests/ui/rust-2018/uniform-paths/deadlock.rs +++ b/tests/ui/rust-2018/uniform-paths/deadlock.rs @@ -2,7 +2,7 @@ //@ compile-flags:--extern foo --extern bar use bar::foo; //~ ERROR can't find crate for `bar` -use foo::bar; //~ ERROR can't find crate for `foo` +use foo::bar; //~^^ ERROR unresolved imports `bar::foo`, `foo::bar` fn main() {} diff --git a/tests/ui/rust-2018/uniform-paths/deadlock.stderr b/tests/ui/rust-2018/uniform-paths/deadlock.stderr index 8b9863948bd..c50bc16ac55 100644 --- a/tests/ui/rust-2018/uniform-paths/deadlock.stderr +++ b/tests/ui/rust-2018/uniform-paths/deadlock.stderr @@ -4,12 +4,6 @@ error[E0463]: can't find crate for `bar` LL | use bar::foo; | ^^^ can't find crate -error[E0463]: can't find crate for `foo` - --> $DIR/deadlock.rs:5:5 - | -LL | use foo::bar; - | ^^^ can't find crate - error[E0432]: unresolved imports `bar::foo`, `foo::bar` --> $DIR/deadlock.rs:4:5 | @@ -18,7 +12,7 @@ LL | use bar::foo; LL | use foo::bar; | ^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0432, E0463. For more information about an error, try `rustc --explain E0432`. diff --git a/tests/ui/rustdoc/check-doc-alias-attr-location.stderr b/tests/ui/rustdoc/check-doc-alias-attr-location.stderr index 4244c11eb3e..23c93a4ed8b 100644 --- a/tests/ui/rustdoc/check-doc-alias-attr-location.stderr +++ b/tests/ui/rustdoc/check-doc-alias-attr-location.stderr @@ -10,13 +10,13 @@ error: `#[doc(alias = "...")]` isn't allowed on foreign module LL | #[doc(alias = "foo")] | ^^^^^^^^^^^^^ -error: `#[doc(alias = "...")]` isn't allowed on inherent implementation block +error: `#[doc(alias = "...")]` isn't allowed on implementation block --> $DIR/check-doc-alias-attr-location.rs:12:7 | LL | #[doc(alias = "bar")] | ^^^^^^^^^^^^^ -error: `#[doc(alias = "...")]` isn't allowed on trait implementation block +error: `#[doc(alias = "...")]` isn't allowed on implementation block --> $DIR/check-doc-alias-attr-location.rs:18:7 | LL | #[doc(alias = "foobar")] diff --git a/tests/ui/span/borrowck-call-is-borrow-issue-12224.stderr b/tests/ui/span/borrowck-call-is-borrow-issue-12224.stderr index 8081f7b3a8b..f7750884b4a 100644 --- a/tests/ui/span/borrowck-call-is-borrow-issue-12224.stderr +++ b/tests/ui/span/borrowck-call-is-borrow-issue-12224.stderr @@ -44,7 +44,7 @@ LL | LL | foo(f); | ^ move occurs because `f` has type `{closure@$DIR/borrowck-call-is-borrow-issue-12224.rs:52:17: 52:58}`, which does not implement the `Copy` trait | - = help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once + = help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once help: consider cloning the value if the performance cost is acceptable | LL | foo(f.clone()); diff --git a/tests/ui/suggestions/dont-suggest-ref/move-into-closure.stderr b/tests/ui/suggestions/dont-suggest-ref/move-into-closure.stderr index 132a31c8f7c..39c2fabf9eb 100644 --- a/tests/ui/suggestions/dont-suggest-ref/move-into-closure.stderr +++ b/tests/ui/suggestions/dont-suggest-ref/move-into-closure.stderr @@ -12,7 +12,7 @@ LL | let X(_t) = x; | data moved here | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:13:18 | LL | fn consume_fn<F: Fn()>(_f: F) { } @@ -37,7 +37,7 @@ LL | if let Either::One(_t) = e { } | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:13:18 | LL | fn consume_fn<F: Fn()>(_f: F) { } @@ -62,7 +62,7 @@ LL | while let Either::One(_t) = e { } | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:13:18 | LL | fn consume_fn<F: Fn()>(_f: F) { } @@ -90,7 +90,7 @@ LL | Either::One(_t) | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:13:18 | LL | fn consume_fn<F: Fn()>(_f: F) { } @@ -118,7 +118,7 @@ LL | Either::One(_t) => (), | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:13:18 | LL | fn consume_fn<F: Fn()>(_f: F) { } @@ -143,7 +143,7 @@ LL | let X(mut _t) = x; | data moved here | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:13:18 | LL | fn consume_fn<F: Fn()>(_f: F) { } @@ -168,7 +168,7 @@ LL | if let Either::One(mut _t) = em { } | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:13:18 | LL | fn consume_fn<F: Fn()>(_f: F) { } @@ -193,7 +193,7 @@ LL | while let Either::One(mut _t) = em { } | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:13:18 | LL | fn consume_fn<F: Fn()>(_f: F) { } @@ -221,7 +221,7 @@ LL | Either::One(mut _t) | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:13:18 | LL | fn consume_fn<F: Fn()>(_f: F) { } @@ -249,7 +249,7 @@ LL | Either::One(mut _t) => (), | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:13:18 | LL | fn consume_fn<F: Fn()>(_f: F) { } @@ -273,7 +273,7 @@ LL | let X(_t) = x; | data moved here | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:39:22 | LL | fn consume_fn<F: Fn()>(_f: F) { } @@ -298,7 +298,7 @@ LL | if let Either::One(_t) = e { } | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:39:22 | LL | fn consume_fn<F: Fn()>(_f: F) { } @@ -323,7 +323,7 @@ LL | while let Either::One(_t) = e { } | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:39:22 | LL | fn consume_fn<F: Fn()>(_f: F) { } @@ -351,7 +351,7 @@ LL | Either::One(_t) | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:39:22 | LL | fn consume_fn<F: Fn()>(_f: F) { } @@ -379,7 +379,7 @@ LL | Either::One(_t) => (), | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:39:22 | LL | fn consume_fn<F: Fn()>(_f: F) { } @@ -404,7 +404,7 @@ LL | let X(mut _t) = x; | data moved here | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:39:22 | LL | fn consume_fn<F: Fn()>(_f: F) { } @@ -429,7 +429,7 @@ LL | if let Either::One(mut _t) = em { } | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:39:22 | LL | fn consume_fn<F: Fn()>(_f: F) { } @@ -454,7 +454,7 @@ LL | while let Either::One(mut _t) = em { } | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:39:22 | LL | fn consume_fn<F: Fn()>(_f: F) { } @@ -482,7 +482,7 @@ LL | Either::One(mut _t) | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:39:22 | LL | fn consume_fn<F: Fn()>(_f: F) { } @@ -510,7 +510,7 @@ LL | Either::One(mut _t) => (), | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:39:22 | LL | fn consume_fn<F: Fn()>(_f: F) { } @@ -534,7 +534,7 @@ LL | let X(_t) = x; | data moved here | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:50:29 | LL | fn method_consume_fn<F: Fn()>(&self, _f: F) { } @@ -559,7 +559,7 @@ LL | if let Either::One(_t) = e { } | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:50:29 | LL | fn method_consume_fn<F: Fn()>(&self, _f: F) { } @@ -584,7 +584,7 @@ LL | while let Either::One(_t) = e { } | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:50:29 | LL | fn method_consume_fn<F: Fn()>(&self, _f: F) { } @@ -612,7 +612,7 @@ LL | Either::One(_t) | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:50:29 | LL | fn method_consume_fn<F: Fn()>(&self, _f: F) { } @@ -640,7 +640,7 @@ LL | Either::One(_t) => (), | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:50:29 | LL | fn method_consume_fn<F: Fn()>(&self, _f: F) { } @@ -665,7 +665,7 @@ LL | let X(mut _t) = x; | data moved here | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:50:29 | LL | fn method_consume_fn<F: Fn()>(&self, _f: F) { } @@ -690,7 +690,7 @@ LL | if let Either::One(mut _t) = em { } | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:50:29 | LL | fn method_consume_fn<F: Fn()>(&self, _f: F) { } @@ -715,7 +715,7 @@ LL | while let Either::One(mut _t) = em { } | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:50:29 | LL | fn method_consume_fn<F: Fn()>(&self, _f: F) { } @@ -743,7 +743,7 @@ LL | Either::One(mut _t) | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:50:29 | LL | fn method_consume_fn<F: Fn()>(&self, _f: F) { } @@ -771,7 +771,7 @@ LL | Either::One(mut _t) => (), | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:50:29 | LL | fn method_consume_fn<F: Fn()>(&self, _f: F) { } @@ -795,7 +795,7 @@ LL | let X(_t) = x; | data moved here | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:25:21 | LL | fn consume_fnmut<F: FnMut()>(_f: F) { } @@ -820,7 +820,7 @@ LL | if let Either::One(_t) = e { } | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:25:21 | LL | fn consume_fnmut<F: FnMut()>(_f: F) { } @@ -845,7 +845,7 @@ LL | while let Either::One(_t) = e { } | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:25:21 | LL | fn consume_fnmut<F: FnMut()>(_f: F) { } @@ -873,7 +873,7 @@ LL | Either::One(_t) | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:25:21 | LL | fn consume_fnmut<F: FnMut()>(_f: F) { } @@ -901,7 +901,7 @@ LL | Either::One(_t) => (), | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:25:21 | LL | fn consume_fnmut<F: FnMut()>(_f: F) { } @@ -926,7 +926,7 @@ LL | let X(mut _t) = x; | data moved here | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:25:21 | LL | fn consume_fnmut<F: FnMut()>(_f: F) { } @@ -951,7 +951,7 @@ LL | if let Either::One(mut _t) = em { } | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:25:21 | LL | fn consume_fnmut<F: FnMut()>(_f: F) { } @@ -976,7 +976,7 @@ LL | while let Either::One(mut _t) = em { } | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:25:21 | LL | fn consume_fnmut<F: FnMut()>(_f: F) { } @@ -1004,7 +1004,7 @@ LL | Either::One(mut _t) | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:25:21 | LL | fn consume_fnmut<F: FnMut()>(_f: F) { } @@ -1032,7 +1032,7 @@ LL | Either::One(mut _t) => (), | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:25:21 | LL | fn consume_fnmut<F: FnMut()>(_f: F) { } @@ -1060,7 +1060,7 @@ LL | Either::One(mut _t) => (), | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/move-into-closure.rs:25:21 | LL | fn consume_fnmut<F: FnMut()>(_f: F) { } diff --git a/tests/ui/suggestions/option-content-move2.stderr b/tests/ui/suggestions/option-content-move2.stderr index c8aa6667b58..5bcbdd711ae 100644 --- a/tests/ui/suggestions/option-content-move2.stderr +++ b/tests/ui/suggestions/option-content-move2.stderr @@ -14,7 +14,7 @@ LL | LL | var = Some(NotCopyable); | --- variable moved due to use in closure | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/option-content-move2.rs:5:12 | LL | fn func<F: FnMut() -> H, H: FnMut()>(_: F) {} @@ -44,7 +44,7 @@ LL | LL | var = Some(NotCopyableButCloneable); | --- variable moved due to use in closure | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/option-content-move2.rs:5:12 | LL | fn func<F: FnMut() -> H, H: FnMut()>(_: F) {} diff --git a/tests/ui/suggestions/option-content-move3.stderr b/tests/ui/suggestions/option-content-move3.stderr index 2c9a86c036b..f78d3cf6786 100644 --- a/tests/ui/suggestions/option-content-move3.stderr +++ b/tests/ui/suggestions/option-content-move3.stderr @@ -9,7 +9,7 @@ LL | move || { LL | let x = var; | ^^^ move occurs because `var` has type `NotCopyable`, which does not implement the `Copy` trait | - = help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once + = help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once note: if `NotCopyable` implemented `Clone`, you could clone the value --> $DIR/option-content-move3.rs:2:1 | @@ -38,7 +38,7 @@ LL | move || { LL | let x = var; | --- variable moved due to use in closure | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/option-content-move3.rs:6:12 | LL | fn func<F: FnMut() -> H, H: FnMut()>(_: F) {} @@ -63,7 +63,7 @@ LL | move || { LL | let x = var; | ^^^ move occurs because `var` has type `NotCopyableButCloneable`, which does not implement the `Copy` trait | - = help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once + = help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once help: consider borrowing here | LL | let x = &var; @@ -84,7 +84,7 @@ LL | move || { LL | let x = var; | --- variable moved due to use in closure | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/option-content-move3.rs:6:12 | LL | fn func<F: FnMut() -> H, H: FnMut()>(_: F) {} diff --git a/tests/ui/target-feature/gate.rs b/tests/ui/target-feature/gate.rs index 81ed8b3de76..fc3763820cb 100644 --- a/tests/ui/target-feature/gate.rs +++ b/tests/ui/target-feature/gate.rs @@ -1,18 +1,12 @@ //@ only-x86_64 // -// gate-test-sse4a_target_feature // gate-test-powerpc_target_feature -// gate-test-tbm_target_feature // gate-test-arm_target_feature // gate-test-hexagon_target_feature // gate-test-mips_target_feature // gate-test-nvptx_target_feature // gate-test-wasm_target_feature -// gate-test-adx_target_feature -// gate-test-cmpxchg16b_target_feature -// gate-test-movbe_target_feature // gate-test-rtm_target_feature -// gate-test-f16c_target_feature // gate-test-riscv_target_feature // gate-test-ermsb_target_feature // gate-test-bpf_target_feature diff --git a/tests/ui/target-feature/gate.stderr b/tests/ui/target-feature/gate.stderr index 3e9374be73d..345dc2006d0 100644 --- a/tests/ui/target-feature/gate.stderr +++ b/tests/ui/target-feature/gate.stderr @@ -1,5 +1,5 @@ error[E0658]: the target feature `x87` is currently unstable - --> $DIR/gate.rs:30:18 + --> $DIR/gate.rs:24:18 | LL | #[target_feature(enable = "x87")] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/target-feature/invalid-attribute.rs b/tests/ui/target-feature/invalid-attribute.rs index d13098c3a6a..b34a48aba26 100644 --- a/tests/ui/target-feature/invalid-attribute.rs +++ b/tests/ui/target-feature/invalid-attribute.rs @@ -3,19 +3,16 @@ #![warn(unused_attributes)] #[target_feature(enable = "sse2")] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on extern crate alloc; -//~^ NOTE not a function #[target_feature(enable = "sse2")] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on use alloc::alloc::alloc; -//~^ NOTE not a function #[target_feature(enable = "sse2")] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on extern "Rust" {} -//~^ NOTE not a function #[target_feature = "+sse2"] //~^ ERROR malformed `target_feature` attribute @@ -32,42 +29,35 @@ extern "Rust" {} unsafe fn foo() {} #[target_feature(enable = "sse2")] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on mod another {} -//~^ NOTE not a function #[target_feature(enable = "sse2")] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on const FOO: usize = 7; -//~^ NOTE not a function #[target_feature(enable = "sse2")] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on struct Foo; -//~^ NOTE not a function #[target_feature(enable = "sse2")] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on enum Bar {} -//~^ NOTE not a function #[target_feature(enable = "sse2")] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on union Qux { - //~^ NOTE not a function - f1: u16, + f1: u16, f2: u16, } #[target_feature(enable = "sse2")] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on type Uwu = (); -//~^ NOTE not a function #[target_feature(enable = "sse2")] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on trait Baz {} -//~^ NOTE not a function #[inline(always)] //~^ ERROR: cannot use `#[inline(always)]` @@ -75,21 +65,18 @@ trait Baz {} unsafe fn test() {} #[target_feature(enable = "sse2")] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on static A: () = (); -//~^ NOTE not a function #[target_feature(enable = "sse2")] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on impl Quux for u8 {} -//~^ NOTE not a function -//~| NOTE missing `foo` in implementation +//~^ NOTE missing `foo` in implementation //~| ERROR missing: `foo` #[target_feature(enable = "sse2")] -//~^ ERROR attribute should be applied to a function +//~^ ERROR attribute cannot be used on impl Foo {} -//~^ NOTE not a function trait Quux { fn foo(); //~ NOTE `foo` from trait @@ -109,17 +96,15 @@ impl Quux for Foo { fn main() { #[target_feature(enable = "sse2")] - //~^ ERROR attribute should be applied to a function + //~^ ERROR attribute cannot be used on unsafe { foo(); } - //~^^^ NOTE not a function #[target_feature(enable = "sse2")] - //~^ ERROR attribute should be applied to a function + //~^ ERROR attribute cannot be used on || {}; - //~^ NOTE not a function -} + } #[target_feature(enable = "+sse2")] //~^ ERROR `+sse2` is not valid for this target diff --git a/tests/ui/target-feature/invalid-attribute.stderr b/tests/ui/target-feature/invalid-attribute.stderr index 113c0c3695a..a0117649a57 100644 --- a/tests/ui/target-feature/invalid-attribute.stderr +++ b/tests/ui/target-feature/invalid-attribute.stderr @@ -1,5 +1,29 @@ +error: `#[target_feature]` attribute cannot be used on extern crates + --> $DIR/invalid-attribute.rs:5:1 + | +LL | #[target_feature(enable = "sse2")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[target_feature]` can only be applied to functions + +error: `#[target_feature]` attribute cannot be used on use statements + --> $DIR/invalid-attribute.rs:9:1 + | +LL | #[target_feature(enable = "sse2")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[target_feature]` can only be applied to functions + +error: `#[target_feature]` attribute cannot be used on foreign modules + --> $DIR/invalid-attribute.rs:13:1 + | +LL | #[target_feature(enable = "sse2")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[target_feature]` can only be applied to functions + error[E0539]: malformed `target_feature` attribute input - --> $DIR/invalid-attribute.rs:20:1 + --> $DIR/invalid-attribute.rs:17:1 | LL | #[target_feature = "+sse2"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +32,7 @@ LL | #[target_feature = "+sse2"] | help: must be of the form: `#[target_feature(enable = "feat1, feat2")]` error[E0539]: malformed `target_feature` attribute input - --> $DIR/invalid-attribute.rs:26:1 + --> $DIR/invalid-attribute.rs:23:1 | LL | #[target_feature(bar)] | ^^^^^^^^^^^^^^^^^---^^ @@ -17,7 +41,7 @@ LL | #[target_feature(bar)] | help: must be of the form: `#[target_feature(enable = "feat1, feat2")]` error[E0539]: malformed `target_feature` attribute input - --> $DIR/invalid-attribute.rs:29:1 + --> $DIR/invalid-attribute.rs:26:1 | LL | #[target_feature(disable = "baz")] | ^^^^^^^^^^^^^^^^^-------^^^^^^^^^^ @@ -25,161 +49,116 @@ LL | #[target_feature(disable = "baz")] | | expected this to be of the form `enable = "..."` | help: must be of the form: `#[target_feature(enable = "feat1, feat2")]` -error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:5:1 +error: `#[target_feature]` attribute cannot be used on modules + --> $DIR/invalid-attribute.rs:31:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | extern crate alloc; - | ------------------- not a function definition - -error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:10:1 | -LL | #[target_feature(enable = "sse2")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | use alloc::alloc::alloc; - | ------------------------ not a function definition + = help: `#[target_feature]` can only be applied to functions -error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:15:1 +error: `#[target_feature]` attribute cannot be used on constants + --> $DIR/invalid-attribute.rs:35:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | extern "Rust" {} - | ---------------- not a function definition - -error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:34:1 | -LL | #[target_feature(enable = "sse2")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | mod another {} - | -------------- not a function definition + = help: `#[target_feature]` can only be applied to functions -error: attribute should be applied to a function definition +error: `#[target_feature]` attribute cannot be used on structs --> $DIR/invalid-attribute.rs:39:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | const FOO: usize = 7; - | --------------------- not a function definition + | + = help: `#[target_feature]` can only be applied to functions -error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:44:1 +error: `#[target_feature]` attribute cannot be used on enums + --> $DIR/invalid-attribute.rs:43:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | struct Foo; - | ----------- not a function definition + | + = help: `#[target_feature]` can only be applied to functions -error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:49:1 +error: `#[target_feature]` attribute cannot be used on unions + --> $DIR/invalid-attribute.rs:47:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | enum Bar {} - | ----------- not a function definition + | + = help: `#[target_feature]` can only be applied to functions -error: attribute should be applied to a function definition +error: `#[target_feature]` attribute cannot be used on type aliases --> $DIR/invalid-attribute.rs:54:1 | -LL | #[target_feature(enable = "sse2")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | / union Qux { -LL | | -LL | | f1: u16, -LL | | f2: u16, -LL | | } - | |_- not a function definition - -error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:62:1 - | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | type Uwu = (); - | -------------- not a function definition + | + = help: `#[target_feature]` can only be applied to functions -error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:67:1 +error: `#[target_feature]` attribute cannot be used on traits + --> $DIR/invalid-attribute.rs:58:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | trait Baz {} - | ------------ not a function definition - -error: cannot use `#[inline(always)]` with `#[target_feature]` - --> $DIR/invalid-attribute.rs:72:1 | -LL | #[inline(always)] - | ^^^^^^^^^^^^^^^^^ + = help: `#[target_feature]` can only be applied to functions -error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:77:1 +error: `#[target_feature]` attribute cannot be used on statics + --> $DIR/invalid-attribute.rs:67:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | static A: () = (); - | ------------------ not a function definition + | + = help: `#[target_feature]` can only be applied to functions -error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:82:1 +error: `#[target_feature]` attribute cannot be used on trait impl blocks + --> $DIR/invalid-attribute.rs:71:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | impl Quux for u8 {} - | ------------------- not a function definition + | + = help: `#[target_feature]` can only be applied to functions -error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:89:1 +error: `#[target_feature]` attribute cannot be used on inherent impl blocks + --> $DIR/invalid-attribute.rs:77:1 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | impl Foo {} - | ----------- not a function definition + | + = help: `#[target_feature]` can only be applied to functions -error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:111:5 +error: `#[target_feature]` attribute cannot be used on expressions + --> $DIR/invalid-attribute.rs:98:5 | -LL | #[target_feature(enable = "sse2")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | / unsafe { -LL | | foo(); -LL | | } - | |_____- not a function definition +LL | #[target_feature(enable = "sse2")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[target_feature]` can only be applied to functions -error: attribute should be applied to a function definition - --> $DIR/invalid-attribute.rs:118:5 +error: `#[target_feature]` attribute cannot be used on closures + --> $DIR/invalid-attribute.rs:104:5 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | || {}; - | ----- not a function definition + | + = help: `#[target_feature]` can be applied to methods, functions + +error: cannot use `#[inline(always)]` with `#[target_feature]` + --> $DIR/invalid-attribute.rs:62:1 + | +LL | #[inline(always)] + | ^^^^^^^^^^^^^^^^^ error: the feature named `foo` is not valid for this target - --> $DIR/invalid-attribute.rs:23:18 + --> $DIR/invalid-attribute.rs:20:18 | LL | #[target_feature(enable = "foo")] | ^^^^^^^^^^^^^^ `foo` is not valid for this target error[E0046]: not all trait items implemented, missing: `foo` - --> $DIR/invalid-attribute.rs:84:1 + --> $DIR/invalid-attribute.rs:73:1 | LL | impl Quux for u8 {} | ^^^^^^^^^^^^^^^^ missing `foo` in implementation @@ -188,7 +167,7 @@ LL | fn foo(); | --------- `foo` from trait error: `#[target_feature(..)]` cannot be applied to safe trait method - --> $DIR/invalid-attribute.rs:100:5 + --> $DIR/invalid-attribute.rs:87:5 | LL | #[target_feature(enable = "sse2")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot be applied to safe trait method @@ -197,13 +176,13 @@ LL | fn foo() {} | -------- not an `unsafe` function error[E0053]: method `foo` has an incompatible type for trait - --> $DIR/invalid-attribute.rs:103:5 + --> $DIR/invalid-attribute.rs:90:5 | LL | fn foo() {} | ^^^^^^^^ expected safe fn, found unsafe fn | note: type in trait - --> $DIR/invalid-attribute.rs:95:5 + --> $DIR/invalid-attribute.rs:82:5 | LL | fn foo(); | ^^^^^^^^^ @@ -211,7 +190,7 @@ LL | fn foo(); found signature `#[target_features] fn()` error: the feature named `+sse2` is not valid for this target - --> $DIR/invalid-attribute.rs:124:18 + --> $DIR/invalid-attribute.rs:109:18 | LL | #[target_feature(enable = "+sse2")] | ^^^^^^^^^^^^^^^^ `+sse2` is not valid for this target diff --git a/tests/ui/traits/alias/not-a-marker.rs b/tests/ui/traits/alias/not-a-marker.rs index b004b9ff9ae..633cc60554d 100644 --- a/tests/ui/traits/alias/not-a-marker.rs +++ b/tests/ui/traits/alias/not-a-marker.rs @@ -1,7 +1,7 @@ #![feature(trait_alias, marker_trait_attr)] #[marker] -//~^ ERROR attribute should be applied to a trait +//~^ ERROR attribute cannot be used on trait Foo = Send; fn main() {} diff --git a/tests/ui/traits/alias/not-a-marker.stderr b/tests/ui/traits/alias/not-a-marker.stderr index 2f3f6fea30f..8b0eba65b95 100644 --- a/tests/ui/traits/alias/not-a-marker.stderr +++ b/tests/ui/traits/alias/not-a-marker.stderr @@ -1,11 +1,10 @@ -error: attribute should be applied to a trait +error: `#[marker]` attribute cannot be used on trait aliases --> $DIR/not-a-marker.rs:3:1 | LL | #[marker] | ^^^^^^^^^ -LL | -LL | trait Foo = Send; - | ----------------- not a trait + | + = help: `#[marker]` can only be applied to traits error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/attr-misuse.rs b/tests/ui/traits/const-traits/attr-misuse.rs index 01ac74feff7..70dfcbf47d2 100644 --- a/tests/ui/traits/const-traits/attr-misuse.rs +++ b/tests/ui/traits/const-traits/attr-misuse.rs @@ -2,9 +2,9 @@ #[const_trait] trait A { - #[const_trait] //~ ERROR attribute should be applied + #[const_trait] //~ ERROR attribute cannot be used on fn foo(self); } -#[const_trait] //~ ERROR attribute should be applied +#[const_trait] //~ ERROR attribute cannot be used on fn main() {} diff --git a/tests/ui/traits/const-traits/attr-misuse.stderr b/tests/ui/traits/const-traits/attr-misuse.stderr index 998958cedf7..2f86efac4c9 100644 --- a/tests/ui/traits/const-traits/attr-misuse.stderr +++ b/tests/ui/traits/const-traits/attr-misuse.stderr @@ -1,18 +1,18 @@ -error: attribute should be applied to a trait +error: `#[const_trait]` attribute cannot be used on required trait methods + --> $DIR/attr-misuse.rs:5:5 + | +LL | #[const_trait] + | ^^^^^^^^^^^^^^ + | + = help: `#[const_trait]` can only be applied to traits + +error: `#[const_trait]` attribute cannot be used on functions --> $DIR/attr-misuse.rs:9:1 | LL | #[const_trait] | ^^^^^^^^^^^^^^ -LL | fn main() {} - | ------------ not a trait - -error: attribute should be applied to a trait - --> $DIR/attr-misuse.rs:5:5 | -LL | #[const_trait] - | ^^^^^^^^^^^^^^ -LL | fn foo(self); - | ------------- not a trait + = help: `#[const_trait]` can only be applied to traits error: aborting due to 2 previous errors diff --git a/tests/ui/typeck/suggestions/suggest-add-wrapper-issue-145294.rs b/tests/ui/typeck/suggestions/suggest-add-wrapper-issue-145294.rs new file mode 100644 index 00000000000..cfe167cf88d --- /dev/null +++ b/tests/ui/typeck/suggestions/suggest-add-wrapper-issue-145294.rs @@ -0,0 +1,26 @@ +// Suppress the suggestion that adding a wrapper. +// When expected_ty and expr_ty are the same ADT, +// we prefer to compare their internal generic params, +// so when the current variant corresponds to an unresolved infer, +// the suggestion is rejected. +// e.g. `Ok(Some("hi"))` is type of `Result<Option<&str>, _>`, +// where `E` is still an unresolved inference variable. + +fn foo() -> Result<Option<String>, ()> { + todo!() +} + +#[derive(PartialEq, Debug)] +enum Bar<T, E> { + A(T), + B(E), +} + +fn bar() -> Bar<String, ()> { + todo!() +} + +fn main() { + assert_eq!(Ok(Some("hi")), foo()); //~ ERROR mismatched types [E0308] + assert_eq!(Bar::A("hi"), bar()); //~ ERROR mismatched types [E0308] +} diff --git a/tests/ui/typeck/suggestions/suggest-add-wrapper-issue-145294.stderr b/tests/ui/typeck/suggestions/suggest-add-wrapper-issue-145294.stderr new file mode 100644 index 00000000000..5e4ad132210 --- /dev/null +++ b/tests/ui/typeck/suggestions/suggest-add-wrapper-issue-145294.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/suggest-add-wrapper-issue-145294.rs:24:32 + | +LL | assert_eq!(Ok(Some("hi")), foo()); + | ^^^^^ expected `Result<Option<&str>, _>`, found `Result<Option<String>, ()>` + | + = note: expected enum `Result<Option<&str>, _>` + found enum `Result<Option<String>, ()>` + +error[E0308]: mismatched types + --> $DIR/suggest-add-wrapper-issue-145294.rs:25:30 + | +LL | assert_eq!(Bar::A("hi"), bar()); + | ^^^^^ expected `Bar<&str, _>`, found `Bar<String, ()>` + | + = note: expected enum `Bar<&str, _>` + found enum `Bar<String, ()>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/unboxed-closures/unboxed-closure-illegal-move.stderr b/tests/ui/unboxed-closures/unboxed-closure-illegal-move.stderr index 9d87402a15b..266da54941d 100644 --- a/tests/ui/unboxed-closures/unboxed-closure-illegal-move.stderr +++ b/tests/ui/unboxed-closures/unboxed-closure-illegal-move.stderr @@ -10,7 +10,7 @@ LL | let f = to_fn(|| drop(x)); | | | captured by this `Fn` closure | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/unboxed-closure-illegal-move.rs:7:33 | LL | fn to_fn<A:std::marker::Tuple,F:Fn<A>>(f: F) -> F { f } @@ -32,7 +32,7 @@ LL | let f = to_fn_mut(|| drop(x)); | | | captured by this `FnMut` closure | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/unboxed-closure-illegal-move.rs:8:37 | LL | fn to_fn_mut<A:std::marker::Tuple,F:FnMut<A>>(f: F) -> F { f } @@ -54,7 +54,7 @@ LL | let f = to_fn(move || drop(x)); | | | captured by this `Fn` closure | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/unboxed-closure-illegal-move.rs:7:33 | LL | fn to_fn<A:std::marker::Tuple,F:Fn<A>>(f: F) -> F { f } @@ -72,7 +72,7 @@ LL | let f = to_fn_mut(move || drop(x)); | | | captured by this `FnMut` closure | -help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but an `FnOnce` consume them only once +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once --> $DIR/unboxed-closure-illegal-move.rs:8:37 | LL | fn to_fn_mut<A:std::marker::Tuple,F:FnMut<A>>(f: F) -> F { f } diff --git a/tests/ui/unstable-feature-bound/unstable_inherent_method.rs b/tests/ui/unstable-feature-bound/unstable_inherent_method.rs index 0d6e4ebb408..cdd4178fc87 100644 --- a/tests/ui/unstable-feature-bound/unstable_inherent_method.rs +++ b/tests/ui/unstable-feature-bound/unstable_inherent_method.rs @@ -9,14 +9,14 @@ pub trait Trait { #[unstable(feature = "feat", issue = "none" )] #[unstable_feature_bound(foo)] - //~^ ERROR: attribute should be applied to `impl`, trait or free function + //~^ ERROR: attribute cannot be used on fn foo(); } #[stable(feature = "a", since = "1.1.1" )] impl Trait for u8 { #[unstable_feature_bound(foo)] - //~^ ERROR: attribute should be applied to `impl`, trait or free function + //~^ ERROR: attribute cannot be used on fn foo() {} } diff --git a/tests/ui/unstable-feature-bound/unstable_inherent_method.stderr b/tests/ui/unstable-feature-bound/unstable_inherent_method.stderr index 90cbb32df7c..2a1ae936cfe 100644 --- a/tests/ui/unstable-feature-bound/unstable_inherent_method.stderr +++ b/tests/ui/unstable-feature-bound/unstable_inherent_method.stderr @@ -1,20 +1,18 @@ -error: attribute should be applied to `impl`, trait or free function +error: `#[unstable_feature_bound]` attribute cannot be used on required trait methods --> $DIR/unstable_inherent_method.rs:11:5 | LL | #[unstable_feature_bound(foo)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | fn foo(); - | --------- not an `impl`, trait or free function + | + = help: `#[unstable_feature_bound]` can be applied to functions, trait impl blocks, traits -error: attribute should be applied to `impl`, trait or free function +error: `#[unstable_feature_bound]` attribute cannot be used on trait methods in impl blocks --> $DIR/unstable_inherent_method.rs:18:5 | LL | #[unstable_feature_bound(foo)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | fn foo() {} - | ----------- not an `impl`, trait or free function + | + = help: `#[unstable_feature_bound]` can be applied to functions, trait impl blocks, traits error: aborting due to 2 previous errors diff --git a/tests/ui/where-clauses/unsupported_attribute.rs b/tests/ui/where-clauses/unsupported_attribute.rs index 33128b383b9..75213e17661 100644 --- a/tests/ui/where-clauses/unsupported_attribute.rs +++ b/tests/ui/where-clauses/unsupported_attribute.rs @@ -13,18 +13,18 @@ fn foo<'a, T>() where #[doc = "doc"] T: Trait, //~ ERROR most attributes are not supported in `where` clauses #[doc = "doc"] 'a: 'static, //~ ERROR most attributes are not supported in `where` clauses - #[ignore] T: Trait, //~ ERROR most attributes are not supported in `where` clauses - #[ignore] 'a: 'static, //~ ERROR most attributes are not supported in `where` clauses - #[should_panic] T: Trait, //~ ERROR most attributes are not supported in `where` clauses - #[should_panic] 'a: 'static, //~ ERROR most attributes are not supported in `where` clauses - #[macro_use] T: Trait, //~ ERROR most attributes are not supported in `where` clauses - #[macro_use] 'a: 'static, //~ ERROR most attributes are not supported in `where` clauses + #[ignore] T: Trait, //~ ERROR attribute cannot be used on + #[ignore] 'a: 'static, //~ ERROR attribute cannot be used on + #[should_panic] T: Trait, //~ ERROR attribute cannot be used on + #[should_panic] 'a: 'static, //~ ERROR attribute cannot be used on + #[macro_use] T: Trait, //~ ERROR attribute cannot be used on + #[macro_use] 'a: 'static, //~ ERROR attribute cannot be used on #[allow(unused)] T: Trait, //~ ERROR most attributes are not supported in `where` clauses #[allow(unused)] 'a: 'static, //~ ERROR most attributes are not supported in `where` clauses - #[deprecated] T: Trait, //~ ERROR most attributes are not supported in `where` clauses - #[deprecated] 'a: 'static, //~ ERROR most attributes are not supported in `where` clauses - #[automatically_derived] T: Trait, //~ ERROR most attributes are not supported in `where` clauses - #[automatically_derived] 'a: 'static, //~ ERROR most attributes are not supported in `where` clauses + #[deprecated] T: Trait, //~ ERROR attribute cannot be used on + #[deprecated] 'a: 'static, //~ ERROR attribute cannot be used on + #[automatically_derived] T: Trait, //~ ERROR attribute cannot be used on + #[automatically_derived] 'a: 'static, //~ ERROR attribute cannot be used on #[derive(Clone)] T: Trait, //~^ ERROR most attributes are not supported in `where` clauses //~| ERROR expected non-macro attribute, found attribute macro `derive` diff --git a/tests/ui/where-clauses/unsupported_attribute.stderr b/tests/ui/where-clauses/unsupported_attribute.stderr index ecb28039f88..411c895ed87 100644 --- a/tests/ui/where-clauses/unsupported_attribute.stderr +++ b/tests/ui/where-clauses/unsupported_attribute.stderr @@ -10,115 +10,115 @@ error: expected non-macro attribute, found attribute macro `derive` LL | #[derive(Clone)] 'a: 'static, | ^^^^^^ not a non-macro attribute -error: most attributes are not supported in `where` clauses - --> $DIR/unsupported_attribute.rs:14:5 - | -LL | #[doc = "doc"] T: Trait, - | ^^^^^^^^^^^^^^ - | - = help: only `#[cfg]` and `#[cfg_attr]` are supported - -error: most attributes are not supported in `where` clauses - --> $DIR/unsupported_attribute.rs:15:5 - | -LL | #[doc = "doc"] 'a: 'static, - | ^^^^^^^^^^^^^^ - | - = help: only `#[cfg]` and `#[cfg_attr]` are supported - -error: most attributes are not supported in `where` clauses +error: `#[ignore]` attribute cannot be used on where predicates --> $DIR/unsupported_attribute.rs:16:5 | LL | #[ignore] T: Trait, | ^^^^^^^^^ | - = help: only `#[cfg]` and `#[cfg_attr]` are supported + = help: `#[ignore]` can only be applied to functions -error: most attributes are not supported in `where` clauses +error: `#[ignore]` attribute cannot be used on where predicates --> $DIR/unsupported_attribute.rs:17:5 | LL | #[ignore] 'a: 'static, | ^^^^^^^^^ | - = help: only `#[cfg]` and `#[cfg_attr]` are supported + = help: `#[ignore]` can only be applied to functions -error: most attributes are not supported in `where` clauses +error: `#[should_panic]` attribute cannot be used on where predicates --> $DIR/unsupported_attribute.rs:18:5 | LL | #[should_panic] T: Trait, | ^^^^^^^^^^^^^^^ | - = help: only `#[cfg]` and `#[cfg_attr]` are supported + = help: `#[should_panic]` can only be applied to functions -error: most attributes are not supported in `where` clauses +error: `#[should_panic]` attribute cannot be used on where predicates --> $DIR/unsupported_attribute.rs:19:5 | LL | #[should_panic] 'a: 'static, | ^^^^^^^^^^^^^^^ | - = help: only `#[cfg]` and `#[cfg_attr]` are supported + = help: `#[should_panic]` can only be applied to functions -error: most attributes are not supported in `where` clauses +error: `#[macro_use]` attribute cannot be used on where predicates --> $DIR/unsupported_attribute.rs:20:5 | LL | #[macro_use] T: Trait, | ^^^^^^^^^^^^ | - = help: only `#[cfg]` and `#[cfg_attr]` are supported + = help: `#[macro_use]` can be applied to modules, extern crates, crates -error: most attributes are not supported in `where` clauses +error: `#[macro_use]` attribute cannot be used on where predicates --> $DIR/unsupported_attribute.rs:21:5 | LL | #[macro_use] 'a: 'static, | ^^^^^^^^^^^^ | - = help: only `#[cfg]` and `#[cfg_attr]` are supported + = help: `#[macro_use]` can be applied to modules, extern crates, crates -error: most attributes are not supported in `where` clauses - --> $DIR/unsupported_attribute.rs:22:5 +error: `#[deprecated]` attribute cannot be used on where predicates + --> $DIR/unsupported_attribute.rs:24:5 | -LL | #[allow(unused)] T: Trait, - | ^^^^^^^^^^^^^^^^ +LL | #[deprecated] T: Trait, + | ^^^^^^^^^^^^^ | - = help: only `#[cfg]` and `#[cfg_attr]` are supported + = help: `#[deprecated]` can be applied to functions, data types, modules, unions, constants, statics, macro defs, type aliases, use statements, struct fields, traits, associated types, associated consts, enum variants, inherent impl blocks, crates -error: most attributes are not supported in `where` clauses - --> $DIR/unsupported_attribute.rs:23:5 +error: `#[deprecated]` attribute cannot be used on where predicates + --> $DIR/unsupported_attribute.rs:25:5 | -LL | #[allow(unused)] 'a: 'static, - | ^^^^^^^^^^^^^^^^ +LL | #[deprecated] 'a: 'static, + | ^^^^^^^^^^^^^ | - = help: only `#[cfg]` and `#[cfg_attr]` are supported + = help: `#[deprecated]` can be applied to functions, data types, modules, unions, constants, statics, macro defs, type aliases, use statements, struct fields, traits, associated types, associated consts, enum variants, inherent impl blocks, crates + +error: `#[automatically_derived]` attribute cannot be used on where predicates + --> $DIR/unsupported_attribute.rs:26:5 + | +LL | #[automatically_derived] T: Trait, + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[automatically_derived]` can only be applied to trait impl blocks + +error: `#[automatically_derived]` attribute cannot be used on where predicates + --> $DIR/unsupported_attribute.rs:27:5 + | +LL | #[automatically_derived] 'a: 'static, + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[automatically_derived]` can only be applied to trait impl blocks error: most attributes are not supported in `where` clauses - --> $DIR/unsupported_attribute.rs:24:5 + --> $DIR/unsupported_attribute.rs:14:5 | -LL | #[deprecated] T: Trait, - | ^^^^^^^^^^^^^ +LL | #[doc = "doc"] T: Trait, + | ^^^^^^^^^^^^^^ | = help: only `#[cfg]` and `#[cfg_attr]` are supported error: most attributes are not supported in `where` clauses - --> $DIR/unsupported_attribute.rs:25:5 + --> $DIR/unsupported_attribute.rs:15:5 | -LL | #[deprecated] 'a: 'static, - | ^^^^^^^^^^^^^ +LL | #[doc = "doc"] 'a: 'static, + | ^^^^^^^^^^^^^^ | = help: only `#[cfg]` and `#[cfg_attr]` are supported error: most attributes are not supported in `where` clauses - --> $DIR/unsupported_attribute.rs:26:5 + --> $DIR/unsupported_attribute.rs:22:5 | -LL | #[automatically_derived] T: Trait, - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[allow(unused)] T: Trait, + | ^^^^^^^^^^^^^^^^ | = help: only `#[cfg]` and `#[cfg_attr]` are supported error: most attributes are not supported in `where` clauses - --> $DIR/unsupported_attribute.rs:27:5 + --> $DIR/unsupported_attribute.rs:23:5 | -LL | #[automatically_derived] 'a: 'static, - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[allow(unused)] 'a: 'static, + | ^^^^^^^^^^^^^^^^ | = help: only `#[cfg]` and `#[cfg_attr]` are supported diff --git a/typos.toml b/typos.toml index 4035f206a46..317aafc8615 100644 --- a/typos.toml +++ b/typos.toml @@ -52,7 +52,6 @@ ERROR_DS_NOT_AUTHORITIVE_FOR_DST_NC = "ERROR_DS_NOT_AUTHORITIVE_FOR_DST_NC" ERROR_MCA_OCCURED = "ERROR_MCA_OCCURED" ERRNO_ACCES = "ERRNO_ACCES" tolen = "tolen" -numer = "numer" [default] extend-ignore-words-re = [ |
