Skip to content

Commit a5c12f4

Browse files
committed
Auto merge of #26870 - jroesch:default-typaram-fallback, r=nikomatsakis
This PR completes [RFC 213](https://github.com/rust-lang/rfcs/blob/master/text/0213-defaulted-type-params.md) by allowing default type parameters to influence inference. This is almost certainly a breaking change due to interactions between default type parameters and the old fallback algorithm used for integral and floating point literals. The error messages still require polish but I wanted to get early review and feedback from others on the the changes, error messages, and test cases. I also imagine we will want to run anywhere from 1-3 versions of this on crater and evaluate the impact, and it would be best to get that ball rolling. The only outstanding issue I'm aware of is that type alias defaults don't work. It seems this may require significant restructuring, since during inference type aliases have already been expanded. @nikomatsakis might be able to provide some clarity here. r? @nikomatsakis cc @eddyb @gankro @aturon @brson
2 parents 9a196aa + 5ad36cb commit a5c12f4

31 files changed

+949
-117
lines changed

src/doc/reference.md

+2
Original file line numberDiff line numberDiff line change
@@ -2368,6 +2368,8 @@ The currently implemented features of the reference compiler are:
23682368
internally without imposing on callers
23692369
(i.e. making them behave like function calls in
23702370
terms of encapsulation).
2371+
* - `default_type_parameter_fallback` - Allows type parameter defaults to
2372+
influence type inference.
23712373

23722374
If a feature is promoted to a language feature, then all existing programs will
23732375
start to receive compilation warnings about `#![feature]` directives which enabled

src/librustc/ast_map/mod.rs

+19-2
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ pub enum Node<'ast> {
119119
NodeStructCtor(&'ast StructDef),
120120

121121
NodeLifetime(&'ast Lifetime),
122+
NodeTyParam(&'ast TyParam)
122123
}
123124

124125
/// Represents an entry and its parent NodeID.
@@ -142,6 +143,7 @@ enum MapEntry<'ast> {
142143
EntryBlock(NodeId, &'ast Block),
143144
EntryStructCtor(NodeId, &'ast StructDef),
144145
EntryLifetime(NodeId, &'ast Lifetime),
146+
EntryTyParam(NodeId, &'ast TyParam),
145147

146148
/// Roots for node trees.
147149
RootCrate,
@@ -175,7 +177,8 @@ impl<'ast> MapEntry<'ast> {
175177
NodePat(n) => EntryPat(p, n),
176178
NodeBlock(n) => EntryBlock(p, n),
177179
NodeStructCtor(n) => EntryStructCtor(p, n),
178-
NodeLifetime(n) => EntryLifetime(p, n)
180+
NodeLifetime(n) => EntryLifetime(p, n),
181+
NodeTyParam(n) => EntryTyParam(p, n),
179182
}
180183
}
181184

@@ -194,6 +197,7 @@ impl<'ast> MapEntry<'ast> {
194197
EntryBlock(id, _) => id,
195198
EntryStructCtor(id, _) => id,
196199
EntryLifetime(id, _) => id,
200+
EntryTyParam(id, _) => id,
197201
_ => return None
198202
})
199203
}
@@ -213,6 +217,7 @@ impl<'ast> MapEntry<'ast> {
213217
EntryBlock(_, n) => NodeBlock(n),
214218
EntryStructCtor(_, n) => NodeStructCtor(n),
215219
EntryLifetime(_, n) => NodeLifetime(n),
220+
EntryTyParam(_, n) => NodeTyParam(n),
216221
_ => return None
217222
})
218223
}
@@ -573,6 +578,7 @@ impl<'ast> Map<'ast> {
573578
Some(NodePat(pat)) => pat.span,
574579
Some(NodeBlock(block)) => block.span,
575580
Some(NodeStructCtor(_)) => self.expect_item(self.get_parent(id)).span,
581+
Some(NodeTyParam(ty_param)) => ty_param.span,
576582
_ => return None,
577583
};
578584
Some(sp)
@@ -815,6 +821,14 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
815821
self.parent_node = parent_node;
816822
}
817823

824+
fn visit_generics(&mut self, generics: &'ast Generics) {
825+
for ty_param in generics.ty_params.iter() {
826+
self.insert(ty_param.id, NodeTyParam(ty_param));
827+
}
828+
829+
visit::walk_generics(self, generics);
830+
}
831+
818832
fn visit_trait_item(&mut self, ti: &'ast TraitItem) {
819833
let parent_node = self.parent_node;
820834
self.parent_node = ti.id;
@@ -1015,7 +1029,7 @@ impl<'a> NodePrinter for pprust::State<'a> {
10151029
NodePat(a) => self.print_pat(&*a),
10161030
NodeBlock(a) => self.print_block(&*a),
10171031
NodeLifetime(a) => self.print_lifetime(&*a),
1018-
1032+
NodeTyParam(_) => panic!("cannot print TyParam"),
10191033
// these cases do not carry enough information in the
10201034
// ast_map to reconstruct their full structure for pretty
10211035
// printing.
@@ -1123,6 +1137,9 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
11231137
format!("lifetime {}{}",
11241138
pprust::lifetime_to_string(&**l), id_str)
11251139
}
1140+
Some(NodeTyParam(ref ty_param)) => {
1141+
format!("typaram {:?}{}", ty_param, id_str)
1142+
}
11261143
None => {
11271144
format!("unknown node{}", id_str)
11281145
}

src/librustc/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
#![feature(slice_splits)]
5757
#![feature(slice_patterns)]
5858
#![feature(slice_position_elem)]
59+
#![feature(slice_concat_ext)]
5960
#![feature(staged_api)]
6061
#![feature(str_char)]
6162
#![feature(str_match_indices)]

src/librustc/metadata/tydecode.rs

+2
Original file line numberDiff line numberDiff line change
@@ -833,6 +833,7 @@ fn parse_type_param_def_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F)
833833
assert_eq!(next(st), '|');
834834
let index = parse_u32(st);
835835
assert_eq!(next(st), '|');
836+
let default_def_id = parse_def_(st, NominalType, conv);
836837
let default = parse_opt(st, |st| parse_ty_(st, conv));
837838
let object_lifetime_default = parse_object_lifetime_default(st, conv);
838839

@@ -841,6 +842,7 @@ fn parse_type_param_def_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F)
841842
def_id: def_id,
842843
space: space,
843844
index: index,
845+
default_def_id: default_def_id,
844846
default: default,
845847
object_lifetime_default: object_lifetime_default,
846848
}

