Skip to content

Commit 7e88508

Browse files
committed
Refactor error handling around extraneous bounds
1 parent f8058c4 commit 7e88508

File tree

8 files changed

+87
-79
lines changed

8 files changed

+87
-79
lines changed

src/librustc/middle/traits/error_reporting.rs

Lines changed: 62 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -82,57 +82,71 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
8282
note_obligation_cause(infcx, obligation);
8383
}
8484
SelectionError::Unimplemented => {
85-
match obligation.predicate {
86-
ty::Predicate::Trait(ref trait_predicate) => {
87-
let trait_predicate =
88-
infcx.resolve_type_vars_if_possible(trait_predicate);
89-
if !trait_predicate.references_error() {
90-
let trait_ref = trait_predicate.to_poly_trait_ref();
91-
infcx.tcx.sess.span_err(
92-
obligation.cause.span,
93-
format!(
94-
"the trait `{}` is not implemented for the type `{}`",
95-
trait_ref.user_string(infcx.tcx),
96-
trait_ref.self_ty().user_string(infcx.tcx)).as_slice());
97-
}
98-
}
99-
100-
ty::Predicate::Equate(ref predicate) => {
101-
let predicate = infcx.resolve_type_vars_if_possible(predicate);
102-
let err = infcx.equality_predicate(obligation.cause.span,
103-
&predicate).unwrap_err();
85+
match &obligation.cause.code {
86+
&ObligationCauseCode::CompareImplMethodObligation => {
10487
infcx.tcx.sess.span_err(
10588
obligation.cause.span,
10689
format!(
107-
"the requirement `{}` is not satisfied (`{}`)",
108-
predicate.user_string(infcx.tcx),
109-
ty::type_err_to_str(infcx.tcx, &err)).as_slice());
90+
"the requirement `{}` appears on the impl \
91+
method but not on the corresponding trait method",
92+
obligation.predicate.user_string(infcx.tcx)).as_slice());
11093
}
94+
_ => {
95+
match obligation.predicate {
96+
ty::Predicate::Trait(ref trait_predicate) => {
97+
let trait_predicate =
98+
infcx.resolve_type_vars_if_possible(trait_predicate);
99+
if !trait_predicate.references_error() {
100+
let trait_ref = trait_predicate.to_poly_trait_ref();
101+
infcx.tcx.sess.span_err(
102+
obligation.cause.span,
103+
format!(
104+
"the trait `{}` is not implemented for the type `{}`",
105+
trait_ref.user_string(infcx.tcx),
106+
trait_ref.self_ty().user_string(infcx.tcx)).as_slice());
107+
}
108+
}
111109

112-
ty::Predicate::RegionOutlives(ref predicate) => {
113-
let predicate = infcx.resolve_type_vars_if_possible(predicate);
114-
let err = infcx.region_outlives_predicate(obligation.cause.span,
115-
&predicate).unwrap_err();
116-
infcx.tcx.sess.span_err(
117-
obligation.cause.span,
118-
format!(
119-
"the requirement `{}` is not satisfied (`{}`)",
120-
predicate.user_string(infcx.tcx),
121-
ty::type_err_to_str(infcx.tcx, &err)).as_slice());
122-
}
110+
ty::Predicate::Equate(ref predicate) => {
111+
let predicate = infcx.resolve_type_vars_if_possible(predicate);
112+
let err = infcx.equality_predicate(obligation.cause.span,
113+
&predicate).unwrap_err();
123114

124-
ty::Predicate::Projection(..) |
125-
ty::Predicate::TypeOutlives(..) => {
126-
let predicate =
127-
infcx.resolve_type_vars_if_possible(&obligation.predicate);
128-
infcx.tcx.sess.span_err(
129-
obligation.cause.span,
130-
format!(
131-
"the requirement `{}` is not satisfied",
132-
predicate.user_string(infcx.tcx)).as_slice());
115+
infcx.tcx.sess.span_err(
116+
obligation.cause.span,
117+
format!(
118+
"the requirement `{}` is not satisfied (`{}`)",
119+
predicate.user_string(infcx.tcx),
120+
ty::type_err_to_str(infcx.tcx, &err)).as_slice());
121+
}
122+
123+
ty::Predicate::RegionOutlives(ref predicate) => {
124+
let predicate = infcx.resolve_type_vars_if_possible(predicate);
125+
let err = infcx.region_outlives_predicate(obligation.cause.span,
126+
&predicate).unwrap_err();
127+
infcx.tcx.sess.span_err(
128+
obligation.cause.span,
129+
format!(
130+
"the requirement `{}` is not satisfied (`{}`)",
131+
predicate.user_string(infcx.tcx),
132+
ty::type_err_to_str(infcx.tcx, &err)).as_slice());
133+
}
134+
135+
ty::Predicate::Projection(..) |
136+
ty::Predicate::TypeOutlives(..) => {
137+
let predicate =
138+
infcx.resolve_type_vars_if_possible(&obligation.predicate);
139+
infcx.tcx.sess.span_err(
140+
obligation.cause.span,
141+
format!(
142+
"the requirement `{}` is not satisfied",
143+
predicate.user_string(infcx.tcx)).as_slice());
144+
}
145+
}
133146
}
134147
}
135148
}
149+
136150
OutputTypeParameterMismatch(ref expected_trait_ref, ref actual_trait_ref, ref e) => {
137151
let expected_trait_ref = infcx.resolve_type_vars_if_possible(&*expected_trait_ref);
138152
let actual_trait_ref = infcx.resolve_type_vars_if_possible(&*actual_trait_ref);
@@ -242,7 +256,7 @@ fn note_obligation_cause<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
242256
}
243257

244258
fn note_obligation_cause_code<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
245-
_predicate: &ty::Predicate<'tcx>,
259+
predicate: &ty::Predicate<'tcx>,
246260
cause_span: Span,
247261
cause_code: &ObligationCauseCode<'tcx>)
248262
{
@@ -329,6 +343,11 @@ fn note_obligation_cause_code<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
329343
let parent_predicate = parent_trait_ref.as_predicate();
330344
note_obligation_cause_code(infcx, &parent_predicate, cause_span, &*data.parent_code);
331345
}
346+
ObligationCauseCode::CompareImplMethodObligation => {
347+
span_note!(tcx.sess, cause_span,
348+
"the requirement `{}` appears on the impl method but not on the corresponding trait method",
349+
predicate.user_string(infcx.tcx));
350+
}
332351
}
333352
}
334353

