@@ -392,14 +392,13 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
392392 // Check that trait predicates are WF when params are substituted by their defaults.
393393 // We don't want to overly constrain the predicates that may be written but we
394394 // want to catch obviously wrong cases such as `struct Foo<T: Copy = String>`
395- // or cases that may cause backwards incompatibility such as a library going from
396- // `pub struct Foo<T>` to `pub struct Foo<T, U = i32>` where U: Trait<T>`
397- // which may break existing uses of Foo<T>.
398- // Therefore the check we do is: If if all params appearing in the LHS of the predicate
399- // have defaults then we verify that it is WF with all defaults substituted simultaneously.
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.
400399 // For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`.
401400 //
402- // First, we build the defaulted substitution.
401+ // First we build the defaulted substitution.
403402 let mut defaulted_params = Vec :: new ( ) ;
404403 let substs = ty:: subst:: Substs :: for_item ( fcx. tcx , def_id, |def, _| {
405404 // All regions are identity.
@@ -414,33 +413,35 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
414413 fcx. tcx . type_of ( def. def_id )
415414 }
416415 } ) ;
417- // In `trait Trait: Super`, checking `Self: Trait` or `Self: Super` is problematic.
418- // We avoid those by skipping any predicates in trait declarations that contain `Self`,
419- // which is excessive so we end up checking less than we could.
420- for pred in predicates. predicates . iter ( )
421- . filter_map ( ty:: Predicate :: as_poly_trait_predicate)
422- . filter ( |p| !( is_trait && p. has_self_ty ( ) ) ) {
423- let is_defaulted_param = |ty : ty:: Ty | match ty. sty {
424- ty:: TyParam ( p) => defaulted_params. contains ( & p. idx ) ,
425- _ => false
426- } ;
427- // If there is a non-defaulted param in the LHS, don't check the substituted predicate.
428- // `skip_binder()` is ok, we're only inspecting the type params.
429- if !pred. skip_binder ( ) . self_ty ( ) . walk ( ) . all ( is_defaulted_param) {
416+ let defaulted_params = & defaulted_params;
417+ // Now we build the substituted predicates.
418+ for & pred in predicates. predicates . iter ( ) {
419+ struct HasNonDefaulted < ' a > { defaulted_params : & ' a Vec < u32 > }
420+ impl < ' tcx , ' a > ty:: fold:: TypeVisitor < ' tcx > for HasNonDefaulted < ' a > {
421+ fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> bool {
422+ match t. sty {
423+ ty:: TyParam ( p) => !self . defaulted_params . contains ( & p. idx ) ,
424+ _ => t. super_visit_with ( self )
425+ }
426+ }
427+ }
428+ // If there is a non-defaulted param in the predicate, don't check it.
429+ if pred. visit_with ( & mut HasNonDefaulted { defaulted_params } ) {
430430 continue ;
431431 }
432432 let substituted_pred = pred. subst ( fcx. tcx , substs) ;
433- // `skip_binder()` is ok, we're only inspecting for `has_self_ty()`.
434- let substituted_lhs = substituted_pred. skip_binder ( ) . self_ty ( ) ;
435433 // In trait defs, don't check `Self: Sized` when `Self` is the default.
436- let pred_is_sized = Some ( pred. def_id ( ) ) == fcx. tcx . lang_items ( ) . sized_trait ( ) ;
437- if is_trait && substituted_lhs. has_self_ty ( ) && pred_is_sized {
438- continue ;
434+ if let ty:: Predicate :: Trait ( trait_pred) = substituted_pred {
435+ // `skip_binder()` is ok, we're only inspecting for `has_self_ty()`.
436+ let lhs_is_self = trait_pred. skip_binder ( ) . self_ty ( ) . has_self_ty ( ) ;
437+ let pred_sized = Some ( trait_pred. def_id ( ) ) == fcx. tcx . lang_items ( ) . sized_trait ( ) ;
438+ if is_trait && lhs_is_self && pred_sized {
439+ continue ;
440+ }
439441 }
440- let pred = ty:: Predicate :: Trait ( pred. subst ( fcx. tcx , substs) ) ;
441- // Avoid duplicates.
442- if !predicates. predicates . contains ( & pred) {
443- substituted_predicates. push ( pred) ;
442+ // Avoid duplication of predicates that contain no parameters, for example.
443+ if !predicates. predicates . contains ( & substituted_pred) {
444+ substituted_predicates. push ( substituted_pred) ;
444445 }
445446 }
446447
0 commit comments