src/librustc/metadata/tyencode.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -409,9 +409,9 @@ pub fn enc_region_bounds<'a, 'tcx>(w: &mut Encoder,
409409

410410
pub fn enc_type_param_def<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>,
411411
v: &ty::TypeParameterDef<'tcx>) {
412-
mywrite!(w, "{}:{}|{}|{}|",
412+
mywrite!(w, "{}:{}|{}|{}|{}|",
413413
token::get_name(v.name), (cx.ds)(v.def_id),
414-
v.space.to_uint(), v.index);
414+
v.space.to_uint(), v.index, (cx.ds)(v.default_def_id));
415415
enc_opt(w, v.default, |w, t| enc_ty(w, cx, t));
416416
enc_object_lifetime_default(w, cx, v.object_lifetime_default);
417417
}

src/librustc/middle/infer/error_reporting.rs

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

+119-8
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,50 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
653653
}
654654
}
655655

656+
/// Returns a type variable's default fallback if any exists. A default
657+
/// must be attached to the variable when created, if it is created
658+
/// without a default, this will return None.
659+
///
660+
/// This code does not apply to integral or floating point variables,
661+
/// only to use declared defaults.
662+
///
663+
/// See `new_ty_var_with_default` to create a type variable with a default.
664+
/// See `type_variable::Default` for details about what a default entails.
665+
pub fn default(&self, ty: Ty<'tcx>) -> Option<type_variable::Default<'tcx>> {
666+
match ty.sty {
667+
ty::TyInfer(ty::TyVar(vid)) => self.type_variables.borrow().default(vid),
668+
_ => None
669+
}
670+
}
671+
672+
pub fn unsolved_variables(&self) -> Vec<ty::Ty<'tcx>> {
673+
let mut variables = Vec::new();
674+
675+
let unbound_ty_vars = self.type_variables
676+
.borrow()
677+
.unsolved_variables()
678+
.into_iter()
679+
.map(|t| self.tcx.mk_var(t));
680+
681+
let unbound_int_vars = self.int_unification_table
682+
.borrow_mut()
683+
.unsolved_variables()
684+
.into_iter()
685+
.map(|v| self.tcx.mk_int_var(v));
686+
687+
let unbound_float_vars = self.float_unification_table
688+
.borrow_mut()
689+
.unsolved_variables()
690+
.into_iter()
691+
.map(|v| self.tcx.mk_float_var(v));
692+
693+
variables.extend(unbound_ty_vars);
694+
variables.extend(unbound_int_vars);
695+
variables.extend(unbound_float_vars);
696+
697+
return variables;
698+
}
699+
656700
fn combine_fields(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>)
657701
-> CombineFields<'a, 'tcx> {
658702
CombineFields {infcx: self,
@@ -956,13 +1000,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
9561000
pub fn next_ty_var_id(&self, diverging: bool) -> TyVid {
9571001
self.type_variables
9581002
.borrow_mut()
959-
.new_var(diverging)
1003+
.new_var(diverging, None)
9601004
}
9611005

9621006
pub fn next_ty_var(&self) -> Ty<'tcx> {
9631007
self.tcx.mk_var(self.next_ty_var_id(false))
9641008
}
9651009

1010+
pub fn next_ty_var_with_default(&self,
1011+
default: Option<type_variable::Default<'tcx>>) -> Ty<'tcx> {
1012+
let ty_var_id = self.type_variables
1013+
.borrow_mut()
1014+
.new_var(false, default);
1015+
1016+
self.tcx.mk_var(ty_var_id)
1017+
}
1018+
9661019
pub fn next_diverging_ty_var(&self) -> Ty<'tcx> {
9671020
self.tcx.mk_var(self.next_ty_var_id(true))
9681021
}
@@ -996,20 +1049,55 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
9961049
.collect()
9971050
}
9981051

