Skip to content

Commit 6a66b32

Browse files
committed
Refactor compare_impl_method to use all bounds
Refactor compare_impl_method into its own file. Modify the code to stop comparing individual parameter bounds. Instead we now use the predicates list attached to the trait and implementation generics. This ensures consistency even when bounds are declared in different places (i.e on a parameter vs. in a where clause).
1 parent 896cb36 commit 6a66b32

13 files changed

+567
-570
lines changed

src/librustc/middle/subst.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use util::ppaux::Repr;
1919

2020
use std::fmt;
2121
use std::slice::Iter;
22-
use std::vec::Vec;
22+
use std::vec::{Vec, IntoIter};
2323
use syntax::codemap::{Span, DUMMY_SP};
2424

2525
///////////////////////////////////////////////////////////////////////////
@@ -397,6 +397,10 @@ impl<T> VecPerParamSpace<T> {
397397
self.content.iter()
398398
}
399399

400+
pub fn into_iter(self) -> IntoIter<T> {
401+
self.content.into_iter()
402+
}
403+
400404
pub fn iter_enumerated<'a>(&'a self) -> EnumeratedItems<'a,T> {
401405
EnumeratedItems::new(self)
402406
}

src/librustc/middle/traits/error_reporting.rs

+73-53
Original file line numberDiff line numberDiff line change
@@ -161,66 +161,80 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
161161

162162
note_obligation_cause(infcx, obligation);
163163
}
164-
SelectionError::Unimplemented => {
165-
match obligation.predicate {
166-
ty::Predicate::Trait(ref trait_predicate) => {
167-
let trait_predicate =
168-
infcx.resolve_type_vars_if_possible(trait_predicate);
169-
if !trait_predicate.references_error() {
170-
let trait_ref = trait_predicate.to_poly_trait_ref();
171-
infcx.tcx.sess.span_err(
172-
obligation.cause.span,
173-
format!(
174-
"the trait `{}` is not implemented for the type `{}`",
175-
trait_ref.user_string(infcx.tcx),
176-
trait_ref.self_ty().user_string(infcx.tcx)).as_slice());
177-
// Check if it has a custom "#[rustc_on_unimplemented]" error message,
178-
// report with that message if it does
179-
let custom_note = report_on_unimplemented(infcx, &*trait_ref.0,
180-
obligation.cause.span);
181-
if let Some(s) = custom_note {
182-
infcx.tcx.sess.span_note(obligation.cause.span,
183-
s.as_slice());
184-
}
185-
}
186-
}
187164

188-
ty::Predicate::Equate(ref predicate) => {
189-
let predicate = infcx.resolve_type_vars_if_possible(predicate);
190-
let err = infcx.equality_predicate(obligation.cause.span,
191-
&predicate).unwrap_err();
165+
SelectionError::Unimplemented => {
166+
match &obligation.cause.code {
167+
&ObligationCauseCode::CompareImplMethodObligation => {
192168
infcx.tcx.sess.span_err(
193169
obligation.cause.span,
194170
format!(
195-
"the requirement `{}` is not satisfied (`{}`)",
196-
predicate.user_string(infcx.tcx),
197-
ty::type_err_to_str(infcx.tcx, &err)).as_slice());
171+
"the requirement `{}` appears on the impl \
172+
method but not on the corresponding trait method",
173+
obligation.predicate.user_string(infcx.tcx)).as_slice());
198174
}
175+
_ => {
176+
match obligation.predicate {
177+
ty::Predicate::Trait(ref trait_predicate) => {
178+
let trait_predicate =
179+
infcx.resolve_type_vars_if_possible(trait_predicate);
199180

200-
ty::Predicate::RegionOutlives(ref predicate) => {
201-
let predicate = infcx.resolve_type_vars_if_possible(predicate);
202-
let err = infcx.region_outlives_predicate(obligation.cause.span,
203-
&predicate).unwrap_err();
204-
infcx.tcx.sess.span_err(
205-
obligation.cause.span,
206-
format!(
207-
"the requirement `{}` is not satisfied (`{}`)",
208-
predicate.user_string(infcx.tcx),
209-
ty::type_err_to_str(infcx.tcx, &err)).as_slice());
210-
}
181+
if !trait_predicate.references_error() {
182+
let trait_ref = trait_predicate.to_poly_trait_ref();
183+
infcx.tcx.sess.span_err(
184+
obligation.cause.span,
185+
format!(
186+
"the trait `{}` is not implemented for the type `{}`",
187+
trait_ref.user_string(infcx.tcx),
188+
trait_ref.self_ty().user_string(infcx.tcx)).as_slice());
189+
// Check if it has a custom "#[rustc_on_unimplemented]"
190+
// error message, report with that message if it does
191+
let custom_note = report_on_unimplemented(infcx, &*trait_ref.0,
192+
obligation.cause.span);
193+
if let Some(s) = custom_note {
194+
infcx.tcx.sess.span_note(obligation.cause.span,
195+
s.as_slice());
196+
}
197+
}
198+
}
211199

212-
ty::Predicate::Projection(..) |
213-
ty::Predicate::TypeOutlives(..) => {
214-
let predicate =
215-
infcx.resolve_type_vars_if_possible(&obligation.predicate);
216-
infcx.tcx.sess.span_err(
217-
obligation.cause.span,
218-
format!(
219-
"the requirement `{}` is not satisfied",
220-
predicate.user_string(infcx.tcx)).as_slice());
200+
ty::Predicate::Equate(ref predicate) => {
201+
let predicate = infcx.resolve_type_vars_if_possible(predicate);
202+
let err = infcx.equality_predicate(obligation.cause.span,
203+
&predicate).unwrap_err();
204+
infcx.tcx.sess.span_err(
205+
obligation.cause.span,
206+
format!(
207+
"the requirement `{}` is not satisfied (`{}`)",
208+
predicate.user_string(infcx.tcx),
209+
ty::type_err_to_str(infcx.tcx, &err)).as_slice());
210+
}
211+
212+
ty::Predicate::RegionOutlives(ref predicate) => {
213+
let predicate = infcx.resolve_type_vars_if_possible(predicate);
214+
let err = infcx.region_outlives_predicate(obligation.cause.span,
215+
&predicate).unwrap_err();
216+
infcx.tcx.sess.span_err(
217+
obligation.cause.span,
218+
format!(
219+
"the requirement `{}` is not satisfied (`{}`)",
220+
predicate.user_string(infcx.tcx),
221+
ty::type_err_to_str(infcx.tcx, &err)).as_slice());
222+
}
223+
224+
ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
225+
let predicate =
226+
infcx.resolve_type_vars_if_possible(&obligation.predicate);
227+
infcx.tcx.sess.span_err(
228+
obligation.cause.span,
229+
format!(
230+
"the requirement `{}` is not satisfied",
231+
predicate.user_string(infcx.tcx)).as_slice());
232+
}
233+
}
221234
}
222235
}
223236
}
237+
224238
OutputTypeParameterMismatch(ref expected_trait_ref, ref actual_trait_ref, ref e) => {
225239
let expected_trait_ref = infcx.resolve_type_vars_if_possible(&*expected_trait_ref);
226240
let actual_trait_ref = infcx.resolve_type_vars_if_possible(&*actual_trait_ref);
@@ -229,12 +243,12 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
229243
obligation.cause.span,
230244
format!(
231245
"type mismatch: the type `{}` implements the trait `{}`, \
232-
but the trait `{}` is required ({})",
246+
but the trait `{}` is required ({})",
233247
expected_trait_ref.self_ty().user_string(infcx.tcx),
234248
expected_trait_ref.user_string(infcx.tcx),
235249
actual_trait_ref.user_string(infcx.tcx),
236250
ty::type_err_to_str(infcx.tcx, e)).as_slice());
237-
note_obligation_cause(infcx, obligation);
251+
note_obligation_cause(infcx, obligation);
238252
}
239253
}
240254
}
@@ -330,7 +344,7 @@ fn note_obligation_cause<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
330344
}
331345

