@@ -24,6 +24,7 @@ use rustc_data_structures::fx::FxIndexSet;
24
24
use rustc_errors:: { codes:: * , Diag , EmissionGuarantee } ;
25
25
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
26
26
use rustc_middle:: bug;
27
+ use rustc_middle:: query:: LocalCrate ;
27
28
use rustc_middle:: ty:: { self , ImplSubject , Ty , TyCtxt , TypeVisitableExt } ;
28
29
use rustc_middle:: ty:: { GenericArgs , GenericArgsRef } ;
29
30
use rustc_session:: lint:: builtin:: COHERENCE_LEAK_CHECK ;
@@ -136,38 +137,29 @@ pub fn translate_args_with_cause<'tcx>(
136
137
source_args. rebase_onto ( infcx. tcx , source_impl, target_args)
137
138
}
138
139
140
+ pub ( super ) fn specialization_enabled_in ( tcx : TyCtxt < ' _ > , _: LocalCrate ) -> bool {
141
+ tcx. features ( ) . specialization || tcx. features ( ) . min_specialization
142
+ }
143
+
139
144
/// Is `impl1` a specialization of `impl2`?
140
145
///
141
146
/// Specialization is determined by the sets of types to which the impls apply;
142
147
/// `impl1` specializes `impl2` if it applies to a subset of the types `impl2` applies
143
148
/// to.
144
149
#[ instrument( skip( tcx) , level = "debug" ) ]
145
150
pub ( 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 ;
171
163
}
172
164
}
173
165
0 commit comments