diff options
| -rw-r--r-- | src/librustc_typeck/check/wfcheck.rs | 54 | ||||
| -rw-r--r-- | src/test/ui/type-check-defaults.stderr | 24 |
2 files changed, 56 insertions, 22 deletions
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index be42549df74..85fdcd417ff 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -364,15 +364,16 @@ fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } /// Checks where clauses and inline bounds that are declared on def_id. -fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, - fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, - span: Span, - def_id: DefId) { +fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>( + tcx: TyCtxt<'a, 'gcx, 'gcx>, + fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, + span: Span, + def_id: DefId, +) { use ty::subst::Subst; use rustc::ty::TypeFoldable; - let mut predicates = fcx.tcx.predicates_of(def_id); - let mut substituted_predicates = Vec::new(); + let predicates = fcx.tcx.predicates_of(def_id); let generics = tcx.generics_of(def_id); let is_our_default = |def: &ty::GenericParamDef| { @@ -433,7 +434,7 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, } }); // Now we build the substituted predicates. - for &pred in predicates.predicates.iter() { + let default_obligations = predicates.predicates.iter().flat_map(|&pred| { struct CountParams { params: FxHashSet<u32> } impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams { 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>, let substituted_pred = pred.subst(fcx.tcx, substs); // Don't check non-defaulted params, dependent defaults (including lifetimes) // or preds with multiple params. - if substituted_pred.references_error() || param_count.params.len() > 1 - || has_region { - continue; - } - // Avoid duplication of predicates that contain no parameters, for example. - if !predicates.predicates.contains(&substituted_pred) { - substituted_predicates.push(substituted_pred); + if { + substituted_pred.references_error() || param_count.params.len() > 1 + || has_region + } { + None + } else if predicates.predicates.contains(&substituted_pred) { + // Avoid duplication of predicates that contain no parameters, for example. + None + } else { + Some(substituted_pred) } - } + }).map(|pred| { + // convert each of those into an obligation. So if you have + // something like `struct Foo<T: Copy = String>`, we would + // take that predicate `T: Copy`, substitute to `String: Copy` + // (actually that happens in the previous `flat_map` call), + // and then try to prove it (in this case, we'll fail). + // + // Note the subtle difference from how we handle `predicates` + // below: there, we are not trying to prove those predicates + // to be *true* but merely *well-formed*. + let pred = fcx.normalize_associated_types_in(span, &pred); + let cause = traits::ObligationCause::new(span, fcx.body_id, traits::ItemObligation(def_id)); + traits::Obligation::new(cause, fcx.param_env, pred) + }); - predicates.predicates.extend(substituted_predicates); let predicates = predicates.instantiate_identity(fcx.tcx); let predicates = fcx.normalize_associated_types_in(span, &predicates); - let obligations = + debug!("check_where_clauses: predicates={:?}", predicates.predicates); + let wf_obligations = predicates.predicates .iter() .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>, p, span)); - for obligation in obligations { + for obligation in wf_obligations.chain(default_obligations) { + debug!("next obligation cause: {:?}", obligation.cause); fcx.register_predicate(obligation); } } diff --git a/src/test/ui/type-check-defaults.stderr b/src/test/ui/type-check-defaults.stderr index aa124110243..f6d7086679a 100644 --- a/src/test/ui/type-check-defaults.stderr +++ b/src/test/ui/type-check-defaults.stderr @@ -30,7 +30,11 @@ error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not sa LL | struct Bounds<T:Copy=String>(T); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String` | - = note: required by `std::marker::Copy` +note: required by `Bounds` + --> $DIR/type-check-defaults.rs:21:1 + | +LL | struct Bounds<T:Copy=String>(T); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied --> $DIR/type-check-defaults.rs:24:1 @@ -38,7 +42,11 @@ error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not sa LL | struct WhereClause<T=String>(T) where T: Copy; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String` | - = note: required by `std::marker::Copy` +note: required by `WhereClause` + --> $DIR/type-check-defaults.rs:24:1 + | +LL | struct WhereClause<T=String>(T) where T: Copy; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied --> $DIR/type-check-defaults.rs:27:1 @@ -46,7 +54,11 @@ error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not sa LL | trait TraitBound<T:Copy=String> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String` | - = note: required by `std::marker::Copy` +note: required by `TraitBound` + --> $DIR/type-check-defaults.rs:27:1 + | +LL | trait TraitBound<T:Copy=String> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/type-check-defaults.rs:31:1 @@ -68,7 +80,11 @@ LL | trait ProjectionPred<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u8` | = help: the trait `std::ops::Add<u8>` is not implemented for `i32` - = note: required by `std::ops::Add` +note: required by `ProjectionPred` + --> $DIR/type-check-defaults.rs:34:1 + | +LL | trait ProjectionPred<T:Iterator = IntoIter<i32>> where T::Item : Add<u8> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 7 previous errors |
