@@ -157,6 +157,9 @@ fn overlap_within_probe<'cx, 'tcx>(
157157 impl2_def_id : DefId ,
158158 snapshot : & CombinedSnapshot < ' _ , ' tcx > ,
159159) -> Option < OverlapResult < ' tcx > > {
160+ let infcx = selcx. infcx ( ) ;
161+ let tcx = infcx. tcx ;
162+
160163 // For the purposes of this check, we don't bring any placeholder
161164 // types into scope; instead, we replace the generic types with
162165 // fresh type variables, and hence we do our evaluations in an
@@ -166,6 +169,39 @@ fn overlap_within_probe<'cx, 'tcx>(
166169 let impl1_header = with_fresh_ty_vars ( selcx, param_env, impl1_def_id) ;
167170 let impl2_header = with_fresh_ty_vars ( selcx, param_env, impl2_def_id) ;
168171
172+ let strict_coherence = tcx. has_attr ( impl1_def_id, sym:: rustc_strict_coherence)
173+ && tcx. has_attr ( impl2_def_id, sym:: rustc_strict_coherence) ;
174+
175+ if stable_disjoint ( selcx, param_env, & impl1_header, impl2_header, strict_coherence) {
176+ return None ;
177+ }
178+
179+ if !skip_leak_check. is_yes ( ) {
180+ if infcx. leak_check ( true , snapshot) . is_err ( ) {
181+ debug ! ( "overlap: leak check failed" ) ;
182+ return None ;
183+ }
184+ }
185+
186+ let intercrate_ambiguity_causes = selcx. take_intercrate_ambiguity_causes ( ) ;
187+ debug ! ( "overlap: intercrate_ambiguity_causes={:#?}" , intercrate_ambiguity_causes) ;
188+
189+ let involves_placeholder =
190+ matches ! ( selcx. infcx( ) . region_constraints_added_in_snapshot( snapshot) , Some ( true ) ) ;
191+
192+ let impl_header = selcx. infcx ( ) . resolve_vars_if_possible ( impl1_header) ;
193+ Some ( OverlapResult { impl_header, intercrate_ambiguity_causes, involves_placeholder } )
194+ }
195+
196+ /// Given impl1 and impl2 check if both impls can be satisfied by a common type (including
197+ /// where-clauses) If so, return false, otherwise return true, they are disjoint.
198+ fn stable_disjoint < ' cx , ' tcx > (
199+ selcx : & mut SelectionContext < ' cx , ' tcx > ,
200+ param_env : ty:: ParamEnv < ' tcx > ,
201+ impl1_header : & ty:: ImplHeader < ' tcx > ,
202+ impl2_header : ty:: ImplHeader < ' tcx > ,
203+ strict_coherence : bool ,
204+ ) -> bool {
169205 debug ! ( "overlap: impl1_header={:?}" , impl1_header) ;
170206 debug ! ( "overlap: impl2_header={:?}" , impl2_header) ;
171207
@@ -177,7 +213,7 @@ fn overlap_within_probe<'cx, 'tcx>(
177213 {
178214 Ok ( InferOk { obligations, value : ( ) } ) => obligations,
179215 Err ( _) => {
180- return None ;
216+ return true ;
181217 }
182218 } ;
183219
@@ -222,9 +258,7 @@ fn overlap_within_probe<'cx, 'tcx>(
222258 . find ( |o| {
223259 // if both impl headers are set to strict coherence it means that this will be accepted
224260 // only if it's stated that T: !Trait. So only prove that the negated obligation holds.
225- if tcx. has_attr ( impl1_def_id, sym:: rustc_strict_coherence)
226- && tcx. has_attr ( impl2_def_id, sym:: rustc_strict_coherence)
227- {
261+ if strict_coherence {
228262 strict_check ( selcx, o)
229263 } else {
230264 loose_check ( selcx, o) || tcx. features ( ) . negative_impls && strict_check ( selcx, o)
@@ -236,24 +270,10 @@ fn overlap_within_probe<'cx, 'tcx>(
236270
237271 if let Some ( failing_obligation) = opt_failing_obligation {
238272 debug ! ( "overlap: obligation unsatisfiable {:?}" , failing_obligation) ;
239- return None ;
240- }
241-
242- if !skip_leak_check. is_yes ( ) {
243- if infcx. leak_check ( true , snapshot) . is_err ( ) {
244- debug ! ( "overlap: leak check failed" ) ;
245- return None ;
246- }
273+ true
274+ } else {
275+ false
247276 }
248-
249- let impl_header = selcx. infcx ( ) . resolve_vars_if_possible ( impl1_header) ;
250- let intercrate_ambiguity_causes = selcx. take_intercrate_ambiguity_causes ( ) ;
251- debug ! ( "overlap: intercrate_ambiguity_causes={:#?}" , intercrate_ambiguity_causes) ;
252-
253- let involves_placeholder =
254- matches ! ( selcx. infcx( ) . region_constraints_added_in_snapshot( snapshot) , Some ( true ) ) ;
255-
256- Some ( OverlapResult { impl_header, intercrate_ambiguity_causes, involves_placeholder } )
257277}
258278
259279fn loose_check < ' cx , ' tcx > (
0 commit comments