src/librustc/middle/traits/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,12 @@ pub enum ObligationCauseCode<'tcx> {
121121
// static items must have `Sync` type
122122
SharedStatic,
123123

124+
124125
BuiltinDerivedObligation(DerivedObligationCause<'tcx>),
125126

126127
ImplDerivedObligation(DerivedObligationCause<'tcx>),
128+
129+
CompareImplMethodObligation,
127130
}
128131

129132
#[derive(Clone)]

src/librustc_typeck/check/compare_method.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -210,14 +210,17 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
210210

211211
let mut selcx = traits::SelectionContext::new(&infcx, &impl_param_env, tcx);
212212

213+
let normalize_cause =
214+
traits::ObligationCause::misc(impl_m_span, impl_m_body_id);
215+
213216
// Normalize the associated types in the impl_bounds.
214217
let traits::Normalized { value: impl_bounds, .. } =
215-
traits::normalize(&mut selcx, traits::ObligationCause::dummy(), &impl_bounds);
218+
traits::normalize(&mut selcx, normalize_cause.clone(), &impl_bounds);
216219

217220
// Normalize the associated types in the trait_boubnds.
218221
let trait_bounds = trait_m.generics.to_bounds(tcx, &trait_to_skol_substs);
219222
let traits::Normalized { value: trait_bounds, .. } =
220-
traits::normalize(&mut selcx, traits::ObligationCause::dummy(), &trait_bounds);
223+
traits::normalize(&mut selcx, normalize_cause, &trait_bounds);
221224

222225
// Obtain the predicate split predicate sets for each.
223226
let trait_pred = trait_bounds.predicates.split();
@@ -246,9 +249,15 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
246249
trait_param_env.caller_bounds.repr(tcx));
247250

248251
for predicate in impl_pred.fns.into_iter() {
252+
let cause = traits::ObligationCause {
253+
span: impl_m_span,
254+
body_id: impl_m_body_id,
255+
code: traits::ObligationCauseCode::CompareImplMethodObligation
256+
};
257+
249258
fulfillment_cx.register_predicate_obligation(
250259
&infcx,
251-
traits::Obligation::new(traits::ObligationCause::dummy(), predicate));
260+
traits::Obligation::new(cause, predicate));
252261
}
253262

254263
// Compute skolemized form of impl and trait method tys.

src/test/compile-fail/issue-14853.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ struct X { data: u32 }
2020

