Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -966,11 +966,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
}))
}

/// Forwards a possible `#[track_caller]` annotation from `outer_hir_id` to
/// `inner_hir_id` in case the `async_fn_track_caller` feature is enabled.
/// Forwards a possible `#[track_caller]` annotation from `outer_hir_id` to `inner_hir_id`.
pub(super) fn maybe_forward_track_caller(&mut self, outer_hir_id: HirId, inner_hir_id: HirId) {
if self.tcx.features().async_fn_track_caller()
&& let Some(attrs) = self.curr_owner.attrs.get(&outer_hir_id.local_id)
if let Some(attrs) = self.curr_owner.attrs.get(&outer_hir_id.local_id)
&& let Some(t) = attrs.iter().find(|a| {
matches!(
a,
Expand Down
69 changes: 39 additions & 30 deletions compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use rustc_attr_ir::target::AstTarget;
use rustc_attr_ir::{
CoverageAttrKind, InstrumentFnAttr, OptimizeAttr, RtsanSetting, UsedBy, find_attr,
};
Expand All @@ -15,7 +16,7 @@ use crate::diagnostics::{
ObjcSelectorExpectedStringLiteral, SanitizeInvalidStatic, TargetFeatureOnLangItem,
TrackCallerOnLangItem,
};
use crate::target_checking::Policy::AllowSilent;
use crate::target_checking::AllowedResult;

pub(crate) struct OptimizeParser;

Expand Down Expand Up @@ -53,8 +54,8 @@ pub(crate) struct ColdParser;

impl NoArgsAttributeParser for ColdParser {
const PATH: &[Symbol] = &[sym::cold];
const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn;
const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[

const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
Allow(Target::Fn),
Allow(Target::Method(MethodKind::Trait { body: true })),
Allow(Target::Method(MethodKind::TraitImpl)),
Expand Down Expand Up @@ -113,7 +114,7 @@ pub(crate) struct ExportNameParser;

impl SingleAttributeParser for ExportNameParser {
const PATH: &[rustc_span::Symbol] = &[sym::export_name];
const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError;

const SAFETY: AttributeSafety = AttributeSafety::Unsafe {
note: "the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them",
unsafe_since: Some(Edition2024),
Expand Down Expand Up @@ -221,7 +222,7 @@ impl AttributeParser for NakedParser {

if let Some(earlier) = this.span {
let span = cx.attr_span;
cx.warn_unused_duplicate(earlier, span);
cx.unused_duplicate(earlier, span);
} else {
this.span = Some(cx.attr_span);
}
Expand All @@ -235,10 +236,18 @@ impl AttributeParser for NakedParser {
Allow(Target::Method(MethodKind::Inherent)),
Allow(Target::Method(MethodKind::Trait { body: true })),
Allow(Target::Method(MethodKind::TraitImpl)),
Warn(Target::MacroCall),
]);

fn finalize(self, cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {
let span = self.span?;

if !matches!(NakedParser::ALLOWED_TARGETS.is_allowed(cx.target), AllowedResult::Allowed) {
cx.dcx().span_delayed_bug(
span,
"skipping `naked` attribute incompatibility check for disallowed target",
);
return None;
}
// FIXME(jdonszelmann): upgrade this list to *parsed* attributes
// once all of these have parsed forms. That'd make the check much nicer...
//
Expand Down Expand Up @@ -282,8 +291,6 @@ impl AttributeParser for NakedParser {
sym::doc,
];

let span = self.span?;

let Some(tools) = cx.attr_tools else {
unreachable!("tools required while parsing attributes");
};
Expand Down Expand Up @@ -368,7 +375,7 @@ impl AttributeParser for NakedParser {
pub(crate) struct TrackCallerParser;
impl NoArgsAttributeParser for TrackCallerParser {
const PATH: &[Symbol] = &[sym::track_caller];
const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn;

const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
Allow(Target::Fn),
Allow(Target::Method(MethodKind::Inherent)),
Expand All @@ -377,17 +384,13 @@ impl NoArgsAttributeParser for TrackCallerParser {
Allow(Target::Method(MethodKind::Trait { body: false })), // `#[track_caller]` is inherited from trait methods
Allow(Target::ForeignFn),
Allow(Target::Closure),
Warn(Target::MacroDef),
Warn(Target::Arm),
Warn(Target::Field),
Warn(Target::MacroCall),
]);
const STABILITY: AttributeStability = AttributeStability::Stable;
const CREATE: fn(Span) -> AttributeKind = AttributeKind::TrackCaller;

fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) {
match cx.target {
Target::Fn => {
match cx.ast_target {
AstTarget::Fn(f) => {
// `#[track_caller]` is not valid on weak lang items because they are called via
// `extern` declarations and `#[track_caller]` would alter their ABI.
if let Some(item) = find_attr!(cx.parsed_attrs, Lang(item) => item)
Expand All @@ -399,13 +402,24 @@ impl NoArgsAttributeParser for TrackCallerParser {
sig_span: cx.target_span,
});
}

if f.sig.header.coroutine_marker.is_some() && !cx.features().async_fn_track_caller()
{
feature_err(
cx.sess(),
sym::async_fn_track_caller,
attr_span,
"`#[track_caller]` on async functions is unstable",
)
.emit();
}
}
Target::Closure if !cx.features().closure_track_caller() => {
AstTarget::Closure(_) if !cx.features().closure_track_caller() => {
feature_err(
cx.sess(),
sym::closure_track_caller,
attr_span,
"`#[track_caller]` on closures is currently unstable",
"`#[track_caller]` on closures is unstable",
)
.emit();
}
Expand All @@ -417,7 +431,7 @@ impl NoArgsAttributeParser for TrackCallerParser {
pub(crate) struct NoMangleParser;
impl NoArgsAttributeParser for NoMangleParser {
const PATH: &[Symbol] = &[sym::no_mangle];
const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn;

const SAFETY: AttributeSafety = AttributeSafety::Unsafe {
note: "the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them",
unsafe_since: Some(Edition2024),
Expand All @@ -427,7 +441,7 @@ impl NoArgsAttributeParser for NoMangleParser {
Allow(Target::Static),
Allow(Target::Method(MethodKind::Inherent)),
Allow(Target::Method(MethodKind::TraitImpl)),
AllowSilent(Target::Const), // Handled in the `InvalidNoMangleItems` pass
Error(Target::Const),
Error(Target::Closure),
Error(Target::Param),
]);
Expand Down Expand Up @@ -505,29 +519,28 @@ impl AttributeParser for UsedParser {
UsedBy::Compiler => &mut group.first_compiler,
UsedBy::Linker => {
if let Some(prev) = group.first_default {
cx.warn_unused_duplicate(prev, attr_span);
cx.unused_duplicate(prev, attr_span);
return;
}
&mut group.first_linker
}
UsedBy::Default => {
if let Some(prev) = group.first_linker {
cx.warn_unused_duplicate(prev, attr_span);
cx.unused_duplicate(prev, attr_span);
return;
}
&mut group.first_default
}
};

if let Some(prev) = *target {
cx.warn_unused_duplicate(prev, attr_span);
cx.unused_duplicate(prev, attr_span);
} else {
*target = Some(attr_span);
}
},
)];
const ALLOWED_TARGETS: AllowedTargets<'_> =
AllowedTargets::AllowList(&[Allow(Target::Static), Warn(Target::MacroCall)]);
const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Static)]);

fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {
// If a specific form of `used` is specified, it takes precedence over generic `#[used]`.
Expand All @@ -551,7 +564,7 @@ fn parse_tf_attribute(
};
if list.is_empty() {
let attr_span = cx.attr_span;
cx.adcx().warn_empty_attribute(attr_span);
cx.adcx().empty_attribute(attr_span);
return features;
}
for item in list.mixed() {
Expand Down Expand Up @@ -593,11 +606,7 @@ impl CombineAttributeParser for TargetFeatureParser {
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),
Warn(Target::MacroCall),
Warn(Target::MacroCall), // #158816: 181 regressions from old versions of `v_escape`
]);
const STABILITY: AttributeStability = AttributeStability::Stable;

Expand Down
59 changes: 23 additions & 36 deletions compiler/rustc_attr_parsing/src/attributes/crate_level.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use rustc_attr_ir::WindowsSubsystemKind;
use rustc_data_structures::fx::FxIndexSet;
use rustc_feature::AttributeStability;
use rustc_lint_defs::builtin::{DUPLICATE_TOOLS, UNKNOWN_CRATE_TYPES};
use rustc_lint_defs::builtin::DUPLICATE_TOOLS;
use rustc_span::Symbol;
use rustc_span::edit_distance::find_best_match_for_name_with_substrings;
use rustc_structures::CrateType;
Expand All @@ -15,10 +15,9 @@ pub(crate) struct CrateNameParser;

impl SingleAttributeParser for CrateNameParser {
const PATH: &[Symbol] = &[sym::crate_name];
const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError;

const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
const ALLOWED_TARGETS: AllowedTargets<'_> =
AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate), Error(Target::Param)]);
const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
const STABILITY: AttributeStability = AttributeStability::Stable;

fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
Expand All @@ -36,8 +35,7 @@ impl CombineAttributeParser for CrateTypeParser {
const PATH: &[Symbol] = &[sym::crate_type];
type Item = CrateType;
const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::CrateType(items);
const ALLOWED_TARGETS: AllowedTargets<'_> =
AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate), Error(Target::Param)]);
const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
const TEMPLATE: AttributeTemplate =
template!(NameValueStr: "crate type", "https://doc.rust-lang.org/reference/linkage.html");
const STABILITY: AttributeStability = AttributeStability::Stable;
Expand All @@ -51,21 +49,17 @@ impl CombineAttributeParser for CrateTypeParser {
let crate_type = cx.expect_string_literal(n)?;

let Ok(crate_type) = crate_type.try_into() else {
// We don't error on invalid `#![crate_type]` when not applied to a crate
// We error on invalid `#![crate_type]` when not applied to a crate
if cx.shared.target == Target::Crate {
let candidate = find_best_match_for_name_with_substrings(
&CrateType::all_stable().iter().map(|(name, _)| *name).collect::<Vec<_>>(),
crate_type,
Some(5),
);
let span = n.value_span;
cx.emit_lint(
UNKNOWN_CRATE_TYPES,
UnknownCrateTypes {
sugg: candidate.map(|s| UnknownCrateTypesSuggestion { span, snippet: s }),
},
span,
);
cx.emit_err(UnknownCrateTypes {
sugg: candidate.map(|s| UnknownCrateTypesSuggestion { span, snippet: s }),
});
}
return None;
};
Expand All @@ -78,10 +72,9 @@ pub(crate) struct RecursionLimitParser;

impl SingleAttributeParser for RecursionLimitParser {
const PATH: &[Symbol] = &[sym::recursion_limit];
const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError;

const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N", "https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute");
const ALLOWED_TARGETS: AllowedTargets<'_> =
AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate), Error(Target::Param)]);
const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
const STABILITY: AttributeStability = AttributeStability::Stable;

fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
Expand Down Expand Up @@ -110,10 +103,9 @@ pub(crate) struct TypeLengthLimitParser;

impl SingleAttributeParser for TypeLengthLimitParser {
const PATH: &[Symbol] = &[sym::type_length_limit];
const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError;

const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
const ALLOWED_TARGETS: AllowedTargets<'_> =
AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate), Error(Target::Param)]);
const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
const STABILITY: AttributeStability = AttributeStability::Stable;

fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
Expand Down Expand Up @@ -154,9 +146,8 @@ pub(crate) struct NoStdParser;

impl NoArgsAttributeParser for NoStdParser {
const PATH: &[Symbol] = &[sym::no_std];
const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn;
const ALLOWED_TARGETS: AllowedTargets<'_> =
AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate), Error(Target::Param)]);

