Skip to content

Commit 5ef6af0

Browse files
committed
rustc: move defaulting's use of &mut Substs from InferCtxt to typeck.
1 parent c87063f commit 5ef6af0

File tree

12 files changed

+213
-232
lines changed

12 files changed

+213
-232
lines changed

src/librustc/infer/mod.rs

Lines changed: 59 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,15 +1172,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
11721172
self.tcx.mk_var(self.next_ty_var_id(false))
11731173
}
11741174

1175-
pub fn next_ty_var_with_default(&self,
1176-
default: Option<type_variable::Default<'tcx>>) -> Ty<'tcx> {
1177-
let ty_var_id = self.type_variables
1178-
.borrow_mut()
1179-
.new_var(false, default);
1180-
1181-
self.tcx.mk_var(ty_var_id)
1182-
}
1183-
11841175
pub fn next_diverging_ty_var(&self) -> Ty<'tcx> {
11851176
self.tcx.mk_var(self.next_ty_var_id(true))
11861177
}
@@ -1205,35 +1196,49 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
12051196
ty::ReVar(self.region_vars.new_region_var(origin))
12061197
}
12071198

1199+
/// Create a region inference variable for the given
1200+
/// region parameter definition.
1201+
pub fn region_var_for_def(&self,
1202+
span: Span,
1203+
def: &ty::RegionParameterDef)
1204+
-> ty::Region {
1205+
self.next_region_var(EarlyBoundRegion(span, def.name))
1206+
}
1207+
1208+
/// Create a type inference variable for the given
1209+
/// type parameter definition. The substitutions are
1210+
/// for actual parameters that may be referred to by
1211+
/// the default of this type parameter, if it exists.
1212+
/// E.g. `struct Foo<A, B, C = (A, B)>(...);` when
1213+
/// used in a path such as `Foo::<T, U>::new()` will
1214+
/// use an inference variable for `C` with `[T, U]`
1215+
/// as the substitutions for the default, `(T, U)`.
1216+
pub fn type_var_for_def(&self,
1217+
span: Span,
1218+
def: &ty::TypeParameterDef<'tcx>,
1219+
substs: &Substs<'tcx>)
1220+
-> Ty<'tcx> {
1221+
let default = def.default.map(|default| {
1222+
type_variable::Default {
1223+
ty: default.subst_spanned(self.tcx, substs, Some(span)),
1224+
origin_span: span,
1225+
def_id: def.default_def_id
1226+
}
1227+
});
1228+
1229+
1230+
let ty_var_id = self.type_variables
1231+
.borrow_mut()
1232+
.new_var(false, default);
1233+
1234+
self.tcx.mk_var(ty_var_id)
1235+
}
1236+
12081237
pub fn region_vars_for_defs(&self,
12091238
span: Span,
12101239
defs: &[ty::RegionParameterDef])
12111240
-> Vec<ty::Region> {
1212-
defs.iter()
1213-
.map(|d| self.next_region_var(EarlyBoundRegion(span, d.name)))
1214-
.collect()
1215-
}
1216-
1217-
// We have to take `&mut Substs` in order to provide the correct substitutions for defaults
1218-
// along the way, for this reason we don't return them.
1219-
pub fn type_vars_for_defs(&self,
1220-
span: Span,
1221-
space: subst::ParamSpace,
1222-
substs: &mut Substs<'tcx>,
1223-
defs: &[ty::TypeParameterDef<'tcx>]) {
1224-
1225-
for def in defs.iter() {
1226-
let default = def.default.map(|default| {
1227-
type_variable::Default {
1228-
ty: default.subst_spanned(self.tcx, substs, Some(span)),
1229-
origin_span: span,
1230-
def_id: def.default_def_id
1231-
}
1232-
});
1233-
1234-
let ty_var = self.next_ty_var_with_default(default);
1235-
substs.types.push(space, ty_var);
1236-
}
1241+
defs.iter().map(|def| self.region_var_for_def(span, def)).collect()
12371242
}
12381243

12391244
/// Given a set of generics defined on a type or impl, returns a substitution mapping each
@@ -1243,21 +1248,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
12431248
generics: &ty::Generics<'tcx>)
12441249
-> &'tcx subst::Substs<'tcx>
12451250
{
1246-
let type_params = subst::VecPerParamSpace::empty();
1247-
1248-
let region_params =
1249-
generics.regions.map(
1250-
|d| self.next_region_var(EarlyBoundRegion(span, d.name)));
1251-
1252-
let mut substs = subst::Substs::new(type_params, region_params);
1253-
1254-
for space in subst::ParamSpace::all().iter() {
1255-
self.type_vars_for_defs(
1256-
span,
1257-
*space,
1258-
&mut substs,
1259-
generics.types.get_slice(*space));
1260-
}
1251+
let type_defs = generics.types.as_full_slice();
1252+
let region_defs = generics.regions.as_full_slice();
1253+
let substs = Substs::from_param_defs(region_defs, type_defs, |def| {
1254+
self.region_var_for_def(span, def)
1255+
}, |def, substs| {
1256+
self.type_var_for_def(span, def, substs)
1257+
});
12611258

12621259
self.tcx.mk_substs(substs)
12631260
}
@@ -1269,25 +1266,24 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
12691266
span: Span,
12701267
generics: &ty::Generics<'tcx>,
12711268
self_ty: Ty<'tcx>)
1272-
-> subst::Substs<'tcx>
1269+
-> &'tcx subst::Substs<'tcx>
12731270
{
1274-
12751271
assert!(generics.types.len(subst::SelfSpace) == 1);
12761272
assert!(generics.types.len(subst::FnSpace) == 0);
1277-
assert!(generics.regions.len(subst::SelfSpace) == 0);
1278-
assert!(generics.regions.len(subst::FnSpace) == 0);
1279-
1280-
let type_params = Vec::new();
1281-
1282-
let region_param_defs = generics.regions.get_slice(subst::TypeSpace);
1283-
let regions = self.region_vars_for_defs(span, region_param_defs);
12841273

1285-
let mut substs = subst::Substs::new_trait(type_params, regions, self_ty);
1286-
1287-
let type_parameter_defs = generics.types.get_slice(subst::TypeSpace);
1288-
self.type_vars_for_defs(span, subst::TypeSpace, &mut substs, type_parameter_defs);
1274+
let type_defs = generics.types.as_full_slice();
1275+
let region_defs = generics.regions.as_full_slice();
1276+
let substs = Substs::from_param_defs(region_defs, type_defs, |def| {
1277+
self.region_var_for_def(span, def)
1278+
}, |def, substs| {
1279+
if def.space == subst::SelfSpace {
1280+
self_ty
1281+
} else {
1282+
self.type_var_for_def(span, def, substs)
1283+
}
1284+
});
12891285

1290-
return substs;
1286+
self.tcx.mk_substs(substs)
12911287
}
12921288

12931289
pub fn fresh_bound_region(&self, debruijn: ty::DebruijnIndex) -> ty::Region {

src/librustc/traits/error_reporting.rs

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
3131
use ty::error::ExpectedFound;
3232
use ty::fast_reject;
3333
use ty::fold::TypeFolder;
34-
use ty::subst::{self, Subst, TypeSpace};
34+
use ty::subst::{Subst, TypeSpace};
3535
use util::nodemap::{FnvHashMap, FnvHashSet};
3636

3737
use std::cmp;
@@ -167,27 +167,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
167167
});
168168
}
169169

