Clean up shared subst code
This commit is contained in:
parent
d9190da982
commit
3ae2468261
7 changed files with 100 additions and 143 deletions
|
@ -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)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(¶meters.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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue