Skip to content

Commit 01dcb3b

Browse files
jroeschJared Roesch
authored andcommitted
Refactor the default type parameter algorithm
The algorithm was not correctly detecting conflicts after moving defaults into TypeVariableValue. The updated algorithm correctly detects and reports conflicts with information about where the conflict occured and which items the defaults were introduced by. The span's for said items are not being correctly attached and still need to be patched.
1 parent d782e35 commit 01dcb3b

File tree

11 files changed

+198
-53
lines changed

11 files changed

+198
-53
lines changed

src/librustc/middle/infer/error_reporting.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -893,8 +893,8 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
893893
self.report_inference_failure(vo.clone());
894894
}
895895
self.give_suggestion(same_regions);
896-
for &(ref trace, terr) in trace_origins {
897-
self.report_and_explain_type_error(trace.clone(), &terr);
896+
for &(ref trace, ref terr) in trace_origins {
897+
self.report_and_explain_type_error(trace.clone(), terr);
898898
}
899899
}
900900

src/librustc/middle/infer/mod.rs

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ use syntax::codemap;
4040
use syntax::codemap::{Span, DUMMY_SP};
4141
use util::nodemap::{FnvHashMap, NodeMap};
4242

43+
use ast_map;
4344
use self::combine::CombineFields;
4445
use self::region_inference::{RegionVarBindings, RegionSnapshot};
4546
use self::error_reporting::ErrorReporting;
@@ -72,7 +73,7 @@ pub struct InferCtxt<'a, 'tcx: 'a> {
7273
// We instantiate UnificationTable with bounds<Ty> because the
7374
// types that might instantiate a general type variable have an
7475
// order, represented by its upper and lower bounds.
75-
type_variables: RefCell<type_variable::TypeVariableTable<'tcx>>,
76+
pub type_variables: RefCell<type_variable::TypeVariableTable<'tcx>>,
7677

7778
// Map from integral variable to the kind of integer it represents
7879
int_unification_table: RefCell<UnificationTable<ty::IntVid>>,
@@ -690,7 +691,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
690691
variables.extend(unbound_ty_vars);
691692
variables.extend(unbound_int_vars);
692693
variables.extend(unbound_float_vars);
693-
694+
694695
return variables;
695696
}
696697

@@ -1047,15 +1048,36 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
10471048
}
10481049

