1
Fork 0

Clean up shared subst code

This commit is contained in:
varkor 2018-05-14 19:57:59 +01:00
parent d9190da982
commit 3ae2468261
7 changed files with 100 additions and 143 deletions

View file

@ -905,34 +905,34 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
self.next_region_var(RegionVariableOrigin::NLL(origin))
}
/// Create a region inference variable for the given
/// region parameter definition.
pub fn region_var_for_def(&self,
span: Span,
def: &ty::GenericParamDef)
-> ty::Region<'tcx> {
self.next_region_var(EarlyBoundRegion(span, def.name))
}
pub fn var_for_def(&self,
span: Span,
param: &ty::GenericParamDef)
-> UnpackedKind<'tcx> {
match param.kind {
GenericParamDefKind::Lifetime => {
// Create a region inference variable for the given
// region parameter definition.
UnpackedKind::Lifetime(self.next_region_var(EarlyBoundRegion(span, param.name)))
}
GenericParamDefKind::Type(_) => {
// Create a type inference variable for the given
// type parameter definition. The substitutions are
// for actual parameters that may be referred to by
// the default of this type parameter, if it exists.
// E.g. `struct Foo<A, B, C = (A, B)>(...);` when
// used in a path such as `Foo::<T, U>::new()` will
// use an inference variable for `C` with `[T, U]`
// as the substitutions for the default, `(T, U)`.
let ty_var_id = self.type_variables
.borrow_mut()
.new_var(self.universe(),
false,
TypeVariableOrigin::TypeParameterDefinition(span, param.name));
/// Create a type inference variable for the given
/// type parameter definition. The substitutions are
/// for actual parameters that may be referred to by
/// the default of this type parameter, if it exists.
/// E.g. `struct Foo<A, B, C = (A, B)>(...);` when
/// used in a path such as `Foo::<T, U>::new()` will
/// use an inference variable for `C` with `[T, U]`
/// as the substitutions for the default, `(T, U)`.
pub fn type_var_for_def(&self,
span: Span,
def: &ty::GenericParamDef)
-> Ty<'tcx> {
let ty_var_id = self.type_variables
.borrow_mut()
.new_var(self.universe(),
false,
TypeVariableOrigin::TypeParameterDefinition(span, def.name));
self.tcx.mk_var(ty_var_id)
UnpackedKind::Type(self.tcx.mk_var(ty_var_id))
}
}
}
/// Given a set of generics defined on a type or impl, returns a substitution mapping each
@ -942,14 +942,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
def_id: DefId)
-> &'tcx Substs<'tcx> {
Substs::for_item(self.tcx, def_id, |param, _| {
match param.kind {
GenericParamDefKind::Lifetime => {
UnpackedKind::Lifetime(self.region_var_for_def(span, param))
}
GenericParamDefKind::Type(_) => {
UnpackedKind::Type(self.type_var_for_def(span, param))
}
}
self.var_for_def(span, param)
})
}

View file

