about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs36
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs13
-rw-r--r--compiler/rustc_hir/src/attrs/data_structures.rs3
-rw-r--r--compiler/rustc_middle/src/ty/context.rs5
-rw-r--r--compiler/rustc_type_ir/src/interner.rs8
-rw-r--r--compiler/rustc_type_ir/src/search_graph/global_cache.rs4
-rw-r--r--compiler/rustc_type_ir/src/search_graph/mod.rs2
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 {