Skip to content

Commit

Permalink
auto merge of #20290 : jroesch/rust/generalize-impl-bounds, r=nikomat…
Browse files Browse the repository at this point in the history
…sakis

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
  • Loading branch information
bors committed Jan 15, 2015
2 parents 896cb36 + 6a66b32 commit 451e134
Show file tree
Hide file tree
Showing 13 changed files with 567 additions and 570 deletions.
6 changes: 5 additions & 1 deletion src/librustc/middle/subst.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

///////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -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)
}
Expand Down
126 changes: 73 additions & 53 deletions src/librustc/middle/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
}
}

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();
SelectionError::Unimplemented => {
match &obligation.cause.code {
&ObligationCauseCode::CompareImplMethodObligation => {
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());
"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);

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());
}
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::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);
Expand All @@ -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);
}
}
}
Expand Down Expand Up @@ -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>)
{
Expand Down Expand Up @@ -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));
}
}
}

Expand Down
3 changes: 3 additions & 0 deletions src/librustc/middle/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,12 @@ pub enum ObligationCauseCode<'tcx> {
// static items must have `Sync` type
SharedStatic,


BuiltinDerivedObligation(DerivedObligationCause<'tcx>),

ImplDerivedObligation(DerivedObligationCause<'tcx>),

CompareImplMethodObligation,
}

#[derive(Clone)]
Expand Down
12 changes: 12 additions & 0 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
}
12 changes: 12 additions & 0 deletions src/librustc/middle/ty_fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
//
Expand Down
Loading

0 comments on commit 451e134

Please sign in to comment.