@@ -278,7 +278,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
278278 fn check_trait ( & mut self , item : & hir:: Item ) {
279279 let trait_def_id = self . tcx . hir . local_def_id ( item. id ) ;
280280 self . for_item ( item) . with_fcx ( |fcx, _| {
281- self . check_trait_where_clauses ( fcx, item. span , trait_def_id) ;
281+ self . check_where_clauses ( fcx, item. span , trait_def_id) ;
282282 vec ! [ ]
283283 } ) ;
284284 }
@@ -354,23 +354,6 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
354354 fcx : & FnCtxt < ' fcx , ' gcx , ' tcx > ,
355355 span : Span ,
356356 def_id : DefId ) {
357- self . inner_check_where_clauses ( fcx, span, def_id, false )
358- }
359-
360- fn check_trait_where_clauses < ' fcx , ' tcx > ( & mut self ,
361- fcx : & FnCtxt < ' fcx , ' gcx , ' tcx > ,
362- span : Span ,
363- def_id : DefId ) {
364- self . inner_check_where_clauses ( fcx, span, def_id, true )
365- }
366-
367- /// Checks where clauses and inline bounds that are declared on def_id.
368- fn inner_check_where_clauses < ' fcx , ' tcx > ( & mut self ,
369- fcx : & FnCtxt < ' fcx , ' gcx , ' tcx > ,
370- span : Span ,
371- def_id : DefId ,
372- is_trait : bool )
373- {
374357 use ty:: subst:: Subst ;
375358 use rustc:: ty:: TypeFoldable ;
376359
@@ -390,43 +373,50 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
390373 }
391374
392375 // Check that trait predicates are WF when params are substituted by their defaults.
393- // We don't want to overly constrain the predicates that may be written but we
394- // want to catch obviously wrong cases such as `struct Foo<T: Copy = String>`
395- // or cases where defaults don't work together such as:
396- // `struct Foo<T = i32, U = u8> where T: into<U>`
397- // Therefore we check if a predicate in which all type params are defaulted
398- // is WF with those defaults simultaneously substituted.
376+ // We don't want to overly constrain the predicates that may be written but we want to
377+ // catch cases where a default my never be applied such as `struct Foo<T: Copy = String>`.
378+ // Therefore we check if a predicate which contains a single type param
379+ // with a concrete default is WF with that default substituted.
399380 // For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`.
400381 //
401382 // First we build the defaulted substitution.
402383 let substs = ty:: subst:: Substs :: for_item ( fcx. tcx , def_id, |def, _| {
403384 // All regions are identity.
404385 fcx. tcx . mk_region ( ty:: ReEarlyBound ( def. to_early_bound_region_data ( ) ) )
405386 } , |def, _| {
406- if !is_our_default ( def) {
407- // We don't want to use non-defaulted params in a substitution, mark as err.
408- fcx. tcx . types . err
409- } else {
410- // Substitute with default.
411- fcx. tcx . type_of ( def. def_id )
387+ // If the param has a default,
388+ if is_our_default ( def) {
389+ let default_ty = fcx. tcx . type_of ( def. def_id ) ;
390+ // and it's not a dependent default
391+ if !default_ty. needs_subst ( ) {
392+ // then substitute with the default.
393+ return default_ty;
394+ }
412395 }
396+ // Mark unwanted params as err.
397+ fcx. tcx . types . err
413398 } ) ;
414399 // Now we build the substituted predicates.
415400 for & pred in predicates. predicates . iter ( ) {
401+ struct CountParams { params : FxHashSet < u32 > }
402+ impl < ' tcx > ty:: fold:: TypeVisitor < ' tcx > for CountParams {
403+ fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> bool {
404+ match t. sty {
405+ ty:: TyParam ( p) => {
406+ self . params . insert ( p. idx ) ;
407+ t. super_visit_with ( self )
408+ }
409+ _ => t. super_visit_with ( self )
410+ }
411+ }
412+ }
413+ let mut param_count = CountParams { params : FxHashSet ( ) } ;
414+ pred. visit_with ( & mut param_count) ;
416415 let substituted_pred = pred. subst ( fcx. tcx , substs) ;
417- // If there is a non-defaulted param in the predicate, don't check it .
418- if substituted_pred. references_error ( ) {
416+ // Don't check non-defaulted params, dependent defaults or preds with multiple params .
417+ if substituted_pred. references_error ( ) || param_count . params . len ( ) > 1 {
419418 continue ;
420419 }
421- // In trait defs, don't check `Self: Sized` when `Self` is the default.
422- if let ty:: Predicate :: Trait ( trait_pred) = substituted_pred {
423- // `skip_binder()` is ok, we're only inspecting for `has_self_ty()`.
424- let lhs_is_self = trait_pred. skip_binder ( ) . self_ty ( ) . has_self_ty ( ) ;
425- let pred_sized = Some ( trait_pred. def_id ( ) ) == fcx. tcx . lang_items ( ) . sized_trait ( ) ;
426- if is_trait && lhs_is_self && pred_sized {
427- continue ;
428- }
429- }
430420 // Avoid duplication of predicates that contain no parameters, for example.
431421 if !predicates. predicates . contains ( & substituted_pred) {
432422 substituted_predicates. push ( substituted_pred) ;
0 commit comments