Skip to content

Commit fdf985c

Browse files
committed
Substitute type params in default type params using them.
1 parent 8665a51 commit fdf985c

File tree

7 files changed

+245
-80
lines changed

7 files changed

+245
-80
lines changed

src/librustc/middle/subst.rs

+128-43
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,27 @@
1313
use middle::ty;
1414
use middle::ty_fold;
1515
use middle::ty_fold::TypeFolder;
16+
use util::ppaux::Repr;
1617

1718
use std::rc::Rc;
19+
use syntax::codemap::Span;
1820
use syntax::opt_vec::OptVec;
1921

2022
///////////////////////////////////////////////////////////////////////////
2123
// Public trait `Subst`
2224
//
2325
// Just call `foo.subst(tcx, substs)` to perform a substitution across
2426
// `foo`.
27+
// Or use `foo.subst_spanned(tcx, substs, Some(span))` when there is more
28+
// information available (for better errors).
2529

2630
pub trait Subst {
27-
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> Self;
31+
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> Self {
32+
self.subst_spanned(tcx, substs, None)
33+
}
34+
fn subst_spanned(&self, tcx: ty::ctxt,
35+
substs: &ty::substs,
36+
span: Option<Span>) -> Self;
2837
}
2938

3039
///////////////////////////////////////////////////////////////////////////
@@ -36,19 +45,32 @@ pub trait Subst {
3645
// our current method/trait matching algorithm. - Niko
3746

3847
impl Subst for ty::t {
39-
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::t {
40-
if ty::substs_is_noop(substs) {
48+
fn subst_spanned(&self, tcx: ty::ctxt,
49+
substs: &ty::substs,
50+
span: Option<Span>) -> ty::t {
51+
if ty::substs_is_noop(substs) && !ty::type_has_params(*self) {
4152
*self
4253
} else {
43-
let mut folder = SubstFolder {tcx: tcx, substs: substs};
54+
let mut folder = SubstFolder {
55+
tcx: tcx,
56+
substs: substs,
57+
span: span,
58+
root_ty: Some(*self)
59+
};
4460
folder.fold_ty(*self)
4561
}
4662
}
4763
}
4864

4965
struct SubstFolder<'a> {
5066
tcx: ty::ctxt,
51-
substs: &'a ty::substs
67+
substs: &'a ty::substs,
68+
69+
// The location for which the substitution is performed, if available.
70+
span: Option<Span>,
71+
72+
// The root type that is being substituted, if available.
73+
root_ty: Option<ty::t>
5274
}
5375

5476
impl<'a> TypeFolder for SubstFolder<'a> {
@@ -65,14 +87,42 @@ impl<'a> TypeFolder for SubstFolder<'a> {
6587

6688
match ty::get(t).sty {
6789
ty::ty_param(p) => {
68-
self.substs.tps[p.idx]
90+
if p.idx < self.substs.tps.len() {
91+
self.substs.tps[p.idx]
92+
} else {
93+
let root_msg = match self.root_ty {
94+
Some(root) => format!(" in the substitution of `{}`",
95+
root.repr(self.tcx)),
96+
None => ~""
97+
};
98+
let m = format!("missing type param `{}`{}",
99+
t.repr(self.tcx), root_msg);
100+
match self.span {
101+
Some(span) => self.tcx.sess.span_err(span, m),
102+
None => self.tcx.sess.err(m)
103+
}
104+
ty::mk_err()
105+
}
69106
}
70107
ty::ty_self(_) => {
71-
self.substs.self_ty.expect("ty_self not found in substs")
72-
}
73-
_ => {
74-
ty_fold::super_fold_ty(self, t)
108+
match self.substs.self_ty {
109+
Some(ty) => ty,
110+
None => {
111+
let root_msg = match self.root_ty {
112+
Some(root) => format!(" in the substitution of `{}`",
113+
root.repr(self.tcx)),
114+
None => ~""
115+
};
116+
let m = format!("missing `Self` type param{}", root_msg);
117+
match self.span {
118+
Some(span) => self.tcx.sess.span_err(span, m),
119+
None => self.tcx.sess.err(m)
120+
}
121+
ty::mk_err()
122+
}
123+
}
75124
}
125+
_ => ty_fold::super_fold_ty(self, t)
76126
}
77127
}
78128
}
@@ -81,112 +131,145 @@ impl<'a> TypeFolder for SubstFolder<'a> {
81131
// Other types
82132

83133
impl<T:Subst> Subst for ~[T] {
84-
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ~[T] {
85-
self.map(|t| t.subst(tcx, substs))
134+
fn subst_spanned(&self, tcx: ty::ctxt,
135+
substs: &ty::substs,
136+
span: Option<Span>) -> ~[T] {
137+
self.map(|t| t.subst_spanned(tcx, substs, span))
86138
}
87139
}
88140
impl<T:Subst> Subst for Rc<T> {
89-
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> Rc<T> {
90-
Rc::new(self.borrow().subst(tcx, substs))
141+
fn subst_spanned(&self, tcx: ty::ctxt,
142+
substs: &ty::substs,
143+
span: Option<Span>) -> Rc<T> {
144+
Rc::new(self.borrow().subst_spanned(tcx, substs, span))
91145
}
92146
}
93147

94148
impl<T:Subst> Subst for OptVec<T> {
95-
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> OptVec<T> {
96-
self.map(|t| t.subst(tcx, substs))
149+
fn subst_spanned(&self, tcx: ty::ctxt,
150+
substs: &ty::substs,
151+
span: Option<Span>) -> OptVec<T> {
152+
self.map(|t| t.subst_spanned(tcx, substs, span))
97153
}
98154
}
99155

100156
impl<T:Subst + 'static> Subst for @T {
101-
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> @T {
157+
fn subst_spanned(&self, tcx: ty::ctxt,
158+
substs: &ty::substs,
159+
span: Option<Span>) -> @T {
102160
match self {
103-
t => @(**t).subst(tcx, substs)
161+
t => @(**t).subst_spanned(tcx, substs, span)
104162
}
105163
}
106164
}
107165

108166
impl<T:Subst> Subst for Option<T> {
109-
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> Option<T> {
110-
self.as_ref().map(|t| t.subst(tcx, substs))
167+
fn subst_spanned(&self, tcx: ty::ctxt,
168+
substs: &ty::substs,
169+
span: Option<Span>) -> Option<T> {
170+
self.as_ref().map(|t| t.subst_spanned(tcx, substs, span))
111171
}
112172
}
113173

114174
impl Subst for ty::TraitRef {
115-
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::TraitRef {
175+
fn subst_spanned(&self, tcx: ty::ctxt,
176+
substs: &ty::substs,
177+
span: Option<Span>) -> ty::TraitRef {
116178
ty::TraitRef {
117179
def_id: self.def_id,
118-
substs: self.substs.subst(tcx, substs)
180+
substs: self.substs.subst_spanned(tcx, substs, span)
119181
}
120182
}
121183
}
122184

123185
impl Subst for ty::substs {
124-
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::substs {
186+
fn subst_spanned(&self, tcx: ty::ctxt,
187+
substs: &ty::substs,
188+
span: Option<Span>) -> ty::substs {
125189
ty::substs {
126-
regions: self.regions.subst(tcx, substs),
127-
self_ty: self.self_ty.map(|typ| typ.subst(tcx, substs)),
128-
tps: self.tps.map(|typ| typ.subst(tcx, substs))
190+
regions: self.regions.subst_spanned(tcx, substs, span),
191+
self_ty: self.self_ty.map(|typ| typ.subst_spanned(tcx, substs, span)),
192+
tps: self.tps.map(|typ| typ.subst_spanned(tcx, substs, span))
129193
}
130194
}
131195
}
132196

133197
impl Subst for ty::RegionSubsts {
134-
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::RegionSubsts {
198+
fn subst_spanned(&self, tcx: ty::ctxt,
199+
substs: &ty::substs,
200+
span: Option<Span>) -> ty::RegionSubsts {
135201
match *self {
136202
ty::ErasedRegions => {
137203
ty::ErasedRegions
138204
}
139205
ty::NonerasedRegions(ref regions) => {
140-
ty::NonerasedRegions(regions.subst(tcx, substs))
206+
ty::NonerasedRegions(regions.subst_spanned(tcx, substs, span))
141207
}
142208
}
143209
}
144210
}
145211

146212
impl Subst for ty::BareFnTy {
147-
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::BareFnTy {
148-
let mut folder = SubstFolder {tcx: tcx, substs: substs};
213+
fn subst_spanned(&self, tcx: ty::ctxt,
214+
substs: &ty::substs,
215+
span: Option<Span>) -> ty::BareFnTy {
216+
let mut folder = SubstFolder {
217+
tcx: tcx,
218+
substs: substs,
219+
span: span,
220+
root_ty: None
221+
};
149222
folder.fold_bare_fn_ty(self)
150223
}
151224
}
152225

153226
impl Subst for ty::ParamBounds {
154-
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::ParamBounds {
227+
fn subst_spanned(&self, tcx: ty::ctxt,
228+
substs: &ty::substs,
229+
span: Option<Span>) -> ty::ParamBounds {
155230
ty::ParamBounds {
156231
builtin_bounds: self.builtin_bounds,
157-
trait_bounds: self.trait_bounds.subst(tcx, substs)
232+
trait_bounds: self.trait_bounds.subst_spanned(tcx, substs, span)
158233
}
159234
}
160235
}
161236

162237
impl Subst for ty::TypeParameterDef {
163-
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::TypeParameterDef {
238+
fn subst_spanned(&self, tcx: ty::ctxt,
239+
substs: &ty::substs,
240+
span: Option<Span>) -> ty::TypeParameterDef {
164241
ty::TypeParameterDef {
165242
ident: self.ident,
166243
def_id: self.def_id,
167-
bounds: self.bounds.subst(tcx, substs),
168-
default: self.default.map(|x| x.subst(tcx, substs))
244+
bounds: self.bounds.subst_spanned(tcx, substs, span),
245+
default: self.default.map(|x| x.subst_spanned(tcx, substs, span))
169246
}
170247
}
171248
}
172249

173250
impl Subst for ty::Generics {
174-
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::Generics {
251+
fn subst_spanned(&self, tcx: ty::ctxt,
252+
substs: &ty::substs,
253+
span: Option<Span>) -> ty::Generics {
175254
ty::Generics {
176-
type_param_defs: self.type_param_defs.subst(tcx, substs),
177-
region_param_defs: self.region_param_defs.subst(tcx, substs),
255+
type_param_defs: self.type_param_defs.subst_spanned(tcx, substs, span),
256+
region_param_defs: self.region_param_defs.subst_spanned(tcx, substs, span),
178257
}
179258
}
180259
}
181260

182261
impl Subst for ty::RegionParameterDef {
183-
fn subst(&self, _: ty::ctxt, _: &ty::substs) -> ty::RegionParameterDef {
262+
fn subst_spanned(&self, _: ty::ctxt,
263+
_: &ty::substs,
264+
_: Option<Span>) -> ty::RegionParameterDef {
184265
*self
185266
}
186267
}
187268

188269
impl Subst for ty::Region {
189-
fn subst(&self, _tcx: ty::ctxt, substs: &ty::substs) -> ty::Region {
270+
fn subst_spanned(&self, _tcx: ty::ctxt,
271+
substs: &ty::substs,
272+
_: Option<Span>) -> ty::Region {
190273
// Note: This routine only handles regions that are bound on
191274
// type declarationss and other outer declarations, not those
192275
// bound in *fn types*. Region substitution of the bound
@@ -206,10 +289,12 @@ impl Subst for ty::Region {
206289
}
207290

208291
impl Subst for ty::ty_param_bounds_and_ty {
209-
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::ty_param_bounds_and_ty {
292+
fn subst_spanned(&self, tcx: ty::ctxt,
293+
substs: &ty::substs,
294+
span: Option<Span>) -> ty::ty_param_bounds_and_ty {
210295
ty::ty_param_bounds_and_ty {
211-
generics: self.generics.subst(tcx, substs),
212-
ty: self.ty.subst(tcx, substs)
296+
generics: self.generics.subst_spanned(tcx, substs, span),
297+
ty: self.ty.subst_spanned(tcx, substs, span)
213298
}
214299
}
215300
}

src/librustc/middle/typeck/astconv.rs

+12-4
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252

5353
use middle::const_eval;
5454
use middle::lint;
55+
use middle::subst::Subst;
5556
use middle::ty::{substs};
5657
use middle::ty::{ty_param_substs_and_ty};
5758
use middle::ty;
@@ -228,16 +229,23 @@ fn ast_path_substs<AC:AstConv,RS:RegionScope>(
228229
~"provided type arguments with defaults");
229230
}
230231

231-
let defaults = decl_generics.type_param_defs().slice_from(supplied_ty_param_count)
232-
.iter().map(|&x| x.default.unwrap());
233232
let tps = path.segments.iter().flat_map(|s| s.types.iter())
234233
.map(|&a_t| ast_ty_to_ty(this, rscope, a_t))
235-
.chain(defaults).collect();
236-
substs {
234+
.collect();
235+
236+
let mut substs = substs {
237237
regions: ty::NonerasedRegions(regions),
238238
self_ty: self_ty,
239239
tps: tps
240+
};
241+
242+
for param in decl_generics.type_param_defs()
243+
.slice_from(supplied_ty_param_count).iter() {
244+
let ty = param.default.unwrap().subst_spanned(tcx, &substs, Some(path.span));
245+
substs.tps.push(ty);
240246
}
247+
248+
substs
241249
}
242250

243251
pub fn ast_path_to_substs_and_ty<AC:AstConv,

0 commit comments

Comments
 (0)