diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index fd4cf6f28df..95e916f1a0d 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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) } } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index d31a29ecc0e..236a1e690e8 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -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, diff --git a/src/test/compile-fail/default_ty_param_conflict.rs b/src/test/compile-fail/default_ty_param_conflict.rs index 900945da113..42de545f9d0 100644 --- a/src/test/compile-fail/default_ty_param_conflict.rs +++ b/src/test/compile-fail/default_ty_param_conflict.rs @@ -12,12 +12,19 @@ use std::fmt::Debug; // Example from the RFC fn foo() -> F { F::default() } +//~^ NOTE: a default was defined here... + fn bar(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 } diff --git a/src/test/compile-fail/default_ty_param_conflict_cross_crate.rs b/src/test/compile-fail/default_ty_param_conflict_cross_crate.rs index bc79d3713e5..804a864e074 100644 --- a/src/test/compile-fail/default_ty_param_conflict_cross_crate.rs +++ b/src/test/compile-fail/default_ty_param_conflict_cross_crate.rs @@ -7,14 +7,20 @@ // , 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(x: HashMap) -> HashMap { x } -fn bar(x: HashMap) {} +fn meh(x: Foo) {} +//~^ NOTE: a default was defined here... fn main() { - let x: HashMap = 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` }