@@ -278,7 +278,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
278
278
fn check_trait ( & mut self , item : & hir:: Item ) {
279
279
let trait_def_id = self . tcx . hir . local_def_id ( item. id ) ;
280
280
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) ;
282
282
vec ! [ ]
283
283
} ) ;
284
284
}
@@ -354,23 +354,6 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
354
354
fcx : & FnCtxt < ' fcx , ' gcx , ' tcx > ,
355
355
span : Span ,
356
356
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
- {
374
357
use ty:: subst:: Subst ;
375
358
use rustc:: ty:: TypeFoldable ;
376
359
@@ -390,43 +373,50 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
390
373
}
391
374
392
375
// 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.
399
380
// For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`.
400
381
//
401
382
// First we build the defaulted substitution.
402
383
let substs = ty:: subst:: Substs :: for_item ( fcx. tcx , def_id, |def, _| {
403
384
// All regions are identity.
404
385
fcx. tcx . mk_region ( ty:: ReEarlyBound ( def. to_early_bound_region_data ( ) ) )
405
386
} , |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
+ }
412
395
}
396
+ // Mark unwanted params as err.
397
+ fcx. tcx . types . err
413
398
} ) ;
414
399
// Now we build the substituted predicates.
415
400
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) ;
416
415
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 {
419
418
continue ;
420
419
}
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
- }
430
420
// Avoid duplication of predicates that contain no parameters, for example.
431
421
if !predicates. predicates . contains ( & substituted_pred) {
432
422
substituted_predicates. push ( substituted_pred) ;
0 commit comments