Skip to content
Merged
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
3 changes: 3 additions & 0 deletions compiler/rustc_index_macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,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)
}
26 changes: 23 additions & 3 deletions compiler/rustc_trait_selection/src/traits/specialize/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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:
Expand Down
18 changes: 18 additions & 0 deletions tests/ui/specialization/allow_internal_unstable.rs
Original file line number Diff line number Diff line change
@@ -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! {}