Skip to content

Commit 451e134

Browse files
committed
auto merge of #20290 : jroesch/rust/generalize-impl-bounds, r=nikomatsakis
This should fix both #20020 and #20107. This moves out the code into its own file. I have a couple concerns that can either be addressed in this PR or in a future one. - The error reporting for the fulfillment context should be span aware because currently it is attached to the top of the file which is less then desirable. - There is a failure in the test file: run-pass/issue-2611-3.rs, this seems like it should be a failure to me, but I am not sure. As a nit I'm not enthused about the file name, and am open to better suggestions. r? @nikomatsakis
2 parents 896cb36 + 6a66b32 commit 451e134

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)