Skip to content

Commit 481db40

Browse files
committed
Auto merge of #95562 - lcnr:attr-no-encode, r=davidtwco
don't encode only locally used attrs Part of rust-lang/compiler-team#505. We now filter builtin attributes before encoding them in the crate metadata in case they should only be used in the local crate. To prevent accidental misuse `get_attrs` now requires the caller to state which attribute they are interested in. For places where that isn't trivially possible, I've added a method `fn get_attrs_unchecked` which I intend to remove in a followup PR. After this pull request landed, we can then slowly move all attributes to only be used in the local crate while being certain that we don't accidentally try to access them from extern crates. cc #94963 (comment)
2 parents 18bd2dd + ebf9583 commit 481db40

File tree

55 files changed

+453
-465
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+453
-465
lines changed

compiler/rustc_attr/src/builtin.rs

+141-138
Large diffs are not rendered by default.

compiler/rustc_codegen_llvm/src/attributes.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use rustc_hir::def_id::DefId;
66
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
77
use rustc_middle::ty::{self, TyCtxt};
88
use rustc_session::config::OptLevel;
9+
use rustc_span::symbol::sym;
910
use rustc_target::spec::abi::Abi;
1011
use rustc_target::spec::{FramePointer, SanitizerSet, StackProbeType, StackProtector};
1112
use smallvec::SmallVec;
@@ -329,9 +330,7 @@ pub fn from_fn_attrs<'ll, 'tcx>(
329330
) {
330331
let span = cx
331332
.tcx
332-
.get_attrs(instance.def_id())
333-
.iter()
334-
.find(|a| a.has_name(rustc_span::sym::target_feature))
333+
.get_attr(instance.def_id(), sym::target_feature)
335334
.map_or_else(|| cx.tcx.def_span(instance.def_id()), |a| a.span);
336335
let msg = format!(
337336
"the target features {} must all be either enabled or disabled together",

compiler/rustc_const_eval/src/transform/check_consts/check.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -312,11 +312,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
312312

313313
Status::Unstable(gate) if self.tcx.features().enabled(gate) => {
314314
let unstable_in_stable = self.ccx.is_const_stable_const_fn()
315-
&& !super::rustc_allow_const_fn_unstable(
316-
self.tcx,
317-
self.def_id().to_def_id(),
318-
gate,
319-
);
315+
&& !super::rustc_allow_const_fn_unstable(self.tcx, self.def_id(), gate);
320316
if unstable_in_stable {
321317
emit_unstable_in_stable_error(self.ccx, span, gate);
322318
}
@@ -713,7 +709,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
713709
match &terminator.kind {
714710
TerminatorKind::Call { func, args, fn_span, from_hir_call, .. } => {
715711
let ConstCx { tcx, body, param_env, .. } = *self.ccx;
716-
let caller = self.def_id().to_def_id();
712+
let caller = self.def_id();
717713

718714
let fn_ty = func.ty(body, tcx);
719715

@@ -797,7 +793,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
797793
// trait.
798794
let callee_trait = tcx.trait_of_item(callee);
799795
if callee_trait.is_some()
800-
&& tcx.has_attr(caller, sym::default_method_body_is_const)
796+
&& tcx.has_attr(caller.to_def_id(), sym::default_method_body_is_const)
801797
&& callee_trait == tcx.trait_of_item(caller)
802798
// Can only call methods when it's `<Self as TheTrait>::f`.
803799
&& tcx.types.self_param == substs.type_at(0)

compiler/rustc_const_eval/src/transform/check_consts/mod.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,12 @@ impl<'mir, 'tcx> ConstCx<'mir, 'tcx> {
6666
}
6767
}
6868

69-
pub fn rustc_allow_const_fn_unstable(tcx: TyCtxt<'_>, def_id: DefId, feature_gate: Symbol) -> bool {
70-
let attrs = tcx.get_attrs(def_id);
69+
pub fn rustc_allow_const_fn_unstable(
70+
tcx: TyCtxt<'_>,
71+
def_id: LocalDefId,
72+
feature_gate: Symbol,
73+
) -> bool {
74+
let attrs = tcx.hir().attrs(tcx.hir().local_def_id_to_hir_id(def_id));
7175
attr::rustc_allow_const_fn_unstable(&tcx.sess, attrs).any(|name| name == feature_gate)
7276
}
7377

compiler/rustc_const_eval/src/transform/check_consts/ops.rs

+4-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Concrete error types for all operations which may be invalid in a certain const context.
22
3+
use hir::def_id::LocalDefId;
34
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
45
use rustc_hir as hir;
56
use rustc_hir::def_id::DefId;
@@ -95,7 +96,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallIndirect {
9596
/// A function call where the callee is not marked as `const`.
9697
#[derive(Debug, Clone, Copy)]
9798
pub struct FnCallNonConst<'tcx> {
98-
pub caller: DefId,
99+
pub caller: LocalDefId,
99100
pub callee: DefId,
100101
pub substs: SubstsRef<'tcx>,
101102
pub span: Span,
@@ -117,13 +118,8 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
117118
match self_ty.kind() {
118119
Param(param_ty) => {
119120
debug!(?param_ty);
120-
if let Some(generics) = caller
121-
.as_local()
122-
.map(|id| tcx.hir().local_def_id_to_hir_id(id))
123-
.map(|id| tcx.hir().get(id))
124-
.as_ref()
125-
.and_then(|node| node.generics())
126-
{
121+
let caller_hir_id = tcx.hir().local_def_id_to_hir_id(caller);
122+
if let Some(generics) = tcx.hir().get(caller_hir_id).generics() {
127123
let constraint = with_no_trimmed_paths!(format!(
128124
"~const {}",
129125
trait_ref.print_only_trait_path()

compiler/rustc_feature/src/builtin_attrs.rs

+44-18
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,16 @@ pub enum AttributeDuplicates {
147147
FutureWarnPreceding,
148148
}
149149

150+
/// A conveniece macro to deal with `$($expr)?`.
151+
macro_rules! or_default {
152+
($default:expr,) => {
153+
$default
154+
};
155+
($default:expr, $next:expr) => {
156+
$next
157+
};
158+
}
159+
150160
/// A convenience macro for constructing attribute templates.
151161
/// E.g., `template!(Word, List: "description")` means that the attribute
152162
/// supports forms `#[attr]` and `#[attr(description)]`.
@@ -168,9 +178,10 @@ macro_rules! template {
168178
}
169179

170180
macro_rules! ungated {
171-
($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr $(,)?) => {
181+
($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr $(, @only_local: $only_local:expr)? $(,)?) => {
172182
BuiltinAttribute {
173183
name: sym::$attr,
184+
only_local: or_default!(false, $($only_local)?),
174185
type_: $typ,
175186
template: $tpl,
176187
gate: Ungated,
@@ -180,18 +191,20 @@ macro_rules! ungated {
180191
}
181192

182193
macro_rules! gated {
183-
($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $gate:ident, $msg:expr $(,)?) => {
194+
($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr $(, @only_local: $only_local:expr)?, $gate:ident, $msg:expr $(,)?) => {
184195
BuiltinAttribute {
185196
name: sym::$attr,
197+
only_local: or_default!(false, $($only_local)?),
186198
type_: $typ,
187199
template: $tpl,
188200
duplicates: $duplicates,
189201
gate: Gated(Stability::Unstable, sym::$gate, $msg, cfg_fn!($gate)),
190202
}
191203
};
192-
($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $msg:expr $(,)?) => {
204+
($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr $(, @only_local: $only_local:expr)?, $msg:expr $(,)?) => {
193205
BuiltinAttribute {
194206
name: sym::$attr,
207+
only_local: or_default!(false, $($only_local)?),
195208
type_: $typ,
196209
template: $tpl,
197210
duplicates: $duplicates,
@@ -201,12 +214,13 @@ macro_rules! gated {
201214
}
202215

203216
macro_rules! rustc_attr {
204-
(TEST, $attr:ident, $typ:expr, $tpl:expr, $duplicate:expr $(,)?) => {
217+
(TEST, $attr:ident, $typ:expr, $tpl:expr, $duplicate:expr $(, @only_local: $only_local:expr)? $(,)?) => {
205218
rustc_attr!(
206219
$attr,
207220
$typ,
208221
$tpl,
209222
$duplicate,
223+
$(@only_local: $only_local,)?
210224
concat!(
211225
"the `#[",
212226
stringify!($attr),
@@ -215,9 +229,10 @@ macro_rules! rustc_attr {
215229
),
216230
)
217231
};
218-
($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $msg:expr $(,)?) => {
232+
($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr $(, @only_local: $only_local:expr)?, $msg:expr $(,)?) => {
219233
BuiltinAttribute {
220234
name: sym::$attr,
235+
only_local: or_default!(false, $($only_local)?),
221236
type_: $typ,
222237
template: $tpl,
223238
duplicates: $duplicates,
@@ -237,6 +252,10 @@ const INTERNAL_UNSTABLE: &str = "this is an internal attribute that will never b
237252

238253
pub struct BuiltinAttribute {
239254
pub name: Symbol,
255+
/// Whether this attribute is only used in the local crate.
256+
///
257+
/// If so, it is not encoded in the crate metadata.
258+
pub only_local: bool,
240259
pub type_: AttributeType,
241260
pub template: AttributeTemplate,
242261
pub duplicates: AttributeDuplicates,
@@ -295,7 +314,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
295314
ungated!(must_use, Normal, template!(Word, NameValueStr: "reason"), FutureWarnFollowing),
296315
gated!(
297316
must_not_suspend, Normal, template!(Word, NameValueStr: "reason"), WarnFollowing,
298-
must_not_suspend, experimental!(must_not_suspend)
317+
experimental!(must_not_suspend)
299318
),
300319
ungated!(
301320
deprecated, Normal,
@@ -324,8 +343,8 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
324343
ungated!(repr, Normal, template!(List: "C"), DuplicatesOk),
325344
ungated!(export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding),
326345
ungated!(link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding),
327-
ungated!(no_mangle, Normal, template!(Word), WarnFollowing),
328-
ungated!(used, Normal, template!(Word, List: "compiler|linker"), WarnFollowing),
346+
ungated!(no_mangle, Normal, template!(Word), WarnFollowing, @only_local: true),
347+
ungated!(used, Normal, template!(Word, List: "compiler|linker"), WarnFollowing, @only_local: true),
329348

330349
// Limits:
331350
ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing),
@@ -358,8 +377,8 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
358377
ungated!(panic_handler, Normal, template!(Word), WarnFollowing), // RFC 2070
359378

360379
// Code generation:
361-
ungated!(inline, Normal, template!(Word, List: "always|never"), FutureWarnFollowing),
362-
ungated!(cold, Normal, template!(Word), WarnFollowing),
380+
ungated!(inline, Normal, template!(Word, List: "always|never"), FutureWarnFollowing, @only_local: true),
381+
ungated!(cold, Normal, template!(Word), WarnFollowing, @only_local: true),
363382
ungated!(no_builtins, CrateLevel, template!(Word), WarnFollowing),
364383
ungated!(target_feature, Normal, template!(List: r#"enable = "name""#), DuplicatesOk),
365384
ungated!(track_caller, Normal, template!(Word), WarnFollowing),
@@ -385,7 +404,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
385404
),
386405

387406
// Linking:
388-
gated!(naked, Normal, template!(Word), WarnFollowing, naked_functions, experimental!(naked)),
407+
gated!(naked, Normal, template!(Word), WarnFollowing, @only_local: true, naked_functions, experimental!(naked)),
389408
gated!(
390409
link_ordinal, Normal, template!(List: "ordinal"), ErrorPreceding, raw_dylib,
391410
experimental!(link_ordinal)
@@ -394,6 +413,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
394413
// Plugins:
395414
BuiltinAttribute {
396415
name: sym::plugin,
416+
only_local: false,
397417
type_: CrateLevel,
398418
template: template!(List: "name"),
399419
duplicates: DuplicatesOk,
@@ -475,7 +495,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
475495
),
476496
// DuplicatesOk since it has its own validation
477497
ungated!(
478-
stable, Normal, template!(List: r#"feature = "name", since = "version""#), DuplicatesOk
498+
stable, Normal, template!(List: r#"feature = "name", since = "version""#), DuplicatesOk,
479499
),
480500
ungated!(
481501
unstable, Normal,
@@ -546,11 +566,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
546566
// ==========================================================================
547567

548568
gated!(
549-
linkage, Normal, template!(NameValueStr: "external|internal|..."), ErrorPreceding,
569+
linkage, Normal, template!(NameValueStr: "external|internal|..."), ErrorPreceding, @only_local: true,
550570
"the `linkage` attribute is experimental and not portable across platforms",
551571
),
552572
rustc_attr!(
553-
rustc_std_internal_symbol, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE
573+
rustc_std_internal_symbol, Normal, template!(Word), WarnFollowing, @only_local: true, INTERNAL_UNSTABLE
554574
),
555575

556576
// ==========================================================================
@@ -633,7 +653,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
633653
// Internal attributes, Misc:
634654
// ==========================================================================
635655
gated!(
636-
lang, Normal, template!(NameValueStr: "name"), DuplicatesOk, lang_items,
656+
lang, Normal, template!(NameValueStr: "name"), DuplicatesOk, @only_local: true, lang_items,
637657
"language items are subject to change",
638658
),
639659
rustc_attr!(
@@ -642,11 +662,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
642662
"#[rustc_pass_by_value] is used to mark types that must be passed by value instead of reference."
643663
),
644664
rustc_attr!(
645-
rustc_coherence_is_core, AttributeType::CrateLevel, template!(Word), ErrorFollowing,
665+
rustc_coherence_is_core, AttributeType::CrateLevel, template!(Word), ErrorFollowing, @only_local: true,
646666
"#![rustc_coherence_is_core] allows inherent methods on builtin types, only intended to be used in `core`."
647667
),
648668
rustc_attr!(
649-
rustc_allow_incoherent_impl, AttributeType::Normal, template!(Word), ErrorFollowing,
669+
rustc_allow_incoherent_impl, AttributeType::Normal, template!(Word), ErrorFollowing, @only_local: true,
650670
"#[rustc_allow_incoherent_impl] has to be added to all impl items of an incoherent inherent impl."
651671
),
652672
rustc_attr!(
@@ -656,6 +676,8 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
656676
),
657677
BuiltinAttribute {
658678
name: sym::rustc_diagnostic_item,
679+
// FIXME: This can be `true` once we always use `tcx.is_diagnostic_item`.
680+
only_local: false,
659681
type_: Normal,
660682
template: template!(NameValueStr: "name"),
661683
duplicates: ErrorFollowing,
@@ -676,7 +698,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
676698
"unboxed_closures are still evolving",
677699
),
678700
rustc_attr!(
679-
rustc_inherit_overflow_checks, Normal, template!(Word), WarnFollowing,
701+
rustc_inherit_overflow_checks, Normal, template!(Word), WarnFollowing, @only_local: true,
680702
"the `#[rustc_inherit_overflow_checks]` attribute is just used to control \
681703
overflow checking behavior of several libcore functions that are inlined \
682704
across crates and will never be stable",
@@ -778,6 +800,10 @@ pub fn is_builtin_attr_name(name: Symbol) -> bool {
778800
BUILTIN_ATTRIBUTE_MAP.get(&name).is_some()
779801
}
780802

803+
pub fn is_builtin_only_local(name: Symbol) -> bool {
804+
BUILTIN_ATTRIBUTE_MAP.get(&name).map_or(false, |attr| attr.only_local)
805+
}
806+
781807
pub static BUILTIN_ATTRIBUTE_MAP: SyncLazy<FxHashMap<Symbol, &BuiltinAttribute>> =
782808
SyncLazy::new(|| {
783809
let mut map = FxHashMap::default();

compiler/rustc_feature/src/lib.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,8 @@ pub use accepted::ACCEPTED_FEATURES;
149149
pub use active::{Features, ACTIVE_FEATURES, INCOMPATIBLE_FEATURES};
150150
pub use builtin_attrs::AttributeDuplicates;
151151
pub use builtin_attrs::{
152-
deprecated_attributes, find_gated_cfg, is_builtin_attr_name, AttributeGate, AttributeTemplate,
153-
AttributeType, BuiltinAttribute, GatedCfg, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP,
152+
deprecated_attributes, find_gated_cfg, is_builtin_attr_name, is_builtin_only_local,
153+
AttributeGate, AttributeTemplate, AttributeType, BuiltinAttribute, GatedCfg,
154+
BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP,
154155
};
155156
pub use removed::{REMOVED_FEATURES, STABLE_REMOVED_FEATURES};

compiler/rustc_incremental/src/persist/dirty_clean.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -183,10 +183,7 @@ pub struct DirtyCleanVisitor<'tcx> {
183183
impl<'tcx> DirtyCleanVisitor<'tcx> {
184184
/// Possibly "deserialize" the attribute into a clean/dirty assertion
185185
fn assertion_maybe(&mut self, item_id: LocalDefId, attr: &Attribute) -> Option<Assertion> {
186-
if !attr.has_name(sym::rustc_clean) {
187-
// skip: not rustc_clean/dirty
188-
return None;
189-
}
186+
assert!(attr.has_name(sym::rustc_clean));
190187
if !check_config(self.tcx, attr) {
191188
// skip: not the correct `cfg=`
192189
return None;
@@ -384,7 +381,7 @@ impl<'tcx> DirtyCleanVisitor<'tcx> {
384381
fn check_item(&mut self, item_id: LocalDefId) {
385382
let item_span = self.tcx.def_span(item_id.to_def_id());
386383
let def_path_hash = self.tcx.def_path_hash(item_id.to_def_id());
387-
for attr in self.tcx.get_attrs(item_id.to_def_id()).iter() {
384+
for attr in self.tcx.get_attrs(item_id.to_def_id(), sym::rustc_clean) {
388385
let Some(assertion) = self.assertion_maybe(item_id, attr) else {
389386
continue;
390387
};

compiler/rustc_interface/src/queries.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -258,10 +258,7 @@ impl<'tcx> Queries<'tcx> {
258258
/// an error.
259259
fn check_for_rustc_errors_attr(tcx: TyCtxt<'_>) {
260260
let Some((def_id, _)) = tcx.entry_fn(()) else { return };
261-
262-
let attrs = &*tcx.get_attrs(def_id);
263-
let attrs = attrs.iter().filter(|attr| attr.has_name(sym::rustc_error));
264-
for attr in attrs {
261+
for attr in tcx.get_attrs(def_id, sym::rustc_error) {
265262
match attr.meta_item_list() {
266263
// Check if there is a `#[rustc_error(delay_span_bug_from_inside_query)]`.
267264
Some(list)

compiler/rustc_lint/src/builtin.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,7 @@ impl MissingDoc {
551551
}
552552
}
553553

554-
let attrs = cx.tcx.get_attrs(def_id.to_def_id());
554+
let attrs = cx.tcx.hir().attrs(cx.tcx.hir().local_def_id_to_hir_id(def_id));
555555
let has_doc = attrs.iter().any(has_doc);
556556
if !has_doc {
557557
cx.struct_span_lint(
@@ -2738,11 +2738,7 @@ impl ClashingExternDeclarations {
27382738
// bottleneck, this does just fine.
27392739
(
27402740
overridden_link_name,
2741-
tcx.get_attrs(fi.def_id.to_def_id())
2742-
.iter()
2743-
.find(|at| at.has_name(sym::link_name))
2744-
.unwrap()
2745-
.span,
2741+
tcx.get_attr(fi.def_id.to_def_id(), sym::link_name).unwrap().span,
27462742
)
27472743
})
27482744
{

compiler/rustc_lint/src/types.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,7 @@ enum FfiResult<'tcx> {
668668
}
669669

670670
crate fn nonnull_optimization_guaranteed<'tcx>(tcx: TyCtxt<'tcx>, def: ty::AdtDef<'tcx>) -> bool {
671-
tcx.get_attrs(def.did()).iter().any(|a| a.has_name(sym::rustc_nonnull_optimization_guaranteed))
671+
tcx.has_attr(def.did(), sym::rustc_nonnull_optimization_guaranteed)
672672
}
673673

674674
/// `repr(transparent)` structs can have a single non-ZST field, this function returns that

0 commit comments

Comments
 (0)