const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
const STABILITY: AttributeStability = AttributeStability::Stable;
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoStd;
}
Expand All @@ -165,9 +156,8 @@ pub(crate) struct NoMainParser;

impl NoArgsAttributeParser for NoMainParser {
const PATH: &[Symbol] = &[sym::no_main];
const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn;
const ALLOWED_TARGETS: AllowedTargets<'_> =
AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate), Error(Target::Param)]);

const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
const STABILITY: AttributeStability = AttributeStability::Stable;
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoMain;
}
Expand All @@ -185,9 +175,8 @@ pub(crate) struct WindowsSubsystemParser;

impl SingleAttributeParser for WindowsSubsystemParser {
const PATH: &[Symbol] = &[sym::windows_subsystem];
const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError;
const ALLOWED_TARGETS: AllowedTargets<'_> =
AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate), Error(Target::Param)]);

const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
const TEMPLATE: AttributeTemplate = template!(NameValueStr: ["windows", "console"], "https://doc.rust-lang.org/reference/runtime.html#the-windows_subsystem-attribute");
const STABILITY: AttributeStability = AttributeStability::Stable;

Expand Down Expand Up @@ -241,9 +230,8 @@ pub(crate) struct NoBuiltinsParser;

impl NoArgsAttributeParser for NoBuiltinsParser {
const PATH: &[Symbol] = &[sym::no_builtins];
const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn;
const ALLOWED_TARGETS: AllowedTargets<'_> =
AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate), Error(Target::Param)]);

