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).
This commit is contained in:
parent
896cb36eca
commit
6a66b32270
13 changed files with 571 additions and 574 deletions
|
|
@ -19,7 +19,7 @@ use util::ppaux::Repr;
|
|||
|
||||
use std::fmt;
|
||||
use std::slice::Iter;
|
||||
use std::vec::Vec;
|
||||
use std::vec::{Vec, IntoIter};
|
||||
use syntax::codemap::{Span, DUMMY_SP};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -397,6 +397,10 @@ impl<T> VecPerParamSpace<T> {
|
|||
self.content.iter()
|
||||
}
|
||||
|
||||
pub fn into_iter(self) -> IntoIter<T> {
|
||||
self.content.into_iter()
|
||||
}
|
||||
|
||||
pub fn iter_enumerated<'a>(&'a self) -> EnumeratedItems<'a,T> {
|
||||
EnumeratedItems::new(self)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -161,66 +161,80 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
|
|||
|
||||
note_obligation_cause(infcx, obligation);
|
||||
}
|
||||
|
||||
SelectionError::Unimplemented => {
|
||||
match obligation.predicate {
|
||||
ty::Predicate::Trait(ref trait_predicate) => {
|
||||
let trait_predicate =
|
||||
infcx.resolve_type_vars_if_possible(trait_predicate);
|
||||
if !trait_predicate.references_error() {
|
||||
let trait_ref = trait_predicate.to_poly_trait_ref();
|
||||
infcx.tcx.sess.span_err(
|
||||
obligation.cause.span,
|
||||
format!(
|
||||
"the trait `{}` is not implemented for the type `{}`",
|
||||
trait_ref.user_string(infcx.tcx),
|
||||
trait_ref.self_ty().user_string(infcx.tcx)).as_slice());
|
||||
// Check if it has a custom "#[rustc_on_unimplemented]" error message,
|
||||
// report with that message if it does
|
||||
let custom_note = report_on_unimplemented(infcx, &*trait_ref.0,
|
||||
obligation.cause.span);
|
||||
if let Some(s) = custom_note {
|
||||
infcx.tcx.sess.span_note(obligation.cause.span,
|
||||
s.as_slice());
|
||||
match &obligation.cause.code {
|
||||
&ObligationCauseCode::CompareImplMethodObligation => {
|
||||
infcx.tcx.sess.span_err(
|
||||
obligation.cause.span,
|
||||
format!(
|
||||
"the requirement `{}` appears on the impl \
|
||||
method but not on the corresponding trait method",
|
||||
obligation.predicate.user_string(infcx.tcx)).as_slice());
|
||||
}
|
||||
_ => {
|
||||
match obligation.predicate {
|
||||
ty::Predicate::Trait(ref trait_predicate) => {
|
||||
let trait_predicate =
|
||||
infcx.resolve_type_vars_if_possible(trait_predicate);
|
||||
|
||||
if !trait_predicate.references_error() {
|
||||
let trait_ref = trait_predicate.to_poly_trait_ref();
|
||||
infcx.tcx.sess.span_err(
|
||||
obligation.cause.span,
|
||||
format!(
|
||||
"the trait `{}` is not implemented for the type `{}`",
|
||||
trait_ref.user_string(infcx.tcx),
|
||||
trait_ref.self_ty().user_string(infcx.tcx)).as_slice());
|
||||
// Check if it has a custom "#[rustc_on_unimplemented]"
|
||||
// error message, report with that message if it does
|
||||
let custom_note = report_on_unimplemented(infcx, &*trait_ref.0,
|
||||
obligation.cause.span);
|
||||
if let Some(s) = custom_note {
|
||||
infcx.tcx.sess.span_note(obligation.cause.span,
|
||||
s.as_slice());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ty::Predicate::Equate(ref predicate) => {
|
||||
let predicate = infcx.resolve_type_vars_if_possible(predicate);
|
||||
let err = infcx.equality_predicate(obligation.cause.span,
|
||||
&predicate).unwrap_err();
|
||||
infcx.tcx.sess.span_err(
|
||||
obligation.cause.span,
|
||||
format!(
|
||||
"the requirement `{}` is not satisfied (`{}`)",
|
||||
predicate.user_string(infcx.tcx),
|
||||
ty::type_err_to_str(infcx.tcx, &err)).as_slice());
|
||||
}
|
||||
|
||||
ty::Predicate::RegionOutlives(ref predicate) => {
|
||||
let predicate = infcx.resolve_type_vars_if_possible(predicate);
|
||||
let err = infcx.region_outlives_predicate(obligation.cause.span,
|
||||
&predicate).unwrap_err();
|
||||
infcx.tcx.sess.span_err(
|
||||
obligation.cause.span,
|
||||
format!(
|
||||
"the requirement `{}` is not satisfied (`{}`)",
|
||||
predicate.user_string(infcx.tcx),
|
||||
ty::type_err_to_str(infcx.tcx, &err)).as_slice());
|
||||
}
|
||||
|
||||
ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
|
||||
let predicate =
|
||||
infcx.resolve_type_vars_if_possible(&obligation.predicate);
|
||||
infcx.tcx.sess.span_err(
|
||||
obligation.cause.span,
|
||||
format!(
|
||||
"the requirement `{}` is not satisfied",
|
||||
predicate.user_string(infcx.tcx)).as_slice());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ty::Predicate::Equate(ref predicate) => {
|
||||
let predicate = infcx.resolve_type_vars_if_possible(predicate);
|
||||
let err = infcx.equality_predicate(obligation.cause.span,
|
||||
&predicate).unwrap_err();
|
||||
infcx.tcx.sess.span_err(
|
||||
obligation.cause.span,
|
||||
format!(
|
||||
"the requirement `{}` is not satisfied (`{}`)",
|
||||
predicate.user_string(infcx.tcx),
|
||||
ty::type_err_to_str(infcx.tcx, &err)).as_slice());
|
||||
}
|
||||
|
||||
ty::Predicate::RegionOutlives(ref predicate) => {
|
||||
let predicate = infcx.resolve_type_vars_if_possible(predicate);
|
||||
let err = infcx.region_outlives_predicate(obligation.cause.span,
|
||||
&predicate).unwrap_err();
|
||||
infcx.tcx.sess.span_err(
|
||||
obligation.cause.span,
|
||||
format!(
|
||||
"the requirement `{}` is not satisfied (`{}`)",
|
||||
predicate.user_string(infcx.tcx),
|
||||
ty::type_err_to_str(infcx.tcx, &err)).as_slice());
|
||||
}
|
||||
|
||||
ty::Predicate::Projection(..) |
|
||||
ty::Predicate::TypeOutlives(..) => {
|
||||
let predicate =
|
||||
infcx.resolve_type_vars_if_possible(&obligation.predicate);
|
||||
infcx.tcx.sess.span_err(
|
||||
obligation.cause.span,
|
||||
format!(
|
||||
"the requirement `{}` is not satisfied",
|
||||
predicate.user_string(infcx.tcx)).as_slice());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OutputTypeParameterMismatch(ref expected_trait_ref, ref actual_trait_ref, ref e) => {
|
||||
let expected_trait_ref = infcx.resolve_type_vars_if_possible(&*expected_trait_ref);
|
||||
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>,
|
|||
obligation.cause.span,
|
||||
format!(
|
||||
"type mismatch: the type `{}` implements the trait `{}`, \
|
||||
but the trait `{}` is required ({})",
|
||||
but the trait `{}` is required ({})",
|
||||
expected_trait_ref.self_ty().user_string(infcx.tcx),
|
||||
expected_trait_ref.user_string(infcx.tcx),
|
||||
actual_trait_ref.user_string(infcx.tcx),
|
||||
ty::type_err_to_str(infcx.tcx, e)).as_slice());
|
||||
note_obligation_cause(infcx, obligation);
|
||||
note_obligation_cause(infcx, obligation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -330,7 +344,7 @@ fn note_obligation_cause<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
|
|||
}
|
||||
|
||||
fn note_obligation_cause_code<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
|
||||
_predicate: &ty::Predicate<'tcx>,
|
||||
predicate: &ty::Predicate<'tcx>,
|
||||
cause_span: Span,
|
||||
cause_code: &ObligationCauseCode<'tcx>)
|
||||
{
|
||||
|
|
@ -417,6 +431,12 @@ fn note_obligation_cause_code<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
|
|||
let parent_predicate = parent_trait_ref.as_predicate();
|
||||
note_obligation_cause_code(infcx, &parent_predicate, cause_span, &*data.parent_code);
|
||||
}
|
||||
ObligationCauseCode::CompareImplMethodObligation => {
|
||||
span_note!(tcx.sess, cause_span,
|
||||
"the requirement `{}` appears on the impl method\
|
||||
but not on the corresponding trait method",
|
||||
predicate.user_string(infcx.tcx));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -121,9 +121,12 @@ pub enum ObligationCauseCode<'tcx> {
|
|||
// static items must have `Sync` type
|
||||
SharedStatic,
|
||||
|
||||
|
||||
BuiltinDerivedObligation(DerivedObligationCause<'tcx>),
|
||||
|
||||
ImplDerivedObligation(DerivedObligationCause<'tcx>),
|
||||
|
||||
CompareImplMethodObligation,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
|
|
|||
|
|
@ -7341,3 +7341,15 @@ impl<'tcx> Repr<'tcx> for field<'tcx> {
|
|||
self.mt.repr(tcx))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Repr<'tcx> for ParameterEnvironment<'a, 'tcx> {
|
||||
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
|
||||
format!("ParameterEnvironment(\
|
||||
free_substs={}, \
|
||||
implicit_region_bound={}, \
|
||||
caller_bounds={})",
|
||||
self.free_substs.repr(tcx),
|
||||
self.implicit_region_bound.repr(tcx),
|
||||
self.caller_bounds.repr(tcx))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -564,6 +564,18 @@ impl<'tcx> TypeFoldable<'tcx> for ty::UnboxedClosureUpvar<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> TypeFoldable<'tcx> for ty::ParameterEnvironment<'a, 'tcx> where 'tcx: 'a {
|
||||
fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ParameterEnvironment<'a, 'tcx> {
|
||||
ty::ParameterEnvironment {
|
||||
tcx: self.tcx,
|
||||
free_substs: self.free_substs.fold_with(folder),
|
||||
implicit_region_bound: self.implicit_region_bound.fold_with(folder),
|
||||
caller_bounds: self.caller_bounds.fold_with(folder),
|
||||
selection_cache: traits::SelectionCache::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// "super" routines: these are the default implementations for TypeFolder.
|
||||
//
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue