Skip to content

Commit b524991

Browse files
committed
Refactor astconv.rs (part ii)
1 parent 5d07db4 commit b524991

File tree

2 files changed

+117
-69
lines changed

2 files changed

+117
-69
lines changed

src/librustc_typeck/astconv.rs

Lines changed: 116 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,13 @@
1313
//! is parameterized by an instance of `AstConv`.
1414
1515
use rustc_data_structures::accumulate_vec::AccumulateVec;
16+
use rustc_data_structures::array_vec::ArrayVec;
1617
use hir::{self, GenericArg};
1718
use hir::def::Def;
1819
use hir::def_id::DefId;
1920
use middle::resolve_lifetime as rl;
2021
use namespace::Namespace;
21-
use rustc::ty::subst::{Subst, Substs};
22+
use rustc::ty::subst::{Kind, Subst, Substs};
2223
use rustc::traits;
2324
use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
2425
use rustc::ty::GenericParamDefKind;
@@ -270,85 +271,133 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
270271
false
271272
};
272273

273-
let self_offset = self_ty.is_some() as usize;
274-
let substs = Substs::for_item(tcx, def_id, |param, substs| {
275-
if param.index == 0 {
276-
if let Some(ty) = self_ty {
277-
if let GenericParamDefKind::Type { .. } = param.kind {
278-
// Handle `Self` first.
279-
return ty.into();
274+
// Collect the segments of the path: we need to substitute arguments
275+
// for parameters throughout the entire path (wherever there are
276+
// generic parameters).
277+
let mut parent_defs = self.tcx().generics_of(def_id);
278+
let count = parent_defs.count();
279+
let mut stack = vec![(def_id, parent_defs)];
280+
while let Some(def_id) = parent_defs.parent {
281+
parent_defs = self.tcx().generics_of(def_id);
282+
stack.push((def_id, parent_defs));
283+
}
284+
285+
// We manually build up the substitution, rather than using convenience
286+
// methods in subst.rs so that we can iterate over the arguments and
287+
// parameters in lock-step linearly, rather than trying to match each pair.
288+
let mut substs: AccumulateVec<[Kind<'tcx>; 8]> = if count <= 8 {
289+
AccumulateVec::Array(ArrayVec::new())
290+
} else {
291+
AccumulateVec::Heap(Vec::with_capacity(count))
292+
};
293+
fn push_kind<'tcx>(substs: &mut AccumulateVec<[Kind<'tcx>; 8]>, kind: Kind<'tcx>) {
294+
match substs {
295+
AccumulateVec::Array(ref mut arr) => arr.push(kind),
296+
AccumulateVec::Heap(ref mut vec) => vec.push(kind),
297+
}
298+
}
299+
300+
// Iterate over each segment of the path.
301+
while let Some((_, defs)) = stack.pop() {
302+
let mut params = defs.params.iter();
303+
let mut next_param = params.next();
304+
305+
// `Self` is handled first.
306+
if let Some(ty) = self_ty {
307+
if let Some(param) = next_param {
308+
if param.index == 0 {
309+
if let GenericParamDefKind::Type { .. } = param.kind {
310+
push_kind(&mut substs, ty.into());
311+
next_param = params.next();
312+
}
280313
}
281314
}
282315
}
283316

284-
let inferred_lifetimes = if lt_provided == 0 {
285-
lt_accepted
286-
} else {
287-
0
288-
};
289-
290-
let param_idx = (param.index as usize - self_offset).saturating_sub(inferred_lifetimes);
291-
292-
if let Some(arg) = generic_args.args.get(param_idx) {
293-
match param.kind {
294-
GenericParamDefKind::Lifetime => match arg {
295-
GenericArg::Lifetime(lt) => {
296-
return self.ast_region_to_region(lt, Some(param)).into();
317+
let args = &generic_args.args;
318+
'args: for arg in args {
319+
while let Some(param) = next_param {
320+
match param.kind {
321+
GenericParamDefKind::Lifetime => match arg {
322+
GenericArg::Lifetime(lt) => {
323+
push_kind(&mut substs,
324+
self.ast_region_to_region(&lt, Some(param)).into());
325+
next_param = params.next();
326+
continue 'args;
327+
}
328+
GenericArg::Type(_) => {
329+
// We expected a lifetime argument, but got a type
330+
// argument. That means we're inferring the lifetimes.
331+
push_kind(&mut substs, tcx.types.re_static.into());
332+
next_param = params.next();
333+
}
334+
}
335+
GenericParamDefKind::Type { .. } => match arg {
336+
GenericArg::Type(ty) => {
337+
push_kind(&mut substs, self.ast_ty_to_ty(&ty).into());
338+
next_param = params.next();
339+
continue 'args;
340+
}
341+
GenericArg::Lifetime(_) => {
342+
break 'args;
343+
}
297344
}
298-
_ => {}
299-
}
300-
GenericParamDefKind::Type { .. } => match arg {
301-
GenericArg::Type(ty) => return self.ast_ty_to_ty(ty).into(),
302-
_ => {}
303345
}
304346
}
305347
}
306348

307-
match param.kind {
308-
GenericParamDefKind::Lifetime => tcx.types.re_static.into(),
309-
GenericParamDefKind::Type { has_default, .. } => {
310-
if infer_types {
311-
// No type parameters were provided, we can infer all.
312-
if !default_needs_object_self(param) {
313-
self.ty_infer_for_def(param, span).into()
314-
} else {
315-
self.ty_infer(span).into()
316-
}
317-
} else if has_default {
318-
// No type parameter provided, but a default exists.
319-
320-
// If we are converting an object type, then the
321-
// `Self` parameter is unknown. However, some of the
322-
// other type parameters may reference `Self` in their
323-
// defaults. This will lead to an ICE if we are not
324-
// careful!
325-
if default_needs_object_self(param) {
326-
struct_span_err!(tcx.sess, span, E0393,
327-
"the type parameter `{}` must be explicitly \
328-
specified",
329-
param.name)
330-
.span_label(span,
331-
format!("missing reference to `{}`", param.name))
332-
.note(&format!("because of the default `Self` reference, \
333-
type parameters must be specified on object \
334-
types"))
335-
.emit();
336-
tcx.types.err.into()
349+
while let Some(param) = next_param {
350+
match param.kind {
351+
GenericParamDefKind::Lifetime => {
352+
push_kind(&mut substs, tcx.types.re_static.into());
353+
}
354+
GenericParamDefKind::Type { has_default, .. } => {
355+
if infer_types {
356+
// No type parameters were provided, we can infer all.
357+
push_kind(&mut substs, if !default_needs_object_self(param) {
358+
self.ty_infer_for_def(param, span).into()
359+
} else {
360+
self.ty_infer(span).into()
361+
});
362+
} else if has_default {
363+
// No type parameter provided, but a default exists.
364+
365+
// If we are converting an object type, then the
366+
// `Self` parameter is unknown. However, some of the
367+
// other type parameters may reference `Self` in their
368+
// defaults. This will lead to an ICE if we are not
369+
// careful!
370+
if default_needs_object_self(param) {
371+
struct_span_err!(tcx.sess, span, E0393,
372+
"the type parameter `{}` must be explicitly \
373+
specified",
374+
param.name)
375+
.span_label(span,
376+
format!("missing reference to `{}`", param.name))
377+
.note(&format!("because of the default `Self` reference, \
378+
type parameters must be specified on object \
379+
types"))
380+
.emit();
381+
push_kind(&mut substs, tcx.types.err.into());
382+
} else {
383+
// This is a default type parameter.
384+
let kind = self.normalize_ty(
385+
span,
386+
tcx.at(span).type_of(param.def_id)
387+
.subst_spanned(tcx, &substs, Some(span))
388+
).into();
389+
push_kind(&mut substs, kind);
390+
}
337391
} else {
338-
// This is a default type parameter.
339-
self.normalize_ty(
340-
span,
341-
tcx.at(span).type_of(param.def_id)
342-
.subst_spanned(tcx, substs, Some(span))
343-
).into()
392+
// We've already errored above about the mismatch.
393+
push_kind(&mut substs, tcx.types.err.into());
344394
}
345-
} else {
346-
// We've already errored above about the mismatch.
347-
tcx.types.err.into()
348395
}
349-
}
396+
};
397+
next_param = params.next();
350398
}
351-
});
399+
}
400+
let substs = self.tcx().intern_substs(&substs);
352401

353402
let assoc_bindings = generic_args.bindings.iter().map(|binding| {
354403
ConvertedBinding {

src/test/ui/error-codes/E0107.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,4 @@ struct Baz<'a, 'b, 'c> {
2929
//~| 2 unexpected lifetime parameters
3030
}
3131

32-
fn main() {
33-
}
32+
fn main() {}

0 commit comments

Comments
 (0)