170-
fn impl_substs(&self,
171-
did: DefId,
172-
obligation: PredicateObligation<'tcx>)
173-
-> subst::Substs<'tcx> {
174-
let tcx = self.tcx;
175-
176-
let ity = tcx.lookup_item_type(did);
177-
let (tps, rps, _) =
178-
(ity.generics.types.get_slice(TypeSpace),
179-
ity.generics.regions.get_slice(TypeSpace),
180-
ity.ty);
181-
182-
let rps = self.region_vars_for_defs(obligation.cause.span, rps);
183-
let mut substs = subst::Substs::new_type(vec![], rps);
184-
self.type_vars_for_defs(obligation.cause.span,
185-
TypeSpace,
186-
&mut substs,
187-
tps);
188-
substs
189-
}
190-
191170
fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
192171
/// returns the fuzzy category of a given type, or None
193172
/// if the type can be equated to any type.
@@ -242,10 +221,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
242221

243222
self.tcx.lookup_trait_def(trait_ref.def_id)
244223
.for_each_relevant_impl(self.tcx, trait_self_ty, |def_id| {
224+
let ity = tcx.lookup_item_type(def_id);
225+
let impl_substs = self.fresh_substs_for_generics(obligation.cause.span,
226+
&ity.generics);
245227
let impl_trait_ref = tcx
246228
.impl_trait_ref(def_id)
247229
.unwrap()
248-
.subst(tcx, &self.impl_substs(def_id, obligation.clone()));
230+
.subst(tcx, impl_substs);
249231

250232
let impl_self_ty = impl_trait_ref.self_ty();
251233

src/librustc/traits/util.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -358,8 +358,7 @@ pub fn fresh_type_vars_for_impl<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx
358358
impl_def_id: DefId)
359359
-> &'tcx Substs<'tcx>
360360
{
361-
let tcx = infcx.tcx;
362-
let impl_generics = tcx.lookup_item_type(impl_def_id).generics;
361+
let impl_generics = infcx.tcx.lookup_item_type(impl_def_id).generics;
363362
infcx.fresh_substs_for_generics(span, &impl_generics)
364363
}
365364

src/librustc/ty/subst.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,33 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
7373
}
7474
}
7575

