diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs | 36 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/codegen_attrs.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_hir/src/attrs/data_structures.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/context.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_type_ir/src/interner.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_type_ir/src/search_graph/global_cache.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_type_ir/src/search_graph/mod.rs | 2 |
7 files changed, 54 insertions, 17 deletions
diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index 262b8213977..7978bf28214 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -370,6 +370,7 @@ impl<S: Stage> NoArgsAttributeParser<S> for NoMangleParser { pub(crate) struct UsedParser { first_compiler: Option<Span>, first_linker: Option<Span>, + first_default: Option<Span>, } // A custom `AttributeParser` is used rather than a Simple attribute parser because @@ -382,7 +383,7 @@ impl<S: Stage> AttributeParser<S> for UsedParser { template!(Word, List: &["compiler", "linker"]), |group: &mut Self, cx, args| { let used_by = match args { - ArgParser::NoArgs => UsedBy::Linker, + ArgParser::NoArgs => UsedBy::Default, ArgParser::List(list) => { let Some(l) = list.single() else { cx.expected_single_argument(list.span); @@ -423,12 +424,29 @@ impl<S: Stage> AttributeParser<S> for UsedParser { ArgParser::NameValue(_) => return, }; + let attr_span = cx.attr_span; + + // `#[used]` is interpreted as `#[used(linker)]` (though depending on target OS the + // circumstances are more complicated). While we're checking `used_by`, also report + // these cross-`UsedBy` duplicates to warn. let target = match used_by { UsedBy::Compiler => &mut group.first_compiler, - UsedBy::Linker => &mut group.first_linker, + UsedBy::Linker => { + if let Some(prev) = group.first_default { + cx.warn_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); + return; + } + &mut group.first_default + } }; - let attr_span = cx.attr_span; if let Some(prev) = *target { cx.warn_unused_duplicate(prev, attr_span); } else { @@ -440,11 +458,13 @@ impl<S: Stage> AttributeParser<S> for UsedParser { AllowedTargets::AllowList(&[Allow(Target::Static), Warn(Target::MacroCall)]); fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> { - // Ratcheting behaviour, if both `linker` and `compiler` are specified, use `linker` - Some(match (self.first_compiler, self.first_linker) { - (_, Some(span)) => AttributeKind::Used { used_by: UsedBy::Linker, span }, - (Some(span), _) => AttributeKind::Used { used_by: UsedBy::Compiler, span }, - (None, None) => return None, + // If a specific form of `used` is specified, it takes precedence over generic `#[used]`. + // If both `linker` and `compiler` are specified, use `linker`. + Some(match (self.first_compiler, self.first_linker, self.first_default) { + (_, Some(span), _) => AttributeKind::Used { used_by: UsedBy::Linker, span }, + (Some(span), _, _) => AttributeKind::Used { used_by: UsedBy::Compiler, span }, + (_, _, Some(span)) => AttributeKind::Used { used_by: UsedBy::Default, span }, + (None, None, None) => return None, }) } } diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 32ae810ecc8..2c7643e46ce 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -263,6 +263,19 @@ fn process_builtin_attrs( AttributeKind::Used { used_by, .. } => match used_by { UsedBy::Compiler => codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_COMPILER, UsedBy::Linker => codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_LINKER, + UsedBy::Default => { + let used_form = if tcx.sess.target.os == "illumos" { + // illumos' `ld` doesn't support a section header that would represent + // `#[used(linker)]`, see + // https://github.com/rust-lang/rust/issues/146169. For that target, + // downgrade as if `#[used(compiler)]` was requested and hope for the + // best. + CodegenFnAttrFlags::USED_COMPILER + } else { + CodegenFnAttrFlags::USED_LINKER + }; + codegen_fn_attrs.flags |= used_form; + } }, AttributeKind::FfiConst(_) => { codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index ddcbaeaad88..beeca7332cb 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -146,12 +146,13 @@ impl Deprecation { } /// There are three valid forms of the attribute: -/// `#[used]`, which is semantically equivalent to `#[used(linker)]` except that the latter is currently unstable. +/// `#[used]`, which is equivalent to `#[used(linker)]` on targets that support it, but `#[used(compiler)]` if not. /// `#[used(compiler)]` /// `#[used(linker)]` #[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)] #[derive(HashStable_Generic, PrintAttribute)] pub enum UsedBy { + Default, Compiler, Linker, } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 1b89a49cf98..3c5c21a7a89 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -207,8 +207,9 @@ impl<'tcx> Interner for TyCtxt<'tcx> { from_entry(entry) } - fn evaluation_is_concurrent(&self) -> bool { - self.sess.threads() > 1 + fn assert_evaluation_is_concurrent(&self) { + // Turns out, the assumption for this function isn't perfect. + // See trait-system-refactor-initiative#234. } fn expand_abstract_consts<T: TypeFoldable<TyCtxt<'tcx>>>(self, t: T) -> T { diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 886d1a78bcb..f933423197d 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -183,7 +183,9 @@ pub trait Interner: from_entry: impl FnOnce(&CanonicalParamEnvCacheEntry<Self>) -> R, ) -> R; - fn evaluation_is_concurrent(&self) -> bool; + /// Useful for testing. If a cache entry is replaced, this should + /// (in theory) only happen when concurrent. + fn assert_evaluation_is_concurrent(&self); fn expand_abstract_consts<T: TypeFoldable<Self>>(self, t: T) -> T; @@ -567,7 +569,7 @@ impl<I: Interner> search_graph::Cx for I { fn with_global_cache<R>(self, f: impl FnOnce(&mut search_graph::GlobalCache<Self>) -> R) -> R { I::with_global_cache(self, f) } - fn evaluation_is_concurrent(&self) -> bool { - self.evaluation_is_concurrent() + fn assert_evaluation_is_concurrent(&self) { + self.assert_evaluation_is_concurrent() } } diff --git a/compiler/rustc_type_ir/src/search_graph/global_cache.rs b/compiler/rustc_type_ir/src/search_graph/global_cache.rs index eb56c1af408..7e438fefffc 100644 --- a/compiler/rustc_type_ir/src/search_graph/global_cache.rs +++ b/compiler/rustc_type_ir/src/search_graph/global_cache.rs @@ -56,13 +56,13 @@ impl<X: Cx> GlobalCache<X> { let with_overflow = WithOverflow { nested_goals, result }; let prev = entry.with_overflow.insert(required_depth, with_overflow); if let Some(prev) = &prev { - assert!(cx.evaluation_is_concurrent()); + cx.assert_evaluation_is_concurrent(); assert_eq!(cx.get_tracked(&prev.result), evaluation_result.result); } } else { let prev = entry.success.replace(Success { required_depth, nested_goals, result }); if let Some(prev) = &prev { - assert!(cx.evaluation_is_concurrent()); + cx.assert_evaluation_is_concurrent(); assert_eq!(cx.get_tracked(&prev.result), evaluation_result.result); } } diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs index 7aa58d096d5..8a41c99aeaa 100644 --- a/compiler/rustc_type_ir/src/search_graph/mod.rs +++ b/compiler/rustc_type_ir/src/search_graph/mod.rs @@ -53,7 +53,7 @@ pub trait Cx: Copy { fn with_global_cache<R>(self, f: impl FnOnce(&mut GlobalCache<Self>) -> R) -> R; - fn evaluation_is_concurrent(&self) -> bool; + fn assert_evaluation_is_concurrent(&self); } pub trait Delegate: Sized { |