@ -2329,18 +2329,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
let substs = Substs::for_item(self, def_id, |param, substs| {
match param.kind {
GenericParamDefKind::Lifetime => bug!(),
GenericParamDefKind::Type(_) => {
GenericParamDefKind::Type(ty_param) => {
if param.index == 0 {
UnpackedKind::Type(ty)
} else {
match param.kind {
ty::GenericParamDefKind::Type(ty_param) => {
assert!(ty_param.has_default);
UnpackedKind::Type(
self.type_of(param.def_id).subst(self, substs))
}
_ => unreachable!()
}
assert!(ty_param.has_default);
UnpackedKind::Type(self.type_of(param.def_id).subst(self, substs))
}
}
}

View file

@ -276,7 +276,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
};
UnpackedKind::Lifetime(lt)
}
GenericParamDefKind::Type(_) => {
GenericParamDefKind::Type(ty) => {
let i = param.index as usize;
// Handle Self first, so we can adjust the index to match the AST.
@ -284,24 +284,18 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
return UnpackedKind::Type(ty);
}
let has_default = match param.kind {
GenericParamDefKind::Type(ty) => ty.has_default,
_ => unreachable!()
};
let i = i - (lt_accepted + own_self);
let ty = if i < ty_provided {
// A provided type parameter.
self.ast_ty_to_ty(&parameters.types[i])
} else if infer_types {
// No type parameters were provided, we can infer all.
let ty_var = if !default_needs_object_self(param) {
if !default_needs_object_self(param) {
self.ty_infer_for_def(param, span)
} else {
self.ty_infer(span)
};
ty_var
} else if has_default {
}
} else if ty.has_default {
// No type parameter provided, but a default exists.
// If we are converting an object type, then the

View file

@ -318,36 +318,28 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
let provided = &segment.parameters;
let own_counts = method_generics.own_counts();
Substs::for_item(self.tcx, pick.item.def_id, |param, _| {
match param.kind {
GenericParamDefKind::Lifetime => {
let i = param.index as usize;
let lt = if i < parent_substs.len() {
parent_substs.region_at(i)
} else if let Some(lifetime)
= provided.as_ref().and_then(|p| p.lifetimes.get(i - parent_substs.len())) {
AstConv::ast_region_to_region(self.fcx, lifetime, Some(param))
} else {
self.region_var_for_def(self.span, param)
};
UnpackedKind::Lifetime(lt)
}
GenericParamDefKind::Type(_) => {
let i = param.index as usize;
let ty = if i < parent_substs.len() {
parent_substs.type_at(i)
} else if let Some(ast_ty)
= provided.as_ref().and_then(|p| {
let idx =
i - parent_substs.len() - own_counts.lifetimes;
p.types.get(idx)
})
{
self.to_ty(ast_ty)
} else {
self.type_var_for_def(self.span, param)
};
UnpackedKind::Type(ty)
let i = param.index as usize;
if i < parent_substs.len() {
parent_substs[i].unpack()
} else {
match param.kind {
GenericParamDefKind::Lifetime => {
if let Some(lifetime) = provided.as_ref().and_then(|p| {
p.lifetimes.get(i - parent_substs.len())
}) {
return UnpackedKind::Lifetime(
AstConv::ast_region_to_region(self.fcx, lifetime, Some(param)));
}
}
GenericParamDefKind::Type(_) => {
if let Some(ast_ty) = provided.as_ref().and_then(|p| {
p.types.get(i - parent_substs.len() - own_counts.lifetimes)
}) {
return UnpackedKind::Type(self.to_ty(ast_ty));
}
}
}
self.var_for_def(self.span, param)
}
})
}

View file

@ -256,20 +256,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// Construct a trait-reference `self_ty : Trait<input_tys>`
let substs = Substs::for_item(self.tcx, trait_def_id, |param, _| {
match param.kind {
GenericParamDefKind::Lifetime => {
UnpackedKind::Lifetime(self.region_var_for_def(span, param))
}
GenericParamDefKind::Lifetime => {}
GenericParamDefKind::Type(_) => {
let ty = if param.index == 0 {
self_ty
if param.index == 0 {
return UnpackedKind::Type(self_ty);
} else if let Some(ref input_types) = opt_input_types {
input_types[param.index as usize - 1]
} else {
self.type_var_for_def(span, param)
};
UnpackedKind::Type(ty)
return UnpackedKind::Type(input_types[param.index as usize - 1]);
}
}
}
self.var_for_def(span, param)
});
let trait_ref = ty::TraitRef::new(trait_def_id, substs);

View file

@ -1389,26 +1389,17 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
xform_fn_sig.subst(self.tcx, substs)
} else {
let substs = Substs::for_item(self.tcx, method, |param, _| {
match param.kind {
GenericParamDefKind::Lifetime => {
let i = param.index as usize;
let lt = if i < substs.len() {
substs.region_at(i)
} else {
let i = param.index as usize;
if i < substs.len() {
substs[i].unpack()
} else {
match param.kind {
GenericParamDefKind::Lifetime => {
// In general, during probe we erase regions. See
// `impl_self_ty()` for an explanation.
self.tcx.types.re_erased
};
UnpackedKind::Lifetime(lt)
}
GenericParamDefKind::Type(_) => {
let i = param.index as usize;
let ty = if i < substs.len() {
substs.type_at(i)
} else {
self.type_var_for_def(self.span, param)
};
UnpackedKind::Type(ty)
UnpackedKind::Lifetime(self.tcx.types.re_erased)
}
GenericParamDefKind::Type(_) => self.var_for_def(self.span, param),
}
}
});

View file

@ -1746,7 +1746,11 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
fn ty_infer_for_def(&self,
ty_param_def: &ty::GenericParamDef,
span: Span) -> Ty<'tcx> {
self.type_var_for_def(span, ty_param_def)
if let UnpackedKind::Type(ty) = self.var_for_def(span, ty_param_def) {
ty
} else {
unreachable!()
}
}
fn projected_ty_from_poly_trait_ref(&self,
@ -4759,17 +4763,26 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
(None, None) => (0, false)
};
let substs = Substs::for_item(self.tcx, def.def_id(), |param, substs| {
let mut i = param.index as usize;
let segment = if i < fn_start {
if let GenericParamDefKind::Type(_) = param.kind {
// Handle Self first, so we can adjust the index to match the AST.
if has_self && i == 0 {
return opt_self_ty.map(|ty| UnpackedKind::Type(ty)).unwrap_or_else(|| {
self.var_for_def(span, param)
});
}
}
i -= has_self as usize;
type_segment
} else {
i -= fn_start;
fn_segment
};
match param.kind {
GenericParamDefKind::Lifetime => {
let mut i = param.index as usize;
let segment = if i < fn_start {
i -= has_self as usize;
type_segment
} else {
i -= fn_start;
fn_segment
};
let lifetimes = segment.map_or(&[][..], |(s, _)| {
s.parameters.as_ref().map_or(&[][..], |p| &p.lifetimes[..])
});
@ -4782,21 +4795,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
UnpackedKind::Lifetime(lt)
}
GenericParamDefKind::Type(_) => {
let mut i = param.index as usize;
let segment = if i < fn_start {
// Handle Self first, so we can adjust the index to match the AST.
if has_self && i == 0 {
return UnpackedKind::Type(opt_self_ty.unwrap_or_else(|| {
self.type_var_for_def(span, param)
}));
}
i -= has_self as usize;
type_segment
} else {
i -= fn_start;
fn_segment
};
let (types, infer_types) = segment.map_or((&[][..], true), |(s, _)| {
(s.parameters.as_ref().map_or(&[][..], |p| &p.types[..]), s.infer_types)
});
@ -4811,24 +4809,23 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
_ => unreachable!()
};
let ty = if let Some(ast_ty) = types.get(i) {
if let Some(ast_ty) = types.get(i) {
// A provided type parameter.
self.to_ty(ast_ty)
UnpackedKind::Type(self.to_ty(ast_ty))
} else if !infer_types && has_default {
// No type parameter provided, but a default exists.
let default = self.tcx.type_of(param.def_id);
self.normalize_ty(
UnpackedKind::Type(self.normalize_ty(
span,
default.subst_spanned(self.tcx, substs, Some(span))
)
))
} else {
// No type parameters were provided, we can infer all.
// This can also be reached in some error cases:
// We prefer to use inference variables instead of
// TyError to let type inference recover somewhat.
self.type_var_for_def(span, param)
};
UnpackedKind::Type(ty)
self.var_for_def(span, param)
}
}
}
});