76+
/// Creates a Substs for generic parameter definitions,
77+
/// by calling closures to obtain each region and type.
78+
/// The closures get to observe the Substs as they're
79+
/// being built, which can be used to correctly
80+
/// substitute defaults of type parameters.
81+
pub fn from_generics<FR, FT>(generics: &ty::Generics<'tcx>,
82+
mut mk_region: FR,
83+
mut mk_type: FT)
84+
-> Substs<'tcx>
85+
where FR: FnMut(&ty::RegionParameterDef, &Substs<'tcx>) -> ty::Region,
86+
FT: FnMut(&ty::TypeParameterDef<'tcx>, &Substs<'tcx>) -> Ty<'tcx> {
87+
let mut substs = Substs::empty();
88+
for &space in &ParamSpace::all() {
89+
for def in generics.regions.get_slice(space) {
90+
let region = mk_region(def, &substs);
91+
assert_eq!(substs.regions.len(def.space), def.index as usize);
92+
substs.regions.push(def.space, region);
93+
}
94+
for def in generics.types.get_slice(space) {
95+
let ty = mk_type(def, &substs);
96+
assert_eq!(substs.types.len(def.space), def.index as usize);
97+
substs.types.push(def.space, ty);
98+
}
99+
}
100+
substs
101+
}
102+
76103
pub fn is_noop(&self) -> bool {
77104
self.regions.is_empty() && self.types.is_empty()
78105
}
@@ -81,6 +108,10 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
81108
*self.types.get(ty_param_def.space, ty_param_def.index as usize)
82109
}
83110

111+
pub fn region_for_def(&self, def: &ty::RegionParameterDef) -> ty::Region {
112+
*self.regions.get(def.space, def.index as usize)
113+
}
114+
84115
pub fn self_ty(&self) -> Option<Ty<'tcx>> {
85116
self.types.get_self().cloned()
86117
}

