Skip to content

Commit 1a0629f

Browse files
committed
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 5fc61c2 commit 1a0629f

File tree

11 files changed

+198
-53
lines changed

11 files changed

+198
-53
lines changed

src/librustc/middle/infer/error_reporting.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -894,8 +894,8 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
894894
self.report_inference_failure(vo.clone());
895895
}
896896
self.give_suggestion(same_regions);
897-
for &(ref trace, terr) in trace_origins {
898-
self.report_and_explain_type_error(trace.clone(), &terr);
897+
for &(ref trace, ref terr) in trace_origins {
898+
self.report_and_explain_type_error(trace.clone(), terr);
899899
}
900900
}
901901

src/librustc/middle/infer/mod.rs

+32-9
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>>,
@@ -693,7 +694,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
693694
variables.extend(unbound_ty_vars);
694695
variables.extend(unbound_int_vars);
695696
variables.extend(unbound_float_vars);
696-
697+
697698
return variables;
698699
}
699700

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

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

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

10801102
for space in subst::ParamSpace::all().iter() {
1081-
type_params.replace(*space, self.type_vars_for_defs(generics.types.get_slice(*space)))
1103+
type_params.replace(*space,
1104+
self.type_vars_for_defs(span, generics.types.get_slice(*space)))
10821105
}
10831106

10841107
let region_params =
@@ -1103,7 +1126,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
11031126
assert!(generics.regions.len(subst::FnSpace) == 0);
11041127

11051128
let type_parameter_defs = generics.types.get_slice(subst::TypeSpace);
1106-
let type_parameters = self.type_vars_for_defs(type_parameter_defs);
1129+
let type_parameters = self.type_vars_for_defs(span, type_parameter_defs);
11071130

11081131
let region_param_defs = generics.regions.get_slice(subst::TypeSpace);
11091132
let regions = self.region_vars_for_defs(span, region_param_defs);
@@ -1340,13 +1363,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
13401363

13411364
pub fn report_conflicting_default_types(&self,
13421365
span: Span,
1343-
expected: Ty<'tcx>,
1344-
actual: Ty<'tcx>) {
1366+
expected: type_variable::Default<'tcx>,
1367+
actual: type_variable::Default<'tcx>) {
13451368
let trace = TypeTrace {
13461369
origin: Misc(span),
13471370
values: Types(ty::expected_found {
1348-
expected: expected,
1349-
found: actual
1371+
expected: expected.ty,
1372+
found: actual.ty
13501373
})
13511374
};
13521375

src/librustc/middle/infer/type_variable.rs

+8-3
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

+20-8
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangIte
5353
use middle::region;
5454
use middle::resolve_lifetime;
5555
use middle::infer;
56+
use middle::infer::type_variable;
5657
use middle::pat_util;
5758
use middle::region::RegionMaps;
5859
use middle::stability;
@@ -1980,7 +1981,7 @@ pub enum TypeError<'tcx> {
19801981
ConvergenceMismatch(ExpectedFound<bool>),
19811982
ProjectionNameMismatched(ExpectedFound<ast::Name>),
19821983
ProjectionBoundsLength(ExpectedFound<usize>),
1983-
terr_ty_param_default_mismatch(expected_found<Ty<'tcx>>)
1984+
TyParamDefaultMismatch(ExpectedFound<Ty<'tcx>>)
19841985
}
19851986

19861987
/// Bounds suitable for an existentially quantified type parameter
@@ -5101,9 +5102,9 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
51015102
values.found)
51025103
},
51035104
terr_ty_param_default_mismatch(ref values) => {
5104-
write!(f, "conflicting type parameter defaults {} {}",
5105-
values.expected,
5106-
values.found)
5105+
write!(f, "conflicting type parameter defaults {} and {}",
5106+
values.expected.ty,
5107+
values.found.ty)
51075108
}
51085109
}
51095110
}
@@ -5423,7 +5424,7 @@ impl<'tcx> ctxt<'tcx> {
54235424
pub fn note_and_explain_type_err(&self, err: &TypeError<'tcx>, sp: Span) {
54245425
use self::TypeError::*;
54255426

5426-
match *err {
5427+
match err.clone() {
54275428
RegionsDoesNotOutlive(subregion, superregion) => {
54285429
self.note_and_explain_region("", subregion, "...");
54295430
self.note_and_explain_region("...does not necessarily outlive ",
@@ -5462,10 +5463,21 @@ impl<'tcx> ctxt<'tcx> {
54625463
using it as a trait object"));
54635464
}
54645465
},
5465-
terr_ty_param_default_mismatch(expected) => {
5466+
terr_ty_param_default_mismatch(values) => {
5467+
let expected = values.expected;
5468+
let found = values.found;
54665469
self.sess.span_note(sp,
5467-
&format!("found conflicting defaults {:?} {:?}",
5468-
expected.expected, expected.found))
5470+
&format!("conflicting type parameter defaults {} and {}",
5471+
expected.ty,
5472+
found.ty));
5473+
self.sess.span_note(expected.definition_span,
5474+
&format!("...a default was defined"));
5475+
self.sess.span_note(expected.origin_span,
5476+
&format!("...that was applied to an unconstrained type variable here"));
5477+
self.sess.span_note(found.definition_span,
5478+
&format!("...a second default was defined"));
5479+
self.sess.span_note(found.origin_span,
5480+
&format!("...that also applies to the same type variable here"));
54695481
}
54705482
_ => {}
54715483
}

src/librustc_typeck/astconv.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ pub trait AstConv<'tcx> {
109109
}
110110

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

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

src/librustc_typeck/check/method/confirm.rs

+2-2
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

+1-1
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

+1-1
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)