diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 16860e43f08fb..0e106227f9eb2 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -155,10 +155,10 @@ enum BuiltinBoundConditions<'tcx> { } #[deriving(Show)] -enum EvaluationResult { +enum EvaluationResult<'tcx> { EvaluatedToOk, - EvaluatedToErr, EvaluatedToAmbig, + EvaluatedToErr(SelectionError<'tcx>), } impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { @@ -272,7 +272,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { bound: ty::BuiltinBound, previous_stack: &ObligationStack<'o, 'tcx>, ty: Ty<'tcx>) - -> EvaluationResult + -> EvaluationResult<'tcx> { let obligation = util::obligation_for_builtin_bound( @@ -295,7 +295,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn evaluate_obligation_recursively<'o>(&mut self, previous_stack: Option<&ObligationStack<'o, 'tcx>>, obligation: &Obligation<'tcx>) - -> EvaluationResult + -> EvaluationResult<'tcx> { debug!("evaluate_obligation_recursively({})", obligation.repr(self.tcx())); @@ -310,7 +310,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn evaluate_stack<'o>(&mut self, stack: &ObligationStack<'o, 'tcx>) - -> EvaluationResult + -> EvaluationResult<'tcx> { // In intercrate mode, whenever any of the types are unbound, // there can always be an impl. Even if there are no impls in @@ -381,7 +381,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match self.candidate_from_obligation(stack) { Ok(Some(c)) => self.winnow_candidate(stack, &c), Ok(None) => EvaluatedToAmbig, - Err(_) => EvaluatedToErr, + Err(e) => EvaluatedToErr(e), } } @@ -812,14 +812,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn winnow_candidate<'o>(&mut self, stack: &ObligationStack<'o, 'tcx>, candidate: &Candidate<'tcx>) - -> EvaluationResult + -> EvaluationResult<'tcx> { debug!("winnow_candidate: candidate={}", candidate.repr(self.tcx())); self.infcx.probe(|| { let candidate = (*candidate).clone(); match self.confirm_candidate(stack.obligation, candidate) { Ok(selection) => self.winnow_selection(Some(stack), selection), - Err(_) => EvaluatedToErr, + Err(error) => EvaluatedToErr(error), } }) } @@ -827,12 +827,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn winnow_selection<'o>(&mut self, stack: Option<&ObligationStack<'o, 'tcx>>, selection: Selection<'tcx>) - -> EvaluationResult + -> EvaluationResult<'tcx> { let mut result = EvaluatedToOk; for obligation in selection.iter_nested() { match self.evaluate_obligation_recursively(stack, obligation) { - EvaluatedToErr => { return EvaluatedToErr; } + EvaluatedToErr(e) => { return EvaluatedToErr(e); } EvaluatedToAmbig => { result = EvaluatedToAmbig; } EvaluatedToOk => { } } @@ -1847,11 +1847,18 @@ impl<'o, 'tcx> Repr<'tcx> for ObligationStack<'o, 'tcx> { } } -impl EvaluationResult { +impl<'tcx> EvaluationResult<'tcx> { fn may_apply(&self) -> bool { match *self { - EvaluatedToOk | EvaluatedToAmbig => true, - EvaluatedToErr => false, + EvaluatedToOk | + EvaluatedToAmbig | + EvaluatedToErr(Overflow) | + EvaluatedToErr(OutputTypeParameterMismatch(..)) => { + true + } + EvaluatedToErr(Unimplemented) => { + false + } } } } diff --git a/src/librustc_typeck/check/vtable.rs b/src/librustc_typeck/check/vtable.rs index b9f7eb3f271b7..80363055a4bf0 100644 --- a/src/librustc_typeck/check/vtable.rs +++ b/src/librustc_typeck/check/vtable.rs @@ -366,6 +366,15 @@ pub fn report_selection_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, "overflow evaluating the trait `{}` for the type `{}`", trait_ref.user_string(fcx.tcx()), self_ty.user_string(fcx.tcx())).as_slice()); + + let current_limit = fcx.tcx().sess.recursion_limit.get(); + let suggested_limit = current_limit * 2; + fcx.tcx().sess.span_note( + obligation.cause.span, + format!( + "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate", + suggested_limit)[]); + note_obligation_cause(fcx, obligation); } Unimplemented => { diff --git a/src/test/compile-fail/recursion_limit.rs b/src/test/compile-fail/recursion_limit.rs index 35713f7cfa2bf..17afb168a9839 100644 --- a/src/test/compile-fail/recursion_limit.rs +++ b/src/test/compile-fail/recursion_limit.rs @@ -42,6 +42,10 @@ fn is_send() { } fn main() { is_send::(); - //~^ ERROR not implemented - //~^^ ERROR not implemented + //~^ ERROR overflow evaluating + //~^^ NOTE consider adding a `#![recursion_limit="20"]` attribute to your crate + //~^^^ NOTE must be implemented + //~^^^^ ERROR overflow evaluating + //~^^^^^ NOTE consider adding a `#![recursion_limit="20"]` attribute to your crate + //~^^^^^^ NOTE must be implemented } diff --git a/src/test/compile-fail/unboxed-closures-type-mismatch.rs b/src/test/compile-fail/unboxed-closures-type-mismatch.rs index c60a99ca0dfc0..b3528f7abe719 100644 --- a/src/test/compile-fail/unboxed-closures-type-mismatch.rs +++ b/src/test/compile-fail/unboxed-closures-type-mismatch.rs @@ -14,6 +14,6 @@ use std::ops::FnMut; pub fn main() { let mut f = |&mut: x: int, y: int| -> int { x + y }; - let z = f.call_mut((1u, 2)); //~ ERROR not implemented + let z = f.call_mut((1u, 2)); //~ ERROR type mismatch println!("{}", z); } diff --git a/src/test/compile-fail/unboxed-closures-vtable-mismatch.rs b/src/test/compile-fail/unboxed-closures-vtable-mismatch.rs index 5a22490b6d616..a96bde7cca4cd 100644 --- a/src/test/compile-fail/unboxed-closures-vtable-mismatch.rs +++ b/src/test/compile-fail/unboxed-closures-vtable-mismatch.rs @@ -18,7 +18,7 @@ fn call_it>(y: int, mut f: F) -> int { pub fn main() { let f = |&mut: x: uint, y: int| -> int { (x as int) + y }; - let z = call_it(3, f); //~ ERROR not implemented + let z = call_it(3, f); //~ ERROR type mismatch println!("{}", z); }