@@ -392,14 +392,13 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
392
392
// Check that trait predicates are WF when params are substituted by their defaults.
393
393
// We don't want to overly constrain the predicates that may be written but we
394
394
// 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.
400
399
// For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`.
401
400
//
402
- // First, we build the defaulted substitution.
401
+ // First we build the defaulted substitution.
403
402
let mut defaulted_params = Vec :: new ( ) ;
404
403
let substs = ty:: subst:: Substs :: for_item ( fcx. tcx , def_id, |def, _| {
405
404
// All regions are identity.
@@ -414,33 +413,35 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
414
413
fcx. tcx . type_of ( def. def_id )
415
414
}
416
415
} ) ;
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 } ) {
430
430
continue ;
431
431
}
432
432
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 ( ) ;
435
433
// 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
+ }
439
441
}
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) ;
444
445
}
445
446
}
446
447
0 commit comments