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))
|
self.next_region_var(RegionVariableOrigin::NLL(origin))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a region inference variable for the given
|
pub fn var_for_def(&self,
|
||||||
/// region parameter definition.
|
span: Span,
|
||||||
pub fn region_var_for_def(&self,
|
param: &ty::GenericParamDef)
|
||||||
span: Span,
|
-> UnpackedKind<'tcx> {
|
||||||
def: &ty::GenericParamDef)
|
match param.kind {
|
||||||
-> ty::Region<'tcx> {
|
GenericParamDefKind::Lifetime => {
|
||||||
self.next_region_var(EarlyBoundRegion(span, def.name))
|
// 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
|
UnpackedKind::Type(self.tcx.mk_var(ty_var_id))
|
||||||
/// 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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a set of generics defined on a type or impl, returns a substitution mapping each
|
/// 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)
|
def_id: DefId)
|
||||||
-> &'tcx Substs<'tcx> {
|
-> &'tcx Substs<'tcx> {
|
||||||
Substs::for_item(self.tcx, def_id, |param, _| {
|
Substs::for_item(self.tcx, def_id, |param, _| {
|
||||||
match param.kind {
|
self.var_for_def(span, param)
|
||||||
GenericParamDefKind::Lifetime => {
|
|
||||||
UnpackedKind::Lifetime(self.region_var_for_def(span, param))
|
|
||||||
}
|
|
||||||
GenericParamDefKind::Type(_) => {
|
|
||||||
UnpackedKind::Type(self.type_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| {
|
let substs = Substs::for_item(self, def_id, |param, substs| {
|
||||||
match param.kind {
|
match param.kind {
|
||||||
GenericParamDefKind::Lifetime => bug!(),
|
GenericParamDefKind::Lifetime => bug!(),
|
||||||
GenericParamDefKind::Type(_) => {
|
GenericParamDefKind::Type(ty_param) => {
|
||||||
if param.index == 0 {
|
if param.index == 0 {
|
||||||
UnpackedKind::Type(ty)
|
UnpackedKind::Type(ty)
|
||||||
} else {
|
} else {
|
||||||
match param.kind {
|
assert!(ty_param.has_default);
|
||||||
ty::GenericParamDefKind::Type(ty_param) => {
|
UnpackedKind::Type(self.type_of(param.def_id).subst(self, substs))
|
||||||
assert!(ty_param.has_default);
|
|
||||||
UnpackedKind::Type(
|
|
||||||
self.type_of(param.def_id).subst(self, substs))
|
|
||||||
}
|
|
||||||
_ => unreachable!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -276,7 +276,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||||
};
|
};
|
||||||
UnpackedKind::Lifetime(lt)
|
UnpackedKind::Lifetime(lt)
|
||||||
}
|
}
|
||||||
GenericParamDefKind::Type(_) => {
|
GenericParamDefKind::Type(ty) => {
|
||||||
let i = param.index as usize;
|
let i = param.index as usize;
|
||||||
|
|
||||||
// Handle Self first, so we can adjust the index to match the AST.
|
// 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);
|
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 i = i - (lt_accepted + own_self);
|
||||||
let ty = if i < ty_provided {
|
let ty = if i < ty_provided {
|
||||||
// A provided type parameter.
|
// A provided type parameter.
|
||||||
self.ast_ty_to_ty(¶meters.types[i])
|
self.ast_ty_to_ty(¶meters.types[i])
|
||||||
} else if infer_types {
|
} else if infer_types {
|
||||||
// No type parameters were provided, we can infer all.
|
// 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)
|
self.ty_infer_for_def(param, span)
|
||||||
} else {
|
} else {
|
||||||
self.ty_infer(span)
|
self.ty_infer(span)
|
||||||
};
|
}
|
||||||
ty_var
|
} else if ty.has_default {
|
||||||
} else if has_default {
|
|
||||||
// No type parameter provided, but a default exists.
|
// No type parameter provided, but a default exists.
|
||||||
|
|
||||||
// If we are converting an object type, then the
|
// 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 provided = &segment.parameters;
|
||||||
let own_counts = method_generics.own_counts();
|
let own_counts = method_generics.own_counts();
|
||||||
Substs::for_item(self.tcx, pick.item.def_id, |param, _| {
|
Substs::for_item(self.tcx, pick.item.def_id, |param, _| {
|
||||||
match param.kind {
|
let i = param.index as usize;
|
||||||
GenericParamDefKind::Lifetime => {
|
if i < parent_substs.len() {
|
||||||
let i = param.index as usize;
|
parent_substs[i].unpack()
|
||||||
let lt = if i < parent_substs.len() {
|
} else {
|
||||||
parent_substs.region_at(i)
|
match param.kind {
|
||||||
} else if let Some(lifetime)
|
GenericParamDefKind::Lifetime => {
|
||||||
= provided.as_ref().and_then(|p| p.lifetimes.get(i - parent_substs.len())) {
|
if let Some(lifetime) = provided.as_ref().and_then(|p| {
|
||||||
AstConv::ast_region_to_region(self.fcx, lifetime, Some(param))
|
p.lifetimes.get(i - parent_substs.len())
|
||||||
} else {
|
}) {
|
||||||
self.region_var_for_def(self.span, param)
|
return UnpackedKind::Lifetime(
|
||||||
};
|
AstConv::ast_region_to_region(self.fcx, lifetime, Some(param)));
|
||||||
UnpackedKind::Lifetime(lt)
|
}
|
||||||
}
|
}
|
||||||
GenericParamDefKind::Type(_) => {
|
GenericParamDefKind::Type(_) => {
|
||||||
let i = param.index as usize;
|
if let Some(ast_ty) = provided.as_ref().and_then(|p| {
|
||||||
let ty = if i < parent_substs.len() {
|
p.types.get(i - parent_substs.len() - own_counts.lifetimes)
|
||||||
parent_substs.type_at(i)
|
}) {
|
||||||
} else if let Some(ast_ty)
|
return UnpackedKind::Type(self.to_ty(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)
|
|
||||||
}
|
}
|
||||||
|
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>`
|
// Construct a trait-reference `self_ty : Trait<input_tys>`
|
||||||
let substs = Substs::for_item(self.tcx, trait_def_id, |param, _| {
|
let substs = Substs::for_item(self.tcx, trait_def_id, |param, _| {
|
||||||
match param.kind {
|
match param.kind {
|
||||||
GenericParamDefKind::Lifetime => {
|
GenericParamDefKind::Lifetime => {}
|
||||||
UnpackedKind::Lifetime(self.region_var_for_def(span, param))
|
|
||||||
}
|
|
||||||
GenericParamDefKind::Type(_) => {
|
GenericParamDefKind::Type(_) => {
|
||||||
let ty = if param.index == 0 {
|
if param.index == 0 {
|
||||||
self_ty
|
return UnpackedKind::Type(self_ty);
|
||||||
} else if let Some(ref input_types) = opt_input_types {
|
} else if let Some(ref input_types) = opt_input_types {
|
||||||
input_types[param.index as usize - 1]
|
return UnpackedKind::Type(input_types[param.index as usize - 1]);
|
||||||
} else {
|
}
|
||||||
self.type_var_for_def(span, param)
|
|
||||||
};
|
|
||||||
UnpackedKind::Type(ty)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.var_for_def(span, param)
|
||||||
});
|
});
|
||||||
|
|
||||||
let trait_ref = ty::TraitRef::new(trait_def_id, substs);
|
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)
|
xform_fn_sig.subst(self.tcx, substs)
|
||||||
} else {
|
} else {
|
||||||
let substs = Substs::for_item(self.tcx, method, |param, _| {
|
let substs = Substs::for_item(self.tcx, method, |param, _| {
|
||||||
match param.kind {
|
let i = param.index as usize;
|
||||||
GenericParamDefKind::Lifetime => {
|
if i < substs.len() {
|
||||||
let i = param.index as usize;
|
substs[i].unpack()
|
||||||
let lt = if i < substs.len() {
|
} else {
|
||||||
substs.region_at(i)
|
match param.kind {
|
||||||
} else {
|
GenericParamDefKind::Lifetime => {
|
||||||
// In general, during probe we erase regions. See
|
// In general, during probe we erase regions. See
|
||||||
// `impl_self_ty()` for an explanation.
|
// `impl_self_ty()` for an explanation.
|
||||||
self.tcx.types.re_erased
|
UnpackedKind::Lifetime(self.tcx.types.re_erased)
|
||||||
};
|
}
|
||||||
UnpackedKind::Lifetime(lt)
|
GenericParamDefKind::Type(_) => self.var_for_def(self.span, param),
|
||||||
}
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1746,7 +1746,11 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
fn ty_infer_for_def(&self,
|
fn ty_infer_for_def(&self,
|
||||||
ty_param_def: &ty::GenericParamDef,
|
ty_param_def: &ty::GenericParamDef,
|
||||||
span: Span) -> Ty<'tcx> {
|
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,
|
fn projected_ty_from_poly_trait_ref(&self,
|
||||||
|
@ -4759,17 +4763,26 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
(None, None) => (0, false)
|
(None, None) => (0, false)
|
||||||
};
|
};
|
||||||
let substs = Substs::for_item(self.tcx, def.def_id(), |param, substs| {
|
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 {
|
match param.kind {
|
||||||
GenericParamDefKind::Lifetime => {
|
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, _)| {
|
let lifetimes = segment.map_or(&[][..], |(s, _)| {
|
||||||
s.parameters.as_ref().map_or(&[][..], |p| &p.lifetimes[..])
|
s.parameters.as_ref().map_or(&[][..], |p| &p.lifetimes[..])
|
||||||
});
|
});
|
||||||
|
@ -4782,21 +4795,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
UnpackedKind::Lifetime(lt)
|
UnpackedKind::Lifetime(lt)
|
||||||
}
|
}
|
||||||
GenericParamDefKind::Type(_) => {
|
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, _)| {
|
let (types, infer_types) = segment.map_or((&[][..], true), |(s, _)| {
|
||||||
(s.parameters.as_ref().map_or(&[][..], |p| &p.types[..]), s.infer_types)
|
(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!()
|
_ => unreachable!()
|
||||||
};
|
};
|
||||||
|
|
||||||
let ty = if let Some(ast_ty) = types.get(i) {
|
if let Some(ast_ty) = types.get(i) {
|
||||||
// A provided type parameter.
|
// A provided type parameter.
|
||||||
self.to_ty(ast_ty)
|
UnpackedKind::Type(self.to_ty(ast_ty))
|
||||||
} else if !infer_types && has_default {
|
} else if !infer_types && has_default {
|
||||||
// No type parameter provided, but a default exists.
|
// No type parameter provided, but a default exists.
|
||||||
let default = self.tcx.type_of(param.def_id);
|
let default = self.tcx.type_of(param.def_id);
|
||||||
self.normalize_ty(
|
UnpackedKind::Type(self.normalize_ty(
|
||||||
span,
|
span,
|
||||||
default.subst_spanned(self.tcx, substs, Some(span))
|
default.subst_spanned(self.tcx, substs, Some(span))
|
||||||
)
|
))
|
||||||
} else {
|
} else {
|
||||||
// No type parameters were provided, we can infer all.
|
// No type parameters were provided, we can infer all.
|
||||||
// This can also be reached in some error cases:
|
// This can also be reached in some error cases:
|
||||||
// We prefer to use inference variables instead of
|
// We prefer to use inference variables instead of
|
||||||
// TyError to let type inference recover somewhat.
|
// TyError to let type inference recover somewhat.
|
||||||
self.type_var_for_def(span, param)
|
self.var_for_def(span, param)
|
||||||
};
|
}
|
||||||
UnpackedKind::Type(ty)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue