@@ -24,6 +24,7 @@ use rustc_data_structures::fx::FxIndexSet;
2424use rustc_errors:: { codes:: * , Diag , EmissionGuarantee } ;
2525use rustc_hir:: def_id:: { DefId , LocalDefId } ;
2626use rustc_middle:: bug;
27+ use rustc_middle:: query:: LocalCrate ;
2728use rustc_middle:: ty:: { self , ImplSubject , Ty , TyCtxt , TypeVisitableExt } ;
2829use rustc_middle:: ty:: { GenericArgs , GenericArgsRef } ;
2930use rustc_session:: lint:: builtin:: COHERENCE_LEAK_CHECK ;
@@ -136,38 +137,29 @@ pub fn translate_args_with_cause<'tcx>(
136137 source_args. rebase_onto ( infcx. tcx , source_impl, target_args)
137138}
138139
140+ pub ( super ) fn specialization_enabled_in ( tcx : TyCtxt < ' _ > , _: LocalCrate ) -> bool {
141+ tcx. features ( ) . specialization || tcx. features ( ) . min_specialization
142+ }
143+
139144/// Is `impl1` a specialization of `impl2`?
140145///
141146/// Specialization is determined by the sets of types to which the impls apply;
142147/// `impl1` specializes `impl2` if it applies to a subset of the types `impl2` applies
143148/// to.
144149#[ instrument( skip( tcx) , level = "debug" ) ]
145150pub ( super ) fn specializes ( tcx : TyCtxt < ' _ > , ( impl1_def_id, impl2_def_id) : ( DefId , DefId ) ) -> bool {
146- // The feature gate should prevent introducing new specializations, but not
147- // taking advantage of upstream ones.
148- // If specialization is enabled for this crate then no extra checks are needed.
149- // If it's not, and either of the `impl`s is local to this crate, then this definitely
150- // isn't specializing - unless specialization is enabled for the `impl` span,
151- // e.g. if it comes from an `allow_internal_unstable` macro
152- let features = tcx. features ( ) ;
153- let specialization_enabled = features. specialization || features. min_specialization ;
154- if !specialization_enabled {
155- if impl1_def_id. is_local ( ) {
156- let span = tcx. def_span ( impl1_def_id) ;
157- if !span. allows_unstable ( sym:: specialization)
158- && !span. allows_unstable ( sym:: min_specialization)
159- {
160- return false ;
161- }
162- }
163-
164- if impl2_def_id. is_local ( ) {
165- let span = tcx. def_span ( impl2_def_id) ;
166- if !span. allows_unstable ( sym:: specialization)
167- && !span. allows_unstable ( sym:: min_specialization)
168- {
169- return false ;
170- }
151+ // We check that the specializing impl comes from a crate that has specialization enabled,
152+ // or if the specializing impl is marked with `allow_internal_unstable`.
153+ //
154+ // We don't really care if the specialized impl (the parent) is in a crate that has
155+ // specialization enabled, since it's not being specialized, and it's already been checked
156+ // for coherence.
157+ if !tcx. specialization_enabled_in ( impl1_def_id. krate ) {
158+ let span = tcx. def_span ( impl1_def_id) ;
159+ if !span. allows_unstable ( sym:: specialization)
160+ && !span. allows_unstable ( sym:: min_specialization)
161+ {
162+ return false ;
171163 }
172164 }
173165
0 commit comments