const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
const STABILITY: AttributeStability = AttributeStability::Stable;
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoBuiltins;
}
Expand Down Expand Up @@ -281,8 +269,7 @@ impl CombineAttributeParser for FeatureParser {
const PATH: &[Symbol] = &[sym::feature];
type Item = Ident;
const CONVERT: ConvertFn<Self::Item> = AttributeKind::Feature;
const ALLOWED_TARGETS: AllowedTargets<'_> =
AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate), Error(Target::Param)]);
const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
const TEMPLATE: AttributeTemplate = template!(List: &["feature1, feature2, ..."]);
const STABILITY: AttributeStability = AttributeStability::Stable;

Expand All @@ -296,7 +283,7 @@ impl CombineAttributeParser for FeatureParser {

if list.is_empty() {
let attr_span = cx.attr_span;
cx.adcx().warn_empty_attribute(attr_span);
cx.adcx().empty_attribute(attr_span);
}

let mut res = Vec::new();
Expand Down Expand Up @@ -338,7 +325,7 @@ fn parse_register_tool(

if list.is_empty() {
let attr_span = cx.attr_span;
cx.adcx().warn_empty_attribute(attr_span);
cx.adcx().empty_attribute(attr_span);
}

for elem in list.mixed() {
Expand Down
Loading
Loading