Make default error reporting deterministic
This commit is contained in:
parent
d732f7323b
commit
9da04b2bd1
src
librustc_typeck
test/compile-fail
@ -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`
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user