332346
fn note_obligation_cause_code<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
333-
_predicate: &ty::Predicate<'tcx>,
347+
predicate: &ty::Predicate<'tcx>,
334348
cause_span: Span,
335349
cause_code: &ObligationCauseCode<'tcx>)
336350
{
@@ -417,6 +431,12 @@ fn note_obligation_cause_code<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
417431
let parent_predicate = parent_trait_ref.as_predicate();
418432
note_obligation_cause_code(infcx, &parent_predicate, cause_span, &*data.parent_code);
419433
}
434+
ObligationCauseCode::CompareImplMethodObligation => {
435+
span_note!(tcx.sess, cause_span,
436+
"the requirement `{}` appears on the impl method\
437+
but not on the corresponding trait method",
438+
predicate.user_string(infcx.tcx));
439+
}
420440
}
421441
}
422442

src/librustc/middle/traits/mod.rs

+3
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/middle/ty.rs

+12
Original file line numberDiff line numberDiff line change
@@ -7341,3 +7341,15 @@ impl<'tcx> Repr<'tcx> for field<'tcx> {
73417341
self.mt.repr(tcx))
73427342
}
73437343
}
7344+
7345+
impl<'a, 'tcx> Repr<'tcx> for ParameterEnvironment<'a, 'tcx> {
7346+
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
7347+
format!("ParameterEnvironment(\
7348+
free_substs={}, \
7349+
implicit_region_bound={}, \
7350+
caller_bounds={})",
7351+
self.free_substs.repr(tcx),
7352+
self.implicit_region_bound.repr(tcx),
7353+
self.caller_bounds.repr(tcx))
7354+
}
7355+
}

src/librustc/middle/ty_fold.rs

+12
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,18 @@ impl<'tcx> TypeFoldable<'tcx> for ty::UnboxedClosureUpvar<'tcx> {
564564
}
565565
}
566566

567+
impl<'a, 'tcx> TypeFoldable<'tcx> for ty::ParameterEnvironment<'a, 'tcx> where 'tcx: 'a {
568+
fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ParameterEnvironment<'a, 'tcx> {
569+
ty::ParameterEnvironment {
570+
tcx: self.tcx,
571+
free_substs: self.free_substs.fold_with(folder),
572+
implicit_region_bound: self.implicit_region_bound.fold_with(folder),
573+
caller_bounds: self.caller_bounds.fold_with(folder),
574+
selection_cache: traits::SelectionCache::new(),
575+
}
576+
}
577+
}
578+
567579
///////////////////////////////////////////////////////////////////////////
568580
// "super" routines: these are the default implementations for TypeFolder.
569581
//

0 commit comments

Comments
 (0)