2121
impl Something for X {
2222
fn yay<T: Str>(_:Option<X>, thing: &[T]) {
23-
//~^ ERROR in method `yay`, type parameter 0 requires bound `Str`, which is not required
24-
23+
//~^ ERROR the requirement `T : Str` appears on the impl method but not on the corresponding trait method
2524
}
2625
}
2726

src/test/compile-fail/issue-2611-4.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ struct E {
2020
}
2121

2222
impl A for E {
23-
fn b<F: Sync, G>(_x: F) -> F { panic!() } //~ ERROR type parameter 0 requires `Sync`
23+
fn b<F: Sync, G>(_x: F) -> F { panic!() } //~ ERROR the requirement `F : core::kinds::Sync` appears on the impl method but not on the corresponding trait method
2424
}
2525

2626
fn main() {}

src/test/compile-fail/trait-bounds-impl-comparison-1.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,15 @@ trait Foo {
3232
impl Foo for int {
3333
// invalid bound for T, was defined as Eq in trait
3434
fn test_error1_fn<T: Ord>(&self) {}
35-
//~^ ERROR in method `test_error1_fn`, type parameter 0 requires bound `core::cmp::Ord`
35+
//~^ ERROR the requirement `T : core::cmp::Ord` appears on the impl method but not on the corresponding trait method
3636

3737
// invalid bound for T, was defined as Eq + Ord in trait
3838
fn test_error2_fn<T: Eq + B>(&self) {}
39-
//~^ ERROR in method `test_error2_fn`, type parameter 0 requires bound `B`
39+
//~^ ERROR the requirement `T : B` appears on the impl method but not on the corresponding trait method
4040

4141
// invalid bound for T, was defined as Eq + Ord in trait
4242
fn test_error3_fn<T: B + Eq>(&self) {}
43-
//~^ ERROR in method `test_error3_fn`, type parameter 0 requires bound `B`
43+
//~^ ERROR the requirement `T : B` appears on the impl method but not on the corresponding trait method
4444

4545
// multiple bounds, same order as in trait
4646
fn test3_fn<T: Ord + Eq>(&self) {}
@@ -50,16 +50,16 @@ impl Foo for int {
5050

5151
// parameters in impls must be equal or more general than in the defining trait
5252
fn test_error5_fn<T: B>(&self) {}
53-
//~^ ERROR in method `test_error5_fn`, type parameter 0 requires bound `B`
53+
//~^ ERROR the requirement `T : B` appears on the impl method but not on the corresponding trait method
5454

5555
// bound `std::cmp::Eq` not enforced by this implementation, but this is OK
5656
fn test6_fn<T: A>(&self) {}
5757

5858
fn test_error7_fn<T: A + Eq>(&self) {}
59-
//~^ ERROR in method `test_error7_fn`, type parameter 0 requires bound `core::cmp::Eq`
59+
//~^ ERROR the requirement `T : core::cmp::Eq` appears on the impl method but not on the corresponding trait method
6060

6161
fn test_error8_fn<T: C>(&self) {}
62-
//~^ ERROR in method `test_error8_fn`, type parameter 0 requires bound `C`
62+
//~^ ERROR the requirement `T : C` appears on the impl method but not on the corresponding trait method
6363
}
6464

6565

@@ -71,8 +71,7 @@ trait Trait {
7171

7272
impl Trait for uint {
7373
fn method<G: Getter<uint>>() {}
74-
//~^ ERROR in method `method`, type parameter 0 requires bound `Getter<uint>`
74+
//~^ ERROR the requirement `G : Getter<uint>` appears on the impl method but not on the corresponding trait method
7575
}
7676

7777
fn main() {}
78-

src/test/compile-fail/trait-bounds-impl-comparison-2.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ trait IteratorUtil<A> {
2020

2121
impl<A, T: Iterator<A>> IteratorUtil<A> for T {
2222
fn zip<B, U: Iterator<B>>(self, other: U) -> ZipIterator<T, U> {
23-
//~^ ERROR in method `zip`, type parameter 1 requires bound `Iterator<B>`
23+
//~^ ERROR the requirement `U : Iterator<B>` appears on the impl method but not on the corresponding trait method
2424
ZipIterator{a: self, b: other}
2525
}
2626
}

src/test/run-pass/coerce-match.rs

Lines changed: 0 additions & 21 deletions
This file was deleted.

0 commit comments

Comments
 (0)