@@ -185,10 +185,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
185
185
reject_shadowing_type_parameters ( fcx. tcx , item. def_id ) ;
186
186
let sig = fcx. tcx . fn_sig ( item. def_id ) ;
187
187
let sig = fcx. normalize_associated_types_in ( span, & sig) ;
188
- let predicates = fcx. tcx . predicates_of ( item. def_id )
189
- . instantiate_identity ( fcx. tcx ) ;
190
- let predicates = fcx. normalize_associated_types_in ( span, & predicates) ;
191
- this. check_fn_or_method ( fcx, span, sig, & predicates,
188
+ this. check_fn_or_method ( fcx, span, sig,
192
189
item. def_id , & mut implied_bounds) ;
193
190
let sig_if_method = sig_if_method. expect ( "bad signature for method" ) ;
194
191
this. check_method_receiver ( fcx, sig_if_method, & item, self_ty) ;
@@ -272,20 +269,16 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
272
269
}
273
270
}
274
271
275
- let predicates = fcx. tcx . predicates_of ( def_id) . instantiate_identity ( fcx. tcx ) ;
276
- let predicates = fcx. normalize_associated_types_in ( item. span , & predicates) ;
277
- this. check_where_clauses ( fcx, item. span , & predicates) ;
272
+ self . check_where_clauses ( fcx, item. span , def_id) ;
278
273
279
274
vec ! [ ] // no implied bounds in a struct def'n
280
275
} ) ;
281
276
}
282
277
283
278
fn check_trait ( & mut self , item : & hir:: Item ) {
284
279
let trait_def_id = self . tcx . hir . local_def_id ( item. id ) ;
285
- self . for_item ( item) . with_fcx ( |fcx, this| {
286
- let predicates = fcx. tcx . predicates_of ( trait_def_id) . instantiate_identity ( fcx. tcx ) ;
287
- let predicates = fcx. normalize_associated_types_in ( item. span , & predicates) ;
288
- this. check_where_clauses ( fcx, item. span , & predicates) ;
280
+ self . for_item ( item) . with_fcx ( |fcx, _| {
281
+ self . check_where_clauses ( fcx, item. span , trait_def_id) ;
289
282
vec ! [ ]
290
283
} ) ;
291
284
}
@@ -295,12 +288,8 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
295
288
let def_id = fcx. tcx . hir . local_def_id ( item. id ) ;
296
289
let sig = fcx. tcx . fn_sig ( def_id) ;
297
290
let sig = fcx. normalize_associated_types_in ( item. span , & sig) ;
298
-
299
- let predicates = fcx. tcx . predicates_of ( def_id) . instantiate_identity ( fcx. tcx ) ;
300
- let predicates = fcx. normalize_associated_types_in ( item. span , & predicates) ;
301
-
302
291
let mut implied_bounds = vec ! [ ] ;
303
- this. check_fn_or_method ( fcx, item. span , sig, & predicates ,
292
+ this. check_fn_or_method ( fcx, item. span , sig,
304
293
def_id, & mut implied_bounds) ;
305
294
implied_bounds
306
295
} )
@@ -354,19 +343,96 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
354
343
}
355
344
}
356
345
357
- let predicates = fcx. tcx . predicates_of ( item_def_id) . instantiate_identity ( fcx. tcx ) ;
358
- let predicates = fcx. normalize_associated_types_in ( item. span , & predicates) ;
359
- this. check_where_clauses ( fcx, item. span , & predicates) ;
346
+ this. check_where_clauses ( fcx, item. span , item_def_id) ;
360
347
361
348
fcx. impl_implied_bounds ( item_def_id, item. span )
362
349
} ) ;
363
350
}
364
351
352
+ /// Checks where clauses and inline bounds that are declared on def_id.
365
353
fn check_where_clauses < ' fcx , ' tcx > ( & mut self ,
366
354
fcx : & FnCtxt < ' fcx , ' gcx , ' tcx > ,
367
355
span : Span ,
368
- predicates : & ty:: InstantiatedPredicates < ' tcx > )
369
- {
356
+ def_id : DefId ) {
357
+ use ty:: subst:: Subst ;
358
+ use rustc:: ty:: TypeFoldable ;
359
+
360
+ let mut predicates = fcx. tcx . predicates_of ( def_id) ;
361
+ let mut substituted_predicates = Vec :: new ( ) ;
362
+
363
+ let generics = self . tcx . generics_of ( def_id) ;
364
+ let is_our_default = |def : & ty:: TypeParameterDef |
365
+ def. has_default && def. index >= generics. parent_count ( ) as u32 ;
366
+
367
+ // Check that concrete defaults are well-formed. See test `type-check-defaults.rs`.
368
+ // For example this forbids the declaration:
369
+ // struct Foo<T = Vec<[u32]>> { .. }
370
+ // Here the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold.
371
+ for d in generics. types . iter ( ) . cloned ( ) . filter ( is_our_default) . map ( |p| p. def_id ) {
372
+ let ty = fcx. tcx . type_of ( d) ;
373
+ // ignore dependent defaults -- that is, where the default of one type
374
+ // parameter includes another (e.g., <T, U = T>). In those cases, we can't
375
+ // be sure if it will error or not as user might always specify the other.
376
+ if !ty. needs_subst ( ) {
377
+ fcx. register_wf_obligation ( ty, fcx. tcx . def_span ( d) , self . code . clone ( ) ) ;
378
+ }
379
+ }
380
+
381
+ // Check that trait predicates are WF when params are substituted by their defaults.
382
+ // We don't want to overly constrain the predicates that may be written but we want to
383
+ // catch cases where a default my never be applied such as `struct Foo<T: Copy = String>`.
384
+ // Therefore we check if a predicate which contains a single type param
385
+ // with a concrete default is WF with that default substituted.
386
+ // For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`.
387
+ //
388
+ // First we build the defaulted substitution.
389
+ let substs = ty:: subst:: Substs :: for_item ( fcx. tcx , def_id, |def, _| {
390
+ // All regions are identity.
391
+ fcx. tcx . mk_region ( ty:: ReEarlyBound ( def. to_early_bound_region_data ( ) ) )
392
+ } , |def, _| {
393
+ // If the param has a default,
394
+ if is_our_default ( def) {
395
+ let default_ty = fcx. tcx . type_of ( def. def_id ) ;
396
+ // and it's not a dependent default
397
+ if !default_ty. needs_subst ( ) {
398
+ // then substitute with the default.
399
+ return default_ty;
400
+ }
401
+ }
402
+ // Mark unwanted params as err.
403
+ fcx. tcx . types . err
404
+ } ) ;
405
+ // Now we build the substituted predicates.
406
+ for & pred in predicates. predicates . iter ( ) {
407
+ struct CountParams { params : FxHashSet < u32 > }
408
+ impl < ' tcx > ty:: fold:: TypeVisitor < ' tcx > for CountParams {
409
+ fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> bool {
410
+ match t. sty {
411
+ ty:: TyParam ( p) => {
412
+ self . params . insert ( p. idx ) ;
413
+ t. super_visit_with ( self )
414
+ }
415
+ _ => t. super_visit_with ( self )
416
+ }
417
+ }
418
+ }
419
+ let mut param_count = CountParams { params : FxHashSet ( ) } ;
420
+ pred. visit_with ( & mut param_count) ;
421
+ let substituted_pred = pred. subst ( fcx. tcx , substs) ;
422
+ // Don't check non-defaulted params, dependent defaults or preds with multiple params.
423
+ if substituted_pred. references_error ( ) || param_count. params . len ( ) > 1 {
424
+ continue ;
425
+ }
426
+ // Avoid duplication of predicates that contain no parameters, for example.
427
+ if !predicates. predicates . contains ( & substituted_pred) {
428
+ substituted_predicates. push ( substituted_pred) ;
429
+ }
430
+ }
431
+
432
+ predicates. predicates . extend ( substituted_predicates) ;
433
+ let predicates = predicates. instantiate_identity ( fcx. tcx ) ;
434
+ let predicates = fcx. normalize_associated_types_in ( span, & predicates) ;
435
+
370
436
let obligations =
371
437
predicates. predicates
372
438
. iter ( )
@@ -385,7 +451,6 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
385
451
fcx : & FnCtxt < ' fcx , ' gcx , ' tcx > ,
386
452
span : Span ,
387
453
sig : ty:: PolyFnSig < ' tcx > ,
388
- predicates : & ty:: InstantiatedPredicates < ' tcx > ,
389
454
def_id : DefId ,
390
455
implied_bounds : & mut Vec < Ty < ' tcx > > )
391
456
{
@@ -402,7 +467,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
402
467
// FIXME(#25759) return types should not be implied bounds
403
468
implied_bounds. push ( sig. output ( ) ) ;
404
469
405
- self . check_where_clauses ( fcx, span, predicates ) ;
470
+ self . check_where_clauses ( fcx, span, def_id ) ;
406
471
}
407
472
408
473
fn check_method_receiver < ' fcx , ' tcx > ( & mut self ,
0 commit comments