@@ -364,15 +364,16 @@ fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
364364}
365365
366366/// Checks where clauses and inline bounds that are declared on def_id.
367- fn check_where_clauses < ' a , ' gcx , ' fcx , ' tcx > ( tcx : TyCtxt < ' a , ' gcx , ' gcx > ,
368- fcx : & FnCtxt < ' fcx , ' gcx , ' tcx > ,
369- span : Span ,
370- def_id : DefId ) {
367+ fn check_where_clauses < ' a , ' gcx , ' fcx , ' tcx > (
368+ tcx : TyCtxt < ' a , ' gcx , ' gcx > ,
369+ fcx : & FnCtxt < ' fcx , ' gcx , ' tcx > ,
370+ span : Span ,
371+ def_id : DefId ,
372+ ) {
371373 use ty:: subst:: Subst ;
372374 use rustc:: ty:: TypeFoldable ;
373375
374- let mut predicates = fcx. tcx . predicates_of ( def_id) ;
375- let mut substituted_predicates = Vec :: new ( ) ;
376+ let predicates = fcx. tcx . predicates_of ( def_id) ;
376377
377378 let generics = tcx. generics_of ( def_id) ;
378379 let is_our_default = |def : & ty:: GenericParamDef | {
@@ -433,7 +434,7 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
433434 }
434435 } ) ;
435436 // Now we build the substituted predicates.
436- for & pred in predicates. predicates . iter ( ) {
437+ let default_obligations = predicates. predicates . iter ( ) . flat_map ( | & pred| {
437438 struct CountParams { params : FxHashSet < u32 > }
438439 impl < ' tcx > ty:: fold:: TypeVisitor < ' tcx > for CountParams {
439440 fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> bool {
@@ -455,21 +456,37 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
455456 let substituted_pred = pred. subst ( fcx. tcx , substs) ;
456457 // Don't check non-defaulted params, dependent defaults (including lifetimes)
457458 // or preds with multiple params.
458- if substituted_pred. references_error ( ) || param_count. params . len ( ) > 1
459- || has_region {
460- continue ;
461- }
462- // Avoid duplication of predicates that contain no parameters, for example.
463- if !predicates. predicates . contains ( & substituted_pred) {
464- substituted_predicates. push ( substituted_pred) ;
459+ if {
460+ substituted_pred. references_error ( ) || param_count. params . len ( ) > 1
461+ || has_region
462+ } {
463+ None
464+ } else if predicates. predicates . contains ( & substituted_pred) {
465+ // Avoid duplication of predicates that contain no parameters, for example.
466+ None
467+ } else {
468+ Some ( substituted_pred)
465469 }
466- }
470+ } ) . map ( |pred| {
471+ // convert each of those into an obligation. So if you have
472+ // something like `struct Foo<T: Copy = String>`, we would
473+ // take that predicate `T: Copy`, substitute to `String: Copy`
474+ // (actually that happens in the previous `flat_map` call),
475+ // and then try to prove it (in this case, we'll fail).
476+ //
477+ // Note the subtle difference from how we handle `predicates`
478+ // below: there, we are not trying to prove those predicates
479+ // to be *true* but merely *well-formed*.
480+ let pred = fcx. normalize_associated_types_in ( span, & pred) ;
481+ let cause = traits:: ObligationCause :: new ( span, fcx. body_id , traits:: ItemObligation ( def_id) ) ;
482+ traits:: Obligation :: new ( cause, fcx. param_env , pred)
483+ } ) ;
467484
468- predicates. predicates . extend ( substituted_predicates) ;
469485 let predicates = predicates. instantiate_identity ( fcx. tcx ) ;
470486 let predicates = fcx. normalize_associated_types_in ( span, & predicates) ;
471487
472- let obligations =
488+ debug ! ( "check_where_clauses: predicates={:?}" , predicates. predicates) ;
489+ let wf_obligations =
473490 predicates. predicates
474491 . iter ( )
475492 . flat_map ( |p| ty:: wf:: predicate_obligations ( fcx,
@@ -478,7 +495,8 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
478495 p,
479496 span) ) ;
480497
481- for obligation in obligations {
498+ for obligation in wf_obligations. chain ( default_obligations) {
499+ debug ! ( "next obligation cause: {:?}" , obligation. cause) ;
482500 fcx. register_predicate ( obligation) ;
483501 }
484502}
0 commit comments