1052+
// We have to take `&mut Substs` in order to provide the correct substitutions for defaults
1053+
// along the way, for this reason we don't return them.
1054+
pub fn type_vars_for_defs(&self,
1055+
span: Span,
1056+
space: subst::ParamSpace,
1057+
substs: &mut Substs<'tcx>,
1058+
defs: &[ty::TypeParameterDef<'tcx>]) {
1059+
1060+
let mut vars = Vec::with_capacity(defs.len());
1061+
1062+
for def in defs.iter() {
1063+
let default = def.default.map(|default| {
1064+
type_variable::Default {
1065+
ty: default.subst_spanned(self.tcx, substs, Some(span)),
1066+
origin_span: span,
1067+
def_id: def.default_def_id
1068+
}
1069+
});
1070+
1071+
let ty_var = self.next_ty_var_with_default(default);
1072+
substs.types.push(space, ty_var);
1073+
vars.push(ty_var)
1074+
}
1075+
}
1076+
9991077
/// Given a set of generics defined on a type or impl, returns a substitution mapping each
10001078
/// type/region parameter to a fresh inference variable.
10011079
pub fn fresh_substs_for_generics(&self,
10021080
span: Span,
10031081
generics: &ty::Generics<'tcx>)
10041082
-> subst::Substs<'tcx>
10051083
{
1006-
let type_params =
1007-
generics.types.map(
1008-
|_| self.next_ty_var());
1084+
let type_params = subst::VecPerParamSpace::empty();
1085+
10091086
let region_params =
10101087
generics.regions.map(
10111088
|d| self.next_region_var(EarlyBoundRegion(span, d.name)));
1012-
subst::Substs::new(type_params, region_params)
1089+
1090+
let mut substs = subst::Substs::new(type_params, region_params);
1091+
1092+
for space in subst::ParamSpace::all().iter() {
1093+
self.type_vars_for_defs(
1094+
span,
1095+
*space,
1096+
&mut substs,
1097+
generics.types.get_slice(*space));
1098+
}
1099+
1100+
return substs;
10131101
}
10141102

10151103
/// Given a set of generics defined on a trait, returns a substitution mapping each output
@@ -1027,13 +1115,17 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
10271115
assert!(generics.regions.len(subst::SelfSpace) == 0);
10281116
assert!(generics.regions.len(subst::FnSpace) == 0);
10291117

1030-
let type_parameter_count = generics.types.len(subst::TypeSpace);
1031-
let type_parameters = self.next_ty_vars(type_parameter_count);
1118+
let type_params = Vec::new();
10321119

10331120
let region_param_defs = generics.regions.get_slice(subst::TypeSpace);
10341121
let regions = self.region_vars_for_defs(span, region_param_defs);
10351122

1036-
subst::Substs::new_trait(type_parameters, regions, self_ty)
1123+
let mut substs = subst::Substs::new_trait(type_params, regions, self_ty);
1124+
1125+
let type_parameter_defs = generics.types.get_slice(subst::TypeSpace);
1126+
self.type_vars_for_defs(span, subst::TypeSpace, &mut substs, type_parameter_defs);
1127+
1128+
return substs;
10371129
}
10381130

10391131
pub fn fresh_bound_region(&self, debruijn: ty::DebruijnIndex) -> ty::Region {
@@ -1268,6 +1360,25 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
12681360
self.report_and_explain_type_error(trace, err);
12691361
}
12701362

1363+
pub fn report_conflicting_default_types(&self,
1364+
span: Span,
1365+
expected: type_variable::Default<'tcx>,
1366+
actual: type_variable::Default<'tcx>) {
1367+
let trace = TypeTrace {
1368+
origin: Misc(span),
1369+
values: Types(ty::ExpectedFound {
1370+
expected: expected.ty,
1371+
found: actual.ty
1372+
})
1373+
};
1374+
1375+
self.report_and_explain_type_error(trace,
1376+
&TypeError::TyParamDefaultMismatch(ty::ExpectedFound {
1377+
expected: expected,
1378+
found: actual
1379+
}));
1380+
}
1381+
12711382
pub fn replace_late_bound_regions_with_fresh_var<T>(
12721383
&self,
12731384
span: Span,

0 commit comments

Comments
 (0)