src/librustc_typeck/astconv.rs

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ use hir::def_id::DefId;
5555
use hir::print as pprust;
5656
use middle::resolve_lifetime as rl;
5757
use rustc::lint;
58-
use rustc::ty::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs, ParamSpace};
58+
use rustc::ty::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs};
5959
use rustc::traits;
6060
use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
6161
use rustc::ty::wf::object_region_bounds;
@@ -115,11 +115,15 @@ pub trait AstConv<'gcx, 'tcx> {
115115
fn get_free_substs(&self) -> Option<&Substs<'tcx>>;
116116

117117
/// What type should we use when a type is omitted?
118-
fn ty_infer(&self,
119-
param_and_substs: Option<ty::TypeParameterDef<'tcx>>,
120-
substs: Option<&mut Substs<'tcx>>,
121-
space: Option<ParamSpace>,
122-
span: Span) -> Ty<'tcx>;
118+
fn ty_infer(&self, span: Span) -> Ty<'tcx>;
119+
120+
/// Same as ty_infer, but with a known type parameter definition.
121+
fn ty_infer_for_def(&self,
122+
_def: &ty::TypeParameterDef<'tcx>,
123+
_substs: &Substs<'tcx>,
124+
span: Span) -> Ty<'tcx> {
125+
self.ty_infer(span)
126+
}
123127

124128
/// Projecting an associated type from a (potentially)
125129
/// higher-ranked trait reference is more complicated, because of
@@ -535,26 +539,28 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
535539
self_ty: Option<Ty<'tcx>>)
536540
-> Vec<Ty<'tcx>>
537541
{
538-
fn default_type_parameter<'tcx>(p: &ty::TypeParameterDef<'tcx>, self_ty: Option<Ty<'tcx>>)
539-
-> Option<ty::TypeParameterDef<'tcx>>
540-
{
542+
let use_default = |p: &ty::TypeParameterDef<'tcx>| {
541543
if let Some(ref default) = p.default {
542544
if self_ty.is_none() && default.has_self_ty() {
543545
// There is no suitable inference default for a type parameter
544546
// that references self with no self-type provided.
545-
return None;
547+
return false;
546548
}
547549
}
548550

549-
Some(p.clone())
550-
}
551+
true
552+
};
551553

552554
if param_mode == PathParamMode::Optional && types_provided.is_empty() {
553-
ty_param_defs
554-
.iter()
555-
.map(|p| self.ty_infer(default_type_parameter(p, self_ty), Some(&mut substs),
556-
Some(TypeSpace), span))
557-
.collect()
555+
ty_param_defs.iter().map(|def| {
556+
let ty_var = if use_default(def) {
557+
self.ty_infer_for_def(def, &substs, span)
558+
} else {
559+
self.ty_infer(span)
560+
};
561+
substs.types.push(def.space, ty_var);
562+
ty_var
563+
}).collect()
558564
} else {
559565
types_provided
560566
}
@@ -1828,7 +1834,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
18281834
// values in a ExprClosure, or as
18291835
// the type of local variables. Both of these cases are
18301836
// handled specially and will not descend into this routine.
1831-
self.ty_infer(None, None, None, ast_ty.span)
1837+
self.ty_infer(ast_ty.span)
18321838
}
18331839
};
18341840

@@ -1845,7 +1851,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
18451851
{
18461852
match a.ty.node {
18471853
hir::TyInfer if expected_ty.is_some() => expected_ty.unwrap(),
1848-
hir::TyInfer => self.ty_infer(None, None, None, a.ty.span),
1854+
hir::TyInfer => self.ty_infer(a.ty.span),
18491855
_ => self.ast_ty_to_ty(rscope, &a.ty),
18501856
}
18511857
}
@@ -2067,8 +2073,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
20672073
let output_ty = match decl.output {
20682074
_ if is_infer && expected_ret_ty.is_some() =>
20692075
expected_ret_ty.unwrap(),
2070-
_ if is_infer =>
2071-
self.ty_infer(None, None, None, decl.output.span()),
2076+
_ if is_infer => self.ty_infer(decl.output.span()),
20722077
hir::Return(ref output) =>
20732078
self.ast_ty_to_ty(&rb, &output),
20742079
hir::DefaultReturn(..) => bug!(),

0 commit comments

Comments
 (0)