@@ -1412,14 +1412,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
14121412
14131413 debug ! ( "winnowed to {} candidates for {:?}: {:?}" , candidates. len( ) , stack, candidates) ;
14141414
1415+ let needs_infer = stack. obligation . predicate . needs_infer ( ) ;
1416+
14151417 // If there are STILL multiple candidates, we can further
14161418 // reduce the list by dropping duplicates -- including
14171419 // resolving specializations.
14181420 if candidates. len ( ) > 1 {
14191421 let mut i = 0 ;
14201422 while i < candidates. len ( ) {
14211423 let is_dup = ( 0 ..candidates. len ( ) ) . filter ( |& j| i != j) . any ( |j| {
1422- self . candidate_should_be_dropped_in_favor_of ( & candidates[ i] , & candidates[ j] )
1424+ self . candidate_should_be_dropped_in_favor_of (
1425+ & candidates[ i] ,
1426+ & candidates[ j] ,
1427+ needs_infer,
1428+ )
14231429 } ) ;
14241430 if is_dup {
14251431 debug ! ( "Dropping candidate #{}/{}: {:?}" , i, candidates. len( ) , candidates[ i] ) ;
@@ -2253,6 +2259,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
22532259 & mut self ,
22542260 victim : & EvaluatedCandidate < ' tcx > ,
22552261 other : & EvaluatedCandidate < ' tcx > ,
2262+ needs_infer : bool ,
22562263 ) -> bool {
22572264 if victim. candidate == other. candidate {
22582265 return true ;
@@ -2334,10 +2341,55 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
23342341 match victim. candidate {
23352342 ImplCandidate ( victim_def) => {
23362343 let tcx = self . tcx ( ) ;
2337- return tcx. specializes ( ( other_def, victim_def) )
2338- || tcx
2339- . impls_are_allowed_to_overlap ( other_def, victim_def)
2340- . is_some ( ) ;
2344+ if tcx. specializes ( ( other_def, victim_def) ) {
2345+ return true ;
2346+ }
2347+ return match tcx. impls_are_allowed_to_overlap ( other_def, victim_def) {
2348+ Some ( ty:: ImplOverlapKind :: Permitted { marker : true } ) => {
2349+ // Subtle: If the predicate we are evaluating has inference
2350+ // variables, do *not* allow discarding candidates due to
2351+ // marker trait impls.
2352+ //
2353+ // Without this restriction, we could end up accidentally
2354+ // constrainting inference variables based on an arbitrarily
2355+ // chosen trait impl.
2356+ //
2357+ // Imagine we have the following code:
2358+ //
2359+ // ```rust
2360+ // #[marker] trait MyTrait {}
2361+ // impl MyTrait for u8 {}
2362+ // impl MyTrait for bool {}
2363+ // ```
2364+ //
2365+ // And we are evaluating the predicate `<_#0t as MyTrait>`.
2366+ //
2367+ // During selection, we will end up with one candidate for each
2368+ // impl of `MyTrait`. If we were to discard one impl in favor
2369+ // of the other, we would be left with one candidate, causing
2370+ // us to "successfully" select the predicate, unifying
2371+ // _#0t with (for example) `u8`.
2372+ //
2373+ // However, we have no reason to believe that this unification
2374+ // is correct - we've essentially just picked an arbitrary
2375+ // *possibility* for _#0t, and required that this be the *only*
2376+ // possibility.
2377+ //
2378+ // Eventually, we will either:
2379+ // 1) Unify all inference variables in the predicate through
2380+ // some other means (e.g. type-checking of a function). We will
2381+ // then be in a position to drop marker trait candidates
2382+ // without constraining inference variables (since there are
2383+ // none left to constrin)
2384+ // 2) Be left with some unconstrained inference variables. We
2385+ // will then correctly report an inference error, since the
2386+ // existence of multiple marker trait impls tells us nothing
2387+ // about which one should actually apply.
2388+ !needs_infer
2389+ }
2390+ Some ( _) => true ,
2391+ None => false ,
2392+ } ;
23412393 }
23422394 ParamCandidate ( ref cand) => {
23432395 // Prefer the impl to a global where clause candidate.
0 commit comments