Make default error reporting deterministic

This commit is contained in:
Jared Roesch 2015-07-21 14:52:21 -07:00 committed by Jared Roesch
parent d732f7323b
commit 9da04b2bd1
4 changed files with 35 additions and 10 deletions

@ -1800,6 +1800,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// We wrap this in a transaction for error reporting, if we detect a conflict
// we will rollback the inference context to its prior state so we can probe
// for conflicts and correctly report them.
let _ = self.infcx().commit_if_ok(|_: &infer::CombinedSnapshot| {
for ty in &unbound_tyvars {
if self.infcx().type_var_diverges(ty) {
@ -1849,10 +1851,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
def_id: local_def(0) // what do I put here?
});
// This is to ensure that we elimnate any non-determinism from the error
// reporting by fixing an order, it doesn't matter what order we choose
// just that it is consistent.
let (first_default, second_default) =
if default.def_id < conflicting_default.def_id {
(default, conflicting_default)
} else {
(conflicting_default, default)
};
self.infcx().report_conflicting_default_types(
conflicting_default.origin_span,
conflicting_default,
default)
first_default.origin_span,
first_default,
second_default)
}
}
}

@ -1930,7 +1930,6 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
index: index,
name: param.ident.name,
def_id: local_def(param.id),
// what do I return? should this be an option as well
default_def_id: local_def(parent),
default: default,
object_lifetime_default: object_lifetime_default,

@ -12,12 +12,19 @@ use std::fmt::Debug;
// Example from the RFC
fn foo<F:Default=usize>() -> F { F::default() }
//~^ NOTE: a default was defined here...
fn bar<B:Debug=isize>(b: B) { println!("{:?}", b); }
//~^ NOTE: a second default was defined here...
fn main() {
// Here, F is instantiated with $0=uint
let x = foo();
//~^ ERROR: mismatched types
//~| NOTE: conflicting type parameter defaults `usize` and `isize`
//~| NOTE: ...that was applied to an unconstrained type variable here
// Here, B is instantiated with $1=uint, and constraint $0 <: $1 is added.
bar(x);
//~^ NOTE: ...that also applies to the same type variable here
}

@ -7,14 +7,20 @@
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
//aux-build:default_ty_param_cross_crate_crate.rs
extern crate default_param_test;
use std::fmt::Debug;
use std::collections::HashMap;
use default_param_test::{Foo, bleh};
fn foo<R=()>(x: HashMap<i32, i32, R>) -> HashMap<i32, i32, R> { x }
fn bar<R=char>(x: HashMap<i32, i32, R>) {}
fn meh<X, B=bool>(x: Foo<X, B>) {}
//~^ NOTE: a default was defined here...
fn main() {
let x: HashMap<i32, i32, _> = foo(panic!());
bar(x);
let foo = bleh();
//~^ NOTE: ...that also applies to the same type variable here
meh(foo);
//~^ ERROR: mismatched types:
//~| NOTE: conflicting type parameter defaults `bool` and `char`
}