@@ -52,6 +52,7 @@ use std::mem;
52
52
use std:: rc:: Rc ;
53
53
use syntax:: abi:: Abi ;
54
54
use hir;
55
+ use lint;
55
56
use util:: nodemap:: FxHashMap ;
56
57
57
58
struct InferredObligationsSnapshotVecDelegate < ' tcx > {
@@ -407,19 +408,62 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
407
408
debug ! ( "select({:?})" , obligation) ;
408
409
assert ! ( !obligation. predicate. has_escaping_regions( ) ) ;
409
410
411
+ let tcx = self . tcx ( ) ;
410
412
let dep_node = obligation. predicate . dep_node ( ) ;
411
- let _task = self . tcx ( ) . dep_graph . in_task ( dep_node) ;
413
+ let _task = tcx. dep_graph . in_task ( dep_node) ;
412
414
413
415
let stack = self . push_stack ( TraitObligationStackList :: empty ( ) , obligation) ;
414
- match self . candidate_from_obligation ( & stack) ? {
415
- None => Ok ( None ) ,
416
+ let ret = match self . candidate_from_obligation ( & stack) ? {
417
+ None => None ,
416
418
Some ( candidate) => {
417
419
let mut candidate = self . confirm_candidate ( obligation, candidate) ?;
418
420
let inferred_obligations = ( * self . inferred_obligations ) . into_iter ( ) . cloned ( ) ;
419
421
candidate. nested_obligations_mut ( ) . extend ( inferred_obligations) ;
420
- Ok ( Some ( candidate) )
422
+ Some ( candidate)
421
423
} ,
424
+ } ;
425
+
426
+ // Test whether this is a `()` which was produced by defaulting a
427
+ // diverging type variable with `!` disabled. If so, we may need
428
+ // to raise a warning.
429
+ if obligation. predicate . skip_binder ( ) . self_ty ( ) . is_defaulted_unit ( ) {
430
+ let mut raise_warning = true ;
431
+ // Don't raise a warning if the trait is implemented for ! and only
432
+ // permits a trivial implementation for !. This stops us warning
433
+ // about (for example) `(): Clone` becoming `!: Clone` because such
434
+ // a switch can't cause code to stop compiling or execute
435
+ // differently.
436
+ let mut never_obligation = obligation. clone ( ) ;
437
+ let def_id = never_obligation. predicate . skip_binder ( ) . trait_ref . def_id ;
438
+ never_obligation. predicate = never_obligation. predicate . map_bound ( |mut trait_pred| {
439
+ // Swap out () with ! so we can check if the trait is impld for !
440
+ {
441
+ let mut trait_ref = & mut trait_pred. trait_ref ;
442
+ let unit_substs = trait_ref. substs ;
443
+ let mut never_substs = Vec :: with_capacity ( unit_substs. len ( ) ) ;
444
+ never_substs. push ( From :: from ( tcx. types . never ) ) ;
445
+ never_substs. extend ( & unit_substs[ 1 ..] ) ;
446
+ trait_ref. substs = tcx. intern_substs ( & never_substs) ;
447
+ }
448
+ trait_pred
449
+ } ) ;
450
+ if let Ok ( Some ( ..) ) = self . select ( & never_obligation) {
451
+ if !tcx. trait_relevant_for_never ( def_id) {
452
+ // The trait is also implemented for ! and the resulting
453
+ // implementation cannot actually be invoked in any way.
454
+ raise_warning = false ;
455
+ }
456
+ }
457
+
458
+ if raise_warning {
459
+ tcx. sess . add_lint ( lint:: builtin:: RESOLVE_TRAIT_ON_DEFAULTED_UNIT ,
460
+ obligation. cause . body_id ,
461
+ obligation. cause . span ,
462
+ format ! ( "code relies on type inference rules which are likely \
463
+ to change") ) ;
464
+ }
422
465
}
466
+ Ok ( ret)
423
467
}
424
468
425
469
///////////////////////////////////////////////////////////////////////////
@@ -1744,15 +1788,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
1744
1788
1745
1789
ty:: TyStr | ty:: TySlice ( _) | ty:: TyDynamic ( ..) => Never ,
1746
1790
1747
- ty:: TyTuple ( tys) => {
1791
+ ty:: TyTuple ( tys, _ ) => {
1748
1792
Where ( ty:: Binder ( tys. last ( ) . into_iter ( ) . cloned ( ) . collect ( ) ) )
1749
1793
}
1750
1794
1751
1795
ty:: TyAdt ( def, substs) => {
1752
1796
let sized_crit = def. sized_constraint ( self . tcx ( ) ) ;
1753
1797
// (*) binder moved here
1754
1798
Where ( ty:: Binder ( match sized_crit. sty {
1755
- ty:: TyTuple ( tys) => tys. to_vec ( ) . subst ( self . tcx ( ) , substs) ,
1799
+ ty:: TyTuple ( tys, _ ) => tys. to_vec ( ) . subst ( self . tcx ( ) , substs) ,
1756
1800
ty:: TyBool => vec ! [ ] ,
1757
1801
_ => vec ! [ sized_crit. subst( self . tcx( ) , substs) ]
1758
1802
} ) )
@@ -1799,7 +1843,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
1799
1843
Where ( ty:: Binder ( vec ! [ element_ty] ) )
1800
1844
}
1801
1845
1802
- ty:: TyTuple ( tys) => {
1846
+ ty:: TyTuple ( tys, _ ) => {
1803
1847
// (*) binder moved here
1804
1848
Where ( ty:: Binder ( tys. to_vec ( ) ) )
1805
1849
}
@@ -1874,7 +1918,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
1874
1918
vec ! [ element_ty]
1875
1919
}
1876
1920
1877
- ty:: TyTuple ( ref tys) => {
1921
+ ty:: TyTuple ( ref tys, _ ) => {
1878
1922
// (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
1879
1923
tys. to_vec ( )
1880
1924
}
0 commit comments