10491050
pub fn type_vars_for_defs(&self,
1051+
span: Span,
1052+
// substs: Substs,
10501053
defs: &[ty::TypeParameterDef<'tcx>])
10511054
-> Vec<ty::Ty<'tcx>> {
1055+
1056+
fn definition_span<'tcx>(tcx: &ty::ctxt<'tcx>, def_id: ast::DefId) -> Span {
1057+
let parent = tcx.map.get_parent(def_id.node);
1058+
debug!("definition_span def_id={:?} parent={:?} node={:?} parent_node={:?}",
1059+
def_id, parent, tcx.map.find(def_id.node), tcx.map.find(parent));
1060+
match tcx.map.find(parent) {
1061+
None => DUMMY_SP,
1062+
Some(ref node) => match *node {
1063+
ast_map::NodeItem(ref item) => item.span,
1064+
ast_map::NodeForeignItem(ref item) => item.span,
1065+
ast_map::NodeTraitItem(ref item) => item.span,
1066+
ast_map::NodeImplItem(ref item) => item.span,
1067+
_ => DUMMY_SP
1068+
}
1069+
}
1070+
}
1071+
10521072
let mut substs = Substs::empty();
10531073
let mut vars = Vec::with_capacity(defs.len());
10541074

10551075
for def in defs.iter() {
10561076
let default = def.default.map(|default| {
10571077
type_variable::Default {
1058-
ty: default
1078+
ty: default,
1079+
origin_span: span,
1080+
definition_span: definition_span(self.tcx, def.def_id)
10591081
}
10601082
});
10611083
//.subst(self.tcx, &substs)
@@ -1077,7 +1099,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
10771099
let mut type_params = subst::VecPerParamSpace::empty();
10781100

10791101
for space in subst::ParamSpace::all().iter() {
1080-
type_params.replace(*space, self.type_vars_for_defs(generics.types.get_slice(*space)))
1102+
type_params.replace(*space,
1103+
self.type_vars_for_defs(span, generics.types.get_slice(*space)))
10811104
}
10821105

10831106
let region_params =
@@ -1102,7 +1125,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
11021125
assert!(generics.regions.len(subst::FnSpace) == 0);
11031126

11041127
let type_parameter_defs = generics.types.get_slice(subst::TypeSpace);
1105-
let type_parameters = self.type_vars_for_defs(type_parameter_defs);
1128+
let type_parameters = self.type_vars_for_defs(span, type_parameter_defs);
11061129

11071130
let region_param_defs = generics.regions.get_slice(subst::TypeSpace);
11081131
let regions = self.region_vars_for_defs(span, region_param_defs);
@@ -1344,13 +1367,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
13441367

13451368
pub fn report_conflicting_default_types(&self,
13461369
span: Span,
1347-
expected: Ty<'tcx>,
1348-
actual: Ty<'tcx>) {
1370+
expected: type_variable::Default<'tcx>,
1371+
actual: type_variable::Default<'tcx>) {
13491372
let trace = TypeTrace {
13501373
origin: Misc(span),
13511374
values: Types(ty::expected_found {
1352-
expected: expected,
1353-
found: actual
1375+
expected: expected.ty,
1376+
found: actual.ty
13541377
})
13551378
};
13561379

src/librustc/middle/infer/type_variable.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@
1111
pub use self::RelationDir::*;
1212
use self::TypeVariableValue::*;
1313
use self::UndoEntry::*;
14-
1514
use middle::ty::{self, Ty};
15+
use syntax::codemap::Span;
16+
1617
use std::cmp::min;
1718
use std::marker::PhantomData;
1819
use std::mem;
@@ -38,9 +39,13 @@ enum TypeVariableValue<'tcx> {
3839

3940
// We will use this to store the required information to recapitulate what happened when
4041
// an error occurs.
41-
#[derive(Clone)]
42+
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
4243
pub struct Default<'tcx> {
43-
pub ty: Ty<'tcx>
44+
pub ty: Ty<'tcx>,
45+
/// The span where the default was incurred
46+
pub origin_span: Span,
47+
/// The definition that the default originates from
48+
pub definition_span: Span
4449
}
4550

4651
pub struct Snapshot {

src/librustc/middle/ty.rs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangIte
5454
use middle::region;
5555
use middle::resolve_lifetime;
5656
use middle::infer;
57+
use middle::infer::type_variable;
5758
use middle::pat_util;
5859
use middle::region::RegionMaps;
5960
use middle::stability;
@@ -2068,7 +2069,7 @@ pub enum TypeError<'tcx> {
20682069
ConvergenceMismatch(ExpectedFound<bool>),
20692070
ProjectionNameMismatched(ExpectedFound<ast::Name>),
20702071
ProjectionBoundsLength(ExpectedFound<usize>),
2071-
terr_ty_param_default_mismatch(expected_found<Ty<'tcx>>)
2072+
TyParamDefaultMismatch(ExpectedFound<Ty<'tcx>>)
20722073
}
20732074

20742075
/// Bounds suitable for an existentially quantified type parameter
@@ -5083,9 +5084,9 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
50835084
values.found)
50845085
},
50855086
terr_ty_param_default_mismatch(ref values) => {
5086-
write!(f, "conflicting type parameter defaults {} {}",
5087-
values.expected,
5088-
values.found)
5087+
write!(f, "conflicting type parameter defaults {} and {}",
5088+
values.expected.ty,
5089+
values.found.ty)
50895090
}
50905091
}
50915092
}
@@ -5405,7 +5406,7 @@ impl<'tcx> ctxt<'tcx> {
54055406
pub fn note_and_explain_type_err(&self, err: &TypeError<'tcx>, sp: Span) {
54065407
use self::TypeError::*;
54075408

5408-
match *err {
5409+
match err.clone() {
54095410
RegionsDoesNotOutlive(subregion, superregion) => {
54105411
self.note_and_explain_region("", subregion, "...");
54115412
self.note_and_explain_region("...does not necessarily outlive ",
@@ -5444,10 +5445,21 @@ impl<'tcx> ctxt<'tcx> {
54445445
using it as a trait object"));
54455446
}
54465447
},
5447-
terr_ty_param_default_mismatch(expected) => {
5448+
terr_ty_param_default_mismatch(values) => {
5449+
let expected = values.expected;
5450+
let found = values.found;
54485451
self.sess.span_note(sp,
5449-
&format!("found conflicting defaults {:?} {:?}",
5450-
expected.expected, expected.found))
5452+
&format!("conflicting type parameter defaults {} and {}",
5453+
expected.ty,
5454+
found.ty));
5455+
self.sess.span_note(expected.definition_span,
5456+
&format!("...a default was defined"));
5457+
self.sess.span_note(expected.origin_span,
5458+
&format!("...that was applied to an unconstrained type variable here"));
5459+
self.sess.span_note(found.definition_span,
5460+
&format!("...a second default was defined"));
5461+
self.sess.span_note(found.origin_span,
5462+
&format!("...that also applies to the same type variable here"));
54515463
}
54525464
_ => {}
54535465
}

src/librustc_typeck/astconv.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ pub trait AstConv<'tcx> {
111111
}
112112

113113
/// What type should we use when a type is omitted?
114-
fn ty_infer(&self, default: Option<Ty<'tcx>>, span: Span) -> Ty<'tcx>;
114+
fn ty_infer(&self, default: Option<ty::TypeParameterDef<'tcx>>, span: Span) -> Ty<'tcx>;
115115

116116
/// Projecting an associated type from a (potentially)
117117
/// higher-ranked trait reference is more complicated, because of
@@ -403,7 +403,7 @@ fn create_substs_for_ast_path<'tcx>(
403403
// they were optional (e.g. paths inside expressions).
404404
let mut type_substs = if param_mode == PathParamMode::Optional &&
405405
types_provided.is_empty() {
406-
ty_param_defs.iter().map(|p| this.ty_infer(p.default, span)).collect()
406+
ty_param_defs.iter().map(|p| this.ty_infer(Some(p.clone()), span)).collect()
407407
} else {
408408
types_provided
409409
};

src/librustc_typeck/check/method/confirm.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -315,11 +315,11 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
315315

316316
let method_types = {
317317
if num_supplied_types == 0 {
318-
self.fcx.infcx().type_vars_for_defs(method_types)
318+
self.fcx.infcx().type_vars_for_defs(self.span, method_types)
319319
} else if num_method_types == 0 {
320320
span_err!(self.tcx().sess, self.span, E0035,
321321
"does not take type parameters");
322-
self.fcx.infcx().type_vars_for_defs(method_types)
322+
self.fcx.infcx().type_vars_for_defs(self.span, method_types)
323323
} else if num_supplied_types != num_method_types {
324324
span_err!(self.tcx().sess, self.span, E0036,
325325
"incorrect number of type parameters given for this method");

src/librustc_typeck/check/method/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
176176
}
177177

178178
None => {
179-
fcx.inh.infcx.type_vars_for_defs(type_parameter_defs)
179+
fcx.inh.infcx.type_vars_for_defs(span, type_parameter_defs)
180180
}
181181
};
182182

src/librustc_typeck/check/method/probe.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1207,7 +1207,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
12071207
!method.generics.regions.is_empty_in(subst::FnSpace)
12081208
{
12091209
let method_types =
1210-
self.infcx().type_vars_for_defs(
1210+
self.infcx().type_vars_for_defs(self.span,
12111211
method.generics.types.get_slice(subst::FnSpace));
12121212

12131213
// In general, during probe we erase regions. See

0 commit comments

Comments
 (0)