Skip to content

Commit 08d49a6

Browse files
committed
Refactor mod/check (part viii)
1 parent 5f2588f commit 08d49a6

File tree

2 files changed

+69
-51
lines changed

2 files changed

+69
-51
lines changed

src/librustc/ty/subst.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -226,9 +226,9 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
226226
}
227227

228228
fn fill_item<F>(substs: &mut AccumulateVec<[Kind<'tcx>; 8]>,
229-
tcx: TyCtxt<'a, 'gcx, 'tcx>,
230-
defs: &ty::Generics,
231-
mk_kind: &mut F)
229+
tcx: TyCtxt<'a, 'gcx, 'tcx>,
230+
defs: &ty::Generics,
231+
mk_kind: &mut F)
232232
where F: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> Kind<'tcx>
233233
{
234234
if let Some(def_id) = defs.parent {
@@ -238,7 +238,7 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
238238
Substs::fill_single(substs, defs, mk_kind)
239239
}
240240

241-
pub fn fill_single<F>(substs: &mut AccumulateVec<[Kind<'tcx>; 8]>,
241+
fn fill_single<F>(substs: &mut AccumulateVec<[Kind<'tcx>; 8]>,
242242
defs: &ty::Generics,
243243
mk_kind: &mut F)
244244
where F: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> Kind<'tcx>

src/librustc_typeck/check/mod.rs

Lines changed: 65 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -4909,6 +4909,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
49094909
// segment belong to, let's sort out the parameters that the user
49104910
// provided (if any) into their appropriate spaces. We'll also report
49114911
// errors if type parameters are provided in an inappropriate place.
4912+
49124913
let mut generic_segs = HashSet::new();
49134914
for PathSeg(_, index) in &path_segs {
49144915
generic_segs.insert(index);
@@ -4937,104 +4938,115 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
49374938
// variables. If the user provided some types, we may still need
49384939
// to add defaults. If the user provided *too many* types, that's
49394940
// a problem.
4940-
let mut infer_lifetimes = FxHashMap();
4941+
49414942
let mut supress_errors = FxHashMap();
49424943
for &PathSeg(def_id, index) in &path_segs {
49434944
let seg = &segments[index];
49444945
let generics = self.tcx.generics_of(def_id);
4946+
// `impl Trait` is treated as a normal generic parameter internally,
4947+
// but we don't allow users to specify the parameter's value
4948+
// explicitly, so we have to do some error-checking here.
49454949
let supress_mismatch = self.check_impl_trait(span, seg, &generics);
49464950
supress_errors.insert(index,
49474951
self.check_generic_arg_count(span, seg, &generics, false, supress_mismatch));
4948-
let inferred_lifetimes = if if let Some(ref data) = seg.args {
4949-
!data.args.iter().any(|arg| match arg {
4950-
GenericArg::Lifetime(_) => true,
4951-
_ => false,
4952-
})
4953-
} else {
4954-
true
4955-
} {
4956-
generics.own_counts().lifetimes
4957-
} else {
4958-
0
4959-
};
4960-
infer_lifetimes.insert(index, inferred_lifetimes);
49614952
}
49624953

49634954
let has_self = path_segs.last().map(|PathSeg(def_id, _)| {
49644955
self.tcx.generics_of(*def_id).has_self
49654956
}).unwrap_or(false);
49664957

4958+
// Collect the segments of the path: we need to substitute arguments
4959+
// for parameters throughout the entire path (wherever there are
4960+
// generic parameters).
49674961
let def_id = def.def_id();
49684962
let mut parent_defs = self.tcx.generics_of(def_id);
49694963
let count = parent_defs.count();
4970-
let mut substs: AccumulateVec<[Kind<'tcx>; 8]> = if count <= 8 {
4971-
AccumulateVec::Array(ArrayVec::new())
4972-
} else {
4973-
AccumulateVec::Heap(Vec::with_capacity(count))
4974-
};
49754964
let mut stack = vec![(def_id, parent_defs)];
49764965
while let Some(def_id) = parent_defs.parent {
49774966
parent_defs = self.tcx.generics_of(def_id);
49784967
stack.push((def_id, parent_defs));
49794968
}
4980-
macro_rules! push_to_substs {
4981-
($kind:expr) => {
4982-
let k = $kind;
4983-
match substs {
4984-
AccumulateVec::Array(ref mut arr) => arr.push(k),
4985-
AccumulateVec::Heap(ref mut vec) => vec.push(k),
4986-
}
4987-
}
4969+
4970+
// We manually build up the substitution, rather than using convenience
4971+
// methods in subst.rs so that we can iterate over the arguments and
4972+
// parameters in lock-step linearly, rather than trying to match each pair.
4973+
let mut substs: AccumulateVec<[Kind<'tcx>; 8]> = if count <= 8 {
4974+
AccumulateVec::Array(ArrayVec::new())
4975+
} else {
4976+
AccumulateVec::Heap(Vec::with_capacity(count))
49884977
};
4978+
fn push_kind<'tcx>(substs: &mut AccumulateVec<[Kind<'tcx>; 8]>, kind: Kind<'tcx>) {
4979+
match substs {
4980+
AccumulateVec::Array(ref mut arr) => arr.push(kind),
4981+
AccumulateVec::Heap(ref mut vec) => vec.push(kind),
4982+
}
4983+
}
4984+
4985+
// Iterate over each segment of the path.
49894986
while let Some((def_id, defs)) = stack.pop() {
49904987
let mut params = defs.params.iter();
49914988
let mut next_param = params.next();
4989+
4990+
// `Self` is handled first.
49924991
if has_self {
49934992
if let Some(param) = next_param {
49944993
if param.index == 0 {
49954994
if let GenericParamDefKind::Type { .. } = param.kind {
4996-
// Handle `Self` first, so we can adjust the index to match the AST.
4997-
push_to_substs!(opt_self_ty.map(|ty| ty.into()).unwrap_or_else(|| {
4998-
self.var_for_def(span, param)
4999-
}));
4995+
push_kind(&mut substs, opt_self_ty.map(|ty| ty.into())
4996+
.unwrap_or_else(|| self.var_for_def(span, param)));
50004997
next_param = params.next();
50014998
}
50024999
}
50035000
}
50045001
}
50055002

50065003
let mut infer_types = true;
5004+
// Check whether this segment takes generic arguments.
50075005
if let Some(&PathSeg(_, index)) = path_segs
50085006
.iter()
50095007
.find(|&PathSeg(did, _)| *did == def_id) {
5008+
// If we've encountered an `impl Trait`-related error, we're just
5009+
// going to infer the arguments for better error messages.
50105010
if !supress_errors[&index] {
50115011
infer_types = segments[index].infer_types;
5012+
// Check whether the user has provided generic arguments.
50125013
if let Some(ref data) = segments[index].args {
50135014
let args = &data.args;
5015+
// We're going to iterate through the generic arguments that the user
5016+
// provided, matching them with the generic parameters we expect.
5017+
// Mismatches can occur as a result of elided lifetimes, or for malformed
5018+
// input. We try to handle both sensibly.
50145019
'args: for arg in args {
50155020
while let Some(param) = next_param {
50165021
match param.kind {
50175022
GenericParamDefKind::Lifetime => match arg {
50185023
GenericArg::Lifetime(lt) => {
5019-
push_to_substs!(AstConv::ast_region_to_region(self,
5020-
lt, Some(param)).into());
5024+
push_kind(&mut substs,
5025+
AstConv::ast_region_to_region(self, lt, Some(param))
5026+
.into());
50215027
next_param = params.next();
50225028
continue 'args;
50235029
}
50245030
GenericArg::Type(_) => {
5025-
// We're inferring a lifetime.
5026-
push_to_substs!(
5031+
// We expected a lifetime argument, but got a type
5032+
// argument. That means we're inferring the lifetimes.
5033+
push_kind(&mut substs,
50275034
self.re_infer(span, Some(param)).unwrap().into());
50285035
next_param = params.next();
50295036
}
50305037
}
50315038
GenericParamDefKind::Type { .. } => match arg {
50325039
GenericArg::Type(ty) => {
5033-
push_to_substs!(self.to_ty(ty).into());
5040+
push_kind(&mut substs, self.to_ty(ty).into());
50345041
next_param = params.next();
50355042
continue 'args;
50365043
}
50375044
GenericArg::Lifetime(_) => {
5045+
// We expected a type argument, but got a lifetime
5046+
// argument. This is an error, but we need to handle it
5047+
// gracefully so we can report sensible errors. In this
5048+
// case, we're simply going to infer the remaining
5049+
// arguments.
50385050
self.tcx.sess.delay_span_bug(span,
50395051
"found a GenericArg::Lifetime where a \
50405052
GenericArg::Type was expected");
@@ -5043,34 +5055,40 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
50435055
}
50445056
}
50455057
}
5046-
// If we get to this point, we have a GenericArg that is not matched
5047-
// by a GenericParamDef: i.e. the user supplied too many generic args.
5058+
// We should never be able to reach this point with well-formed input.
5059+
// Getting to this point means the user supplied more arguments than
5060+
// there are parameters.
50485061
self.tcx.sess.delay_span_bug(span,
50495062
"GenericArg did not have matching GenericParamDef");
50505063
}
50515064
}
50525065
}
50535066
}
50545067

5068+
// If there are fewer arguments than parameters, it means
5069+
// we're inferring the remaining arguments.
50555070
while let Some(param) = next_param {
50565071
match param.kind {
50575072
GenericParamDefKind::Lifetime => {
5058-
push_to_substs!(self.re_infer(span, Some(param)).unwrap().into());
5073+
push_kind(&mut substs, self.re_infer(span, Some(param)).unwrap().into());
50595074
}
50605075
GenericParamDefKind::Type { has_default, .. } => {
50615076
if !infer_types && has_default {
5062-
// No type parameter provided, but a default exists.
5077+
// If we have a default, then we it doesn't matter that we're not
5078+
// inferring the type arguments: we provide the default where any
5079+
// is missing.
50635080
let default = self.tcx.type_of(param.def_id);
5064-
push_to_substs!(self.normalize_ty(
5081+
let kind = self.normalize_ty(
50655082
span,
50665083
default.subst_spanned(self.tcx, &substs, Some(span))
5067-
).into());
5084+
).into();
5085+
push_kind(&mut substs, kind);
50685086
} else {
5069-
// No type parameters were provided, we can infer all.
5070-
// This can also be reached in some error cases:
5071-
// We prefer to use inference variables instead of
5072-
// TyError to let type inference recover somewhat.
5073-
push_to_substs!(self.var_for_def(span, param));
5087+
// If no type arguments were provided, we have to infer them.
5088+
// This case also occurs as a result of some malformed input, e.g.
5089+
// a lifetime argument being given instead of a type paramter.
5090+
// Using inference instead of `TyError` gives better error messages.
5091+
push_kind(&mut substs, self.var_for_def(span, param));
50745092
}
50755093
}
50765094
}

0 commit comments

Comments
 (0)