about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-01-15 08:44:49 +0100
committerGitHub <noreply@github.com>2024-01-15 08:44:49 +0100
commit0891cb4d814b4acb0b65fc0e73c710f7f38e9741 (patch)
tree42db368bf59274dc68b7a43de0caf4c4429838fd
parent1e46be6a538eb730101753c76311e9a249f2d320 (diff)
parenteb63d3a49d7681d6ede7dc1bcac7bb1125ff7132 (diff)
downloadrust-0891cb4d814b4acb0b65fc0e73c710f7f38e9741.tar.gz
rust-0891cb4d814b4acb0b65fc0e73c710f7f38e9741.zip
Rollup merge of #119963 - clubby789:spec-allow-internal-unstable, r=compiler-errors
Fix `allow_internal_unstable` for `(min_)specialization`

Fixes #119950

Blocked on #119949 (comment doesn't make sense until that merges)

I'd like to follow this up and look for more instances of not properly checking spans for features but I wanted to fix the motivating issue.
-rw-r--r--compiler/rustc_index_macros/src/lib.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/mod.rs26
-rw-r--r--tests/ui/specialization/allow_internal_unstable.rs18
3 files changed, 44 insertions, 3 deletions
diff --git a/compiler/rustc_index_macros/src/lib.rs b/compiler/rustc_index_macros/src/lib.rs
index 4f973c1f010..72567b43a5f 100644
--- a/compiler/rustc_index_macros/src/lib.rs
+++ b/compiler/rustc_index_macros/src/lib.rs
@@ -39,6 +39,9 @@ mod newtype;
     feature = "nightly",
     allow_internal_unstable(step_trait, rustc_attrs, trusted_step, spec_option_partial_eq)
 )]
+// FIXME: Remove the above comment about `min_specialization` once bootstrap is bumped,
+// and the corresponding one on SpecOptionPartialEq
+#[cfg_attr(all(feature = "nightly", not(bootstrap)), allow_internal_unstable(min_specialization))]
 pub fn newtype_index(input: TokenStream) -> TokenStream {
     newtype::newtype(input)
 }
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index 200d022c80c..b37d9714ddd 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -26,7 +26,7 @@ use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt, TypeVisitableExt};
 use rustc_middle::ty::{GenericArgs, GenericArgsRef};
 use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK;
 use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS;
-use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
+use rustc_span::{sym, ErrorGuaranteed, Span, DUMMY_SP};
 
 use super::util;
 use super::SelectionContext;
@@ -142,10 +142,30 @@ pub fn translate_args_with_cause<'tcx>(
 pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, DefId)) -> bool {
     // The feature gate should prevent introducing new specializations, but not
     // taking advantage of upstream ones.
+    // If specialization is enabled for this crate then no extra checks are needed.
+    // If it's not, and either of the `impl`s is local to this crate, then this definitely
+    // isn't specializing - unless specialization is enabled for the `impl` span,
+    // e.g. if it comes from an `allow_internal_unstable` macro
     let features = tcx.features();
     let specialization_enabled = features.specialization || features.min_specialization;
-    if !specialization_enabled && (impl1_def_id.is_local() || impl2_def_id.is_local()) {
-        return false;
+    if !specialization_enabled {
+        if impl1_def_id.is_local() {
+            let span = tcx.def_span(impl1_def_id);
+            if !span.allows_unstable(sym::specialization)
+                && !span.allows_unstable(sym::min_specialization)
+            {
+                return false;
+            }
+        }
+
+        if impl2_def_id.is_local() {
+            let span = tcx.def_span(impl2_def_id);
+            if !span.allows_unstable(sym::specialization)
+                && !span.allows_unstable(sym::min_specialization)
+            {
+                return false;
+            }
+        }
     }
 
     // We determine whether there's a subset relationship by:
diff --git a/tests/ui/specialization/allow_internal_unstable.rs b/tests/ui/specialization/allow_internal_unstable.rs
new file mode 100644
index 00000000000..317782b7b72
--- /dev/null
+++ b/tests/ui/specialization/allow_internal_unstable.rs
@@ -0,0 +1,18 @@
+// check-pass
+// test for #119950
+// compile-flags: --crate-type lib
+
+#![allow(internal_features)]
+#![feature(allow_internal_unstable)]
+
+#[allow_internal_unstable(min_specialization)]
+macro_rules! test {
+    () => {
+        struct T<U>(U);
+        trait Tr {}
+        impl<U> Tr for T<U> {}
+        impl Tr for T<u8> {}
+    }
+}
+
+test! {}