Stop masking overflow and propagate it out more aggressively; also improve error reporting to suggest to user how to fix.
This commit is contained in:
parent
3ee85d828e
commit
34812b891d
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 => {
|
||||
|
@ -42,6 +42,10 @@ fn is_send<T:Send>() { }
|
||||
|
||||
fn main() {
|
||||
is_send::<A>();
|
||||
//~^ 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
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ fn call_it<F:FnMut<(int,int),int>>(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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user