@@ -1412,14 +1412,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
1412
1412
1413
1413
debug ! ( "winnowed to {} candidates for {:?}: {:?}" , candidates. len( ) , stack, candidates) ;
1414
1414
1415
+ let needs_infer = stack. obligation . predicate . needs_infer ( ) ;
1416
+
1415
1417
// If there are STILL multiple candidates, we can further
1416
1418
// reduce the list by dropping duplicates -- including
1417
1419
// resolving specializations.
1418
1420
if candidates. len ( ) > 1 {
1419
1421
let mut i = 0 ;
1420
1422
while i < candidates. len ( ) {
1421
1423
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
+ )
1423
1429
} ) ;
1424
1430
if is_dup {
1425
1431
debug ! ( "Dropping candidate #{}/{}: {:?}" , i, candidates. len( ) , candidates[ i] ) ;
@@ -2253,6 +2259,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
2253
2259
& mut self ,
2254
2260
victim : & EvaluatedCandidate < ' tcx > ,
2255
2261
other : & EvaluatedCandidate < ' tcx > ,
2262
+ needs_infer : bool ,
2256
2263
) -> bool {
2257
2264
if victim. candidate == other. candidate {
2258
2265
return true ;
@@ -2334,10 +2341,55 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
2334
2341
match victim. candidate {
2335
2342
ImplCandidate ( victim_def) => {
2336
2343
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
+ } ;
2341
2393
}
2342
2394
ParamCandidate ( ref cand) => {
2343
2395
// Prefer the impl to a global where clause candidate.
0 commit comments