@@ -76,6 +76,7 @@ use rustc::ty::relate::RelateResult;
7676use rustc:: ty:: subst:: Subst ;
7777use errors:: DiagnosticBuilder ;
7878use syntax:: abi;
79+ use syntax:: feature_gate;
7980use syntax:: ptr:: P ;
8081use syntax_pos;
8182
@@ -520,14 +521,24 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
520521 coerce_source,
521522 & [ coerce_target] ) ) ;
522523
524+ let mut has_unsized_tuple_coercion = false ;
525+
523526 // Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
524527 // emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
525528 // inference might unify those two inner type variables later.
526529 let traits = [ coerce_unsized_did, unsize_did] ;
527530 while let Some ( obligation) = queue. pop_front ( ) {
528531 debug ! ( "coerce_unsized resolve step: {:?}" , obligation) ;
529532 let trait_ref = match obligation. predicate {
530- ty:: Predicate :: Trait ( ref tr) if traits. contains ( & tr. def_id ( ) ) => tr. clone ( ) ,
533+ ty:: Predicate :: Trait ( ref tr) if traits. contains ( & tr. def_id ( ) ) => {
534+ if unsize_did == tr. def_id ( ) {
535+ if let ty:: TyTuple ( ..) = tr. 0 . input_types ( ) . nth ( 1 ) . unwrap ( ) . sty {
536+ debug ! ( "coerce_unsized: found unsized tuple coercion" ) ;
537+ has_unsized_tuple_coercion = true ;
538+ }
539+ }
540+ tr. clone ( )
541+ }
531542 _ => {
532543 coercion. obligations . push ( obligation) ;
533544 continue ;
@@ -557,6 +568,14 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
557568 }
558569 }
559570
571+ if has_unsized_tuple_coercion && !self . tcx . sess . features . borrow ( ) . unsized_tuple_coercion {
572+ feature_gate:: emit_feature_err ( & self . tcx . sess . parse_sess ,
573+ "unsized_tuple_coercion" ,
574+ self . cause . span ,
575+ feature_gate:: GateIssue :: Language ,
576+ feature_gate:: EXPLAIN_UNSIZED_TUPLE_COERCION ) ;
577+ }
578+
560579 Ok ( coercion)
561580 }
562581
0 commit comments