1
Fork 0

Refactor Substs methods on generic parameters

This commit is contained in:
varkor 2018-05-14 18:27:13 +01:00
parent 030f10f752
commit d9190da982
15 changed files with 395 additions and 308 deletions

View file

@ -21,9 +21,9 @@ use hir::def_id::DefId;
use middle::free_region::RegionRelations;
use middle::region;
use middle::lang_items;
use ty::subst::Substs;
use ty::subst::{UnpackedKind, Substs};
use ty::{TyVid, IntVid, FloatVid};
use ty::{self, Ty, TyCtxt};
use ty::{self, Ty, TyCtxt, GenericParamDefKind};
use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
use ty::fold::TypeFoldable;
use ty::relate::RelateResult;
@ -941,10 +941,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
span: Span,
def_id: DefId)
-> &'tcx Substs<'tcx> {
Substs::for_item(self.tcx, def_id, |def, _| {
self.region_var_for_def(span, def)
}, |def, _| {
self.type_var_for_def(span, def)
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))
}
}
})
}

View file

@ -22,8 +22,8 @@ use hir::def_id::DefId;
use infer::outlives::env::OutlivesEnvironment;
use middle::region;
use middle::const_val::ConstEvalErr;
use ty::subst::Substs;
use ty::{self, AdtKind, Slice, Ty, TyCtxt, TypeFoldable, ToPredicate};
use ty::subst::{UnpackedKind, Substs};
use ty::{self, AdtKind, Slice, Ty, TyCtxt, GenericParamDefKind, TypeFoldable, ToPredicate};
use ty::error::{ExpectedFound, TypeError};
use infer::{InferCtxt};
@ -841,10 +841,16 @@ fn vtable_methods<'a, 'tcx>(
// the method may have some early-bound lifetimes, add
// regions for those
let substs = trait_ref.map_bound(|trait_ref| {
Substs::for_item(
tcx, def_id,
|_, _| tcx.types.re_erased,
|def, _| trait_ref.substs.type_for_def(def))
Substs::for_item(tcx, def_id, |param, _| {
match param.kind {
GenericParamDefKind::Lifetime => {
UnpackedKind::Lifetime(tcx.types.re_erased)
}
GenericParamDefKind::Type(_) => {
UnpackedKind::Type(trait_ref.substs.type_for_def(param))
}
}
})
});
// the trait type may have higher-ranked lifetimes in it;

View file

@ -32,7 +32,7 @@ use middle::lang_items;
use middle::resolve_lifetime::{self, ObjectLifetimeDefault};
use middle::stability;
use mir::{self, Mir, interpret};
use ty::subst::{Kind, Substs, Subst};
use ty::subst::{Kind, UnpackedKind, Substs, Subst};
use ty::ReprOptions;
use ty::Instance;
use traits;
@ -44,6 +44,7 @@ use ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predic
use ty::RegionKind;
use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
use ty::TypeVariants::*;
use ty::GenericParamDefKind;
use ty::layout::{LayoutDetails, TargetDataLayout};
use ty::maps;
use ty::steal::Steal;
@ -2325,16 +2326,22 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> {
let def_id = self.require_lang_item(lang_items::OwnedBoxLangItem);
let adt_def = self.adt_def(def_id);
let substs = Substs::for_item(self, def_id, |_, _| bug!(), |def, substs| {
if def.index == 0 {
ty
} else {
match def.kind {
ty::GenericParamDefKind::Type(ty_param) => {
assert!(ty_param.has_default);
self.type_of(def.def_id).subst(self, substs)
let substs = Substs::for_item(self, def_id, |param, substs| {
match param.kind {
GenericParamDefKind::Lifetime => bug!(),
GenericParamDefKind::Type(_) => {
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!()
}
}
_ => unreachable!()
}
}
});

View file

@ -11,7 +11,7 @@
// Type substitutions.
use hir::def_id::DefId;
use ty::{self, Lift, Slice, Region, Ty, TyCtxt};
use ty::{self, Lift, Slice, Region, Ty, TyCtxt, GenericParamDefKind};
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use serialize::{self, Encodable, Encoder, Decodable, Decoder};
@ -174,80 +174,80 @@ impl<'tcx> Decodable for Kind<'tcx> {
}
}
/// A substitution mapping type/region parameters to new values.
/// A substitution mapping generic parameters to new values.
pub type Substs<'tcx> = Slice<Kind<'tcx>>;
impl<'a, 'gcx, 'tcx> Substs<'tcx> {
/// Creates a Substs that maps each generic parameter to itself.
pub fn identity_for_item(tcx: TyCtxt<'a, 'gcx, 'tcx>, def_id: DefId)
-> &'tcx Substs<'tcx> {
Substs::for_item(tcx, def_id, |def, _| {
tcx.mk_region(ty::ReEarlyBound(def.to_early_bound_region_data()))
}, |def, _| tcx.mk_ty_param_from_def(def))
Substs::for_item(tcx, def_id, |param, _| {
match param.kind {
GenericParamDefKind::Lifetime => {
UnpackedKind::Lifetime(
tcx.mk_region(ty::ReEarlyBound(param.to_early_bound_region_data())))
}
GenericParamDefKind::Type(_) => {
UnpackedKind::Type(tcx.mk_ty_param_from_def(param))
}
}
})
}
/// Creates a Substs for generic parameter definitions,
/// by calling closures to obtain each region and type.
/// by calling closures to obtain each kind.
/// The closures get to observe the Substs as they're
/// being built, which can be used to correctly
/// substitute defaults of type parameters.
pub fn for_item<FR, FT>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
def_id: DefId,
mut mk_region: FR,
mut mk_type: FT)
-> &'tcx Substs<'tcx>
where FR: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> ty::Region<'tcx>,
FT: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> Ty<'tcx> {
/// substitute defaults of generic parameters.
pub fn for_item<F>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
def_id: DefId,
mut mk_kind: F)
-> &'tcx Substs<'tcx>
where F: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> UnpackedKind<'tcx>
{
let defs = tcx.generics_of(def_id);
let mut substs = Vec::with_capacity(defs.count());
Substs::fill_item(&mut substs, tcx, defs, &mut mk_region, &mut mk_type);
Substs::fill_item(&mut substs, tcx, defs, &mut mk_kind);
tcx.intern_substs(&substs)
}
pub fn extend_to<FR, FT>(&self,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
def_id: DefId,
mut mk_region: FR,
mut mk_type: FT)
-> &'tcx Substs<'tcx>
where FR: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> ty::Region<'tcx>,
FT: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> Ty<'tcx>
pub fn extend_to<F>(&self,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
def_id: DefId,
mut mk_kind: F)
-> &'tcx Substs<'tcx>
where F: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> UnpackedKind<'tcx>
{
let defs = tcx.generics_of(def_id);
let mut result = Vec::with_capacity(defs.count());
result.extend(self[..].iter().cloned());
Substs::fill_single(&mut result, defs, &mut mk_region, &mut mk_type);
Substs::fill_single(&mut result, defs, &mut mk_kind);
tcx.intern_substs(&result)
}
pub fn fill_item<FR, FT>(substs: &mut Vec<Kind<'tcx>>,
pub fn fill_item<F>(substs: &mut Vec<Kind<'tcx>>,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
defs: &ty::Generics,
mk_region: &mut FR,
mk_type: &mut FT)
where FR: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> ty::Region<'tcx>,
FT: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> Ty<'tcx> {
mk_kind: &mut F)
where F: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> UnpackedKind<'tcx>
{
if let Some(def_id) = defs.parent {
let parent_defs = tcx.generics_of(def_id);
Substs::fill_item(substs, tcx, parent_defs, mk_region, mk_type);
Substs::fill_item(substs, tcx, parent_defs, mk_kind);
}
Substs::fill_single(substs, defs, mk_region, mk_type)
Substs::fill_single(substs, defs, mk_kind)
}
fn fill_single<FR, FT>(substs: &mut Vec<Kind<'tcx>>,
fn fill_single<F>(substs: &mut Vec<Kind<'tcx>>,
defs: &ty::Generics,
mk_region: &mut FR,
mk_type: &mut FT)
where FR: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> ty::Region<'tcx>,
FT: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> Ty<'tcx> {
mk_kind: &mut F)
where F: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> UnpackedKind<'tcx>
{
for param in &defs.params {
let kind = match param.kind {
ty::GenericParamDefKind::Lifetime => mk_region(param, substs).into(),
ty::GenericParamDefKind::Type(_) => mk_type(param, substs).into(),
};
let kind = mk_kind(param, substs);
assert_eq!(param.index as usize, substs.len());
substs.push(kind);
substs.push(kind.pack());
}
}

View file

@ -17,9 +17,9 @@ use hir;
use ich::NodeIdHashingMode;
use middle::const_val::ConstVal;
use traits::{self, ObligationCause};
use ty::{self, Ty, TyCtxt, TypeFoldable};
use ty::{self, Ty, TyCtxt, GenericParamDefKind, TypeFoldable};
use ty::fold::TypeVisitor;
use ty::subst::UnpackedKind;
use ty::subst::{Substs, UnpackedKind};
use ty::maps::TyCtxtAt;
use ty::TypeVariants::*;
use ty::layout::{Integer, IntegerExt};
@ -573,11 +573,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
/// Given the def-id of some item that has no type parameters, make
/// a suitable "empty substs" for it.
pub fn empty_substs_for_def_id(self, item_def_id: DefId) -> &'tcx ty::Substs<'tcx> {
ty::Substs::for_item(self, item_def_id,
|_, _| self.types.re_erased,
|_, _| {
bug!("empty_substs_for_def_id: {:?} has type parameters", item_def_id)
pub fn empty_substs_for_def_id(self, item_def_id: DefId) -> &'tcx Substs<'tcx> {
Substs::for_item(self, item_def_id, |param, _| {
match param.kind {
GenericParamDefKind::Lifetime => UnpackedKind::Lifetime(self.types.re_erased),
GenericParamDefKind::Type(_) => {
bug!("empty_substs_for_def_id: {:?} has type parameters", item_def_id)
}
}
})
}

View file

@ -196,8 +196,8 @@ use rustc::hir::def_id::DefId;
use rustc::middle::const_val::ConstVal;
use rustc::mir::interpret::{AllocId, ConstValue};
use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem};
use rustc::ty::subst::{Substs, Kind};
use rustc::ty::{self, TypeFoldable, Ty, TyCtxt};
use rustc::ty::subst::{Substs, Kind, UnpackedKind};
use rustc::ty::{self, TypeFoldable, Ty, TyCtxt, GenericParamDefKind};
use rustc::ty::adjustment::CustomCoerceUnsized;
use rustc::session::config;
use rustc::mir::{self, Location, Promoted};
@ -1112,10 +1112,16 @@ fn create_mono_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
continue;
}
let substs = Substs::for_item(tcx,
method.def_id,
|_, _| tcx.types.re_erased,
|def, _| trait_ref.substs.type_for_def(def));
let substs = Substs::for_item(tcx, method.def_id, |param, _| {
match param.kind {
GenericParamDefKind::Lifetime => {
UnpackedKind::Lifetime(tcx.types.re_erased)
}
GenericParamDefKind::Type(_) => {
UnpackedKind::Type(trait_ref.substs.type_for_def(param))
}
}
});
let instance = ty::Instance::resolve(tcx,
ty::ParamEnv::reveal_all(),

View file

@ -12,8 +12,8 @@ use rustc::hir;
use rustc::hir::def_id::DefId;
use rustc::infer;
use rustc::mir::*;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::subst::{Kind, Subst, Substs};
use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind};
use rustc::ty::subst::{Kind, UnpackedKind, Subst, Substs};
use rustc::ty::maps::Providers;
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
@ -427,12 +427,12 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
) {
let tcx = self.tcx;
let substs = Substs::for_item(
tcx,
self.def_id,
|_, _| tcx.types.re_erased,
|_, _| ty
);
let substs = Substs::for_item(tcx, self.def_id, |param, _| {
match param.kind {
GenericParamDefKind::Lifetime => UnpackedKind::Lifetime(tcx.types.re_erased),
GenericParamDefKind::Type(_) => UnpackedKind::Type(ty),
}
});
// `func == Clone::clone(&ty) -> ty`
let func_ty = tcx.mk_fn_def(self.def_id, substs);

View file

@ -20,7 +20,8 @@ use middle::resolve_lifetime as rl;
use namespace::Namespace;
use rustc::ty::subst::{Kind, UnpackedKind, Subst, Substs};
use rustc::traits;
use rustc::ty::{self, RegionKind, Ty, TyCtxt, GenericParamDefKind, ToPredicate, TypeFoldable};
use rustc::ty::{self, RegionKind, Ty, TyCtxt, ToPredicate, TypeFoldable};
use rustc::ty::GenericParamDefKind;
use rustc::ty::wf::object_region_bounds;
use rustc_target::spec::abi;
use std::slice;
@ -264,66 +265,76 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
};
let own_self = self_ty.is_some() as usize;
let substs = Substs::for_item(tcx, def_id, |def, _| {
let i = def.index as usize - own_self;
if let Some(lifetime) = parameters.lifetimes.get(i) {
self.ast_region_to_region(lifetime, Some(def))
} else {
tcx.types.re_static
}
}, |def, substs| {
let i = def.index as usize;
// Handle Self first, so we can adjust the index to match the AST.
if let (0, Some(ty)) = (i, self_ty) {
return ty;
}
let has_default = match def.kind {
GenericParamDefKind::Type(ty) => ty.has_default,
_ => unreachable!()
};
let i = i - (lt_accepted + own_self);
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(def) {
self.ty_infer_for_def(def, span)
} else {
self.ty_infer(span)
};
ty_var
} else if has_default {
// No type parameter provided, but a default exists.
// If we are converting an object type, then the
// `Self` parameter is unknown. However, some of the
// other type parameters may reference `Self` in their
// defaults. This will lead to an ICE if we are not
// careful!
if default_needs_object_self(def) {
struct_span_err!(tcx.sess, span, E0393,
"the type parameter `{}` must be explicitly specified",
def.name)
.span_label(span, format!("missing reference to `{}`", def.name))
.note(&format!("because of the default `Self` reference, \
type parameters must be specified on object types"))
.emit();
tcx.types.err
} else {
// This is a default type parameter.
self.normalize_ty(
span,
tcx.at(span).type_of(def.def_id)
.subst_spanned(tcx, substs, Some(span))
)
let substs = Substs::for_item(tcx, def_id, |param, substs| {
match param.kind {
GenericParamDefKind::Lifetime => {
let i = param.index as usize - own_self;
let lt = if let Some(lifetime) = parameters.lifetimes.get(i) {
self.ast_region_to_region(lifetime, Some(param))
} else {
tcx.types.re_static
};
UnpackedKind::Lifetime(lt)
}
GenericParamDefKind::Type(_) => {
let i = param.index as usize;
// Handle Self first, so we can adjust the index to match the AST.
if let (0, Some(ty)) = (i, self_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 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) {
self.ty_infer_for_def(param, span)
} else {
self.ty_infer(span)
};
ty_var
} else if has_default {
// No type parameter provided, but a default exists.
// If we are converting an object type, then the
// `Self` parameter is unknown. However, some of the
// other type parameters may reference `Self` in their
// defaults. This will lead to an ICE if we are not
// careful!
if default_needs_object_self(param) {
struct_span_err!(tcx.sess, span, E0393,
"the type parameter `{}` must be explicitly \
specified",
param.name)
.span_label(span,
format!("missing reference to `{}`", param.name))
.note(&format!("because of the default `Self` reference, \
type parameters must be specified on object \
types"))
.emit();
tcx.types.err
} else {
// This is a default type parameter.
self.normalize_ty(
span,
tcx.at(span).type_of(param.def_id)
.subst_spanned(tcx, substs, Some(span))
)
}
} else {
// We've already errored above about the mismatch.
tcx.types.err
};
UnpackedKind::Type(ty)
}
} else {
// We've already errored above about the mismatch.
tcx.types.err
}
});
@ -1154,12 +1165,17 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
let mut substs = Vec::with_capacity(generics.count());
if let Some(parent_id) = generics.parent {
let parent_generics = tcx.generics_of(parent_id);
Substs::fill_item(
&mut substs, tcx, parent_generics,
&mut |def, _| tcx.mk_region(
ty::ReEarlyBound(def.to_early_bound_region_data())),
&mut |def, _| tcx.mk_ty_param_from_def(def)
);
Substs::fill_item(&mut substs, tcx, parent_generics, &mut |param, _| {
match param.kind {
GenericParamDefKind::Lifetime => {
UnpackedKind::Lifetime(
tcx.mk_region(ty::ReEarlyBound(param.to_early_bound_region_data())))
}
GenericParamDefKind::Type(_) => {
UnpackedKind::Type(tcx.mk_ty_param_from_def(param))
}
}
});
// Replace all lifetimes with 'static
for subst in &mut substs {

View file

@ -18,8 +18,8 @@ use rustc::infer::{InferOk, InferResult};
use rustc::infer::LateBoundRegionConversionTime;
use rustc::infer::type_variable::TypeVariableOrigin;
use rustc::traits::error_reporting::ArgKind;
use rustc::ty::{self, ToPolyTraitRef, Ty};
use rustc::ty::subst::Substs;
use rustc::ty::{self, ToPolyTraitRef, Ty, GenericParamDefKind};
use rustc::ty::subst::{UnpackedKind, Substs};
use rustc::ty::TypeFoldable;
use std::cmp;
use std::iter;
@ -104,15 +104,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// inference phase (`upvar.rs`).
let base_substs =
Substs::identity_for_item(self.tcx, self.tcx.closure_base_def_id(expr_def_id));
let substs = base_substs.extend_to(
self.tcx,
expr_def_id,
|_, _| span_bug!(expr.span, "closure has region param"),
|_, _| {
self.infcx
.next_ty_var(TypeVariableOrigin::ClosureSynthetic(expr.span))
},
);
let substs = base_substs.extend_to(self.tcx,expr_def_id, |param, _| {
match param.kind {
GenericParamDefKind::Lifetime => {
span_bug!(expr.span, "closure has region param")
}
GenericParamDefKind::Type(_) => {
UnpackedKind::Type(self.infcx
.next_ty_var(TypeVariableOrigin::ClosureSynthetic(expr.span)))
}
}
});
if let Some(GeneratorTypes { yield_ty, interior, movability }) = generator_types {
let substs = ty::GeneratorSubsts { substs };
self.demand_eqtype(

View file

@ -15,8 +15,8 @@ use check::{FnCtxt, PlaceOp, callee, Needs};
use hir::def_id::DefId;
use rustc::ty::subst::Substs;
use rustc::traits;
use rustc::ty::{self, Ty};
use rustc::ty::subst::Subst;
use rustc::ty::{self, Ty, GenericParamDefKind};
use rustc::ty::subst::{UnpackedKind, Subst};
use rustc::ty::adjustment::{Adjustment, Adjust, OverloadedDeref};
use rustc::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
use rustc::ty::fold::TypeFoldable;
@ -317,30 +317,37 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
assert_eq!(method_generics.parent_count, parent_substs.len());
let provided = &segment.parameters;
let own_counts = method_generics.own_counts();
Substs::for_item(self.tcx, pick.item.def_id, |def, _| {
let i = def.index as usize;
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(def))
} else {
self.region_var_for_def(self.span, def)
}
}, |def, _cur_substs| {
let i = def.index as usize;
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, def)
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)
}
}
})
}

View file

@ -19,7 +19,8 @@ use namespace::Namespace;
use rustc::ty::subst::Substs;
use rustc::traits;
use rustc::ty::{self, Ty, ToPredicate, ToPolyTraitRef, TraitRef, TypeFoldable};
use rustc::ty::subst::Subst;
use rustc::ty::GenericParamDefKind;
use rustc::ty::subst::{UnpackedKind, Subst};
use rustc::infer::{self, InferOk};
use syntax::ast;
@ -253,16 +254,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
trait_def_id);
// Construct a trait-reference `self_ty : Trait<input_tys>`
let substs = Substs::for_item(self.tcx,
trait_def_id,
|def, _| self.region_var_for_def(span, def),
|def, _substs| {
if def.index == 0 {
self_ty
} else if let Some(ref input_types) = opt_input_types {
input_types[def.index as usize - 1]
} else {
self.type_var_for_def(span, def)
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::Type(_) => {
let ty = if param.index == 0 {
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)
}
}
});

View file

@ -17,9 +17,10 @@ use check::FnCtxt;
use hir::def_id::DefId;
use hir::def::Def;
use namespace::Namespace;
use rustc::ty::subst::{Subst, Substs};
use rustc::ty::subst::{UnpackedKind, Subst, Substs};
use rustc::traits::{self, ObligationCause};
use rustc::ty::{self, Ty, ToPolyTraitRef, ToPredicate, TraitRef, TypeFoldable};
use rustc::ty::GenericParamDefKind;
use rustc::infer::type_variable::TypeVariableOrigin;
use rustc::util::nodemap::FxHashSet;
use rustc::infer::{self, InferOk};
@ -1387,21 +1388,28 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
if generics.params.is_empty() {
xform_fn_sig.subst(self.tcx, substs)
} else {
let substs = Substs::for_item(self.tcx, method, |def, _| {
let i = def.index as usize;
if i < substs.len() {
substs.region_at(i)
} else {
// In general, during probe we erase regions. See
// `impl_self_ty()` for an explanation.
self.tcx.types.re_erased
}
}, |def, _cur_substs| {
let i = def.index as usize;
if i < substs.len() {
substs.type_at(i)
} else {
self.type_var_for_def(self.span, def)
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 {
// 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)
}
}
});
xform_fn_sig.subst(self.tcx, substs)
@ -1414,12 +1422,18 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
}
fn fresh_item_substs(&self, def_id: DefId) -> &'tcx Substs<'tcx> {
Substs::for_item(self.tcx,
def_id,
|_, _| self.tcx.types.re_erased,
|_, _| self.next_ty_var(
TypeVariableOrigin::SubstitutionPlaceholder(
self.tcx.def_span(def_id))))
Substs::for_item(self.tcx, def_id, |param, _| {
match param.kind {
GenericParamDefKind::Lifetime => {
UnpackedKind::Lifetime(self.tcx.types.re_erased)
}
GenericParamDefKind::Type(_) => {
UnpackedKind::Type(self.next_ty_var(
TypeVariableOrigin::SubstitutionPlaceholder(
self.tcx.def_span(def_id))))
}
}
})
}
/// Replace late-bound-regions bound by `value` with `'static` using

View file

@ -94,7 +94,7 @@ use rustc::infer::anon_types::AnonTypeDecl;
use rustc::infer::type_variable::{TypeVariableOrigin};
use rustc::middle::region;
use rustc::mir::interpret::{GlobalId};
use rustc::ty::subst::{Kind, Subst, Substs};
use rustc::ty::subst::{Kind, UnpackedKind, Subst, Substs};
use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine};
use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate};
use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
@ -4758,71 +4758,78 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}
(None, None) => (0, false)
};
let substs = Substs::for_item(self.tcx, def.def_id(), |def, _| {
let mut i = def.index as usize;
let substs = Substs::for_item(self.tcx, def.def_id(), |param, substs| {
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[..])
});
if let Some(lifetime) = lifetimes.get(i) {
AstConv::ast_region_to_region(self, lifetime, Some(def))
} else {
self.re_infer(span, Some(def)).unwrap()
}
}, |def, substs| {
let mut i = def.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 opt_self_ty.unwrap_or_else(|| {
self.type_var_for_def(span, def)
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[..])
});
let lt = if let Some(lifetime) = lifetimes.get(i) {
AstConv::ast_region_to_region(self, lifetime, Some(param))
} else {
self.re_infer(span, Some(param)).unwrap()
};
UnpackedKind::Lifetime(lt)
}
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)
});
GenericParamDefKind::Type(_) => {
let mut i = param.index as usize;
// Skip over the lifetimes in the same segment.
if let Some((_, generics)) = segment {
i -= generics.own_counts().lifetimes;
}
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)
});
let has_default = match def.kind {
GenericParamDefKind::Type(ty) => ty.has_default,
_ => unreachable!()
};
// Skip over the lifetimes in the same segment.
if let Some((_, generics)) = segment {
i -= generics.own_counts().lifetimes;
}
if let Some(ast_ty) = types.get(i) {
// A provided type parameter.
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(def.def_id);
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, def)
let has_default = match param.kind {
GenericParamDefKind::Type(ty) => ty.has_default,
_ => unreachable!()
};
let ty = if let Some(ast_ty) = types.get(i) {
// A provided type parameter.
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(
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)
}
}
});

View file

@ -11,11 +11,10 @@
use check::{Inherited, FnCtxt};
use constrained_type_params::{identify_constrained_type_params, Parameter};
use ty::GenericParamDefKind;
use hir::def_id::DefId;
use rustc::traits::{self, ObligationCauseCode};
use rustc::ty::{self, Lift, Ty, TyCtxt};
use rustc::ty::{self, Lift, Ty, TyCtxt, GenericParamDefKind};
use rustc::ty::subst::{UnpackedKind, Substs};
use rustc::ty::util::ExplicitSelf;
use rustc::util::nodemap::{FxHashSet, FxHashMap};
use rustc::middle::lang_items;
@ -406,22 +405,28 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
// For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`.
//
// First we build the defaulted substitution.
let substs = ty::subst::Substs::for_item(fcx.tcx, def_id, |def, _| {
// All regions are identity.
fcx.tcx.mk_region(ty::ReEarlyBound(def.to_early_bound_region_data()))
}, |def, _| {
// If the param has a default,
if is_our_default(def) {
let default_ty = fcx.tcx.type_of(def.def_id);
// and it's not a dependent default
if !default_ty.needs_subst() {
// then substitute with the default.
return default_ty;
}
let substs = Substs::for_item(fcx.tcx, def_id, |param, _| {
match param.kind {
GenericParamDefKind::Lifetime => {
// All regions are identity.
UnpackedKind::Lifetime(
fcx.tcx.mk_region(ty::ReEarlyBound(param.to_early_bound_region_data())))
}
// Mark unwanted params as err.
fcx.tcx.types.err
});
GenericParamDefKind::Type(_) => {
// If the param has a default,
if is_our_default(param) {
let default_ty = fcx.tcx.type_of(param.def_id);
// and it's not a dependent default
if !default_ty.needs_subst() {
// then substitute with the default.
return UnpackedKind::Type(default_ty);
}
}
// Mark unwanted params as err.
UnpackedKind::Type(fcx.tcx.types.err)
}
}
});
// Now we build the substituted predicates.
for &pred in predicates.predicates.iter() {
struct CountParams { params: FxHashSet<u32> }

View file

@ -30,7 +30,8 @@ use constrained_type_params as ctp;
use middle::lang_items::SizedTraitLangItem;
use middle::resolve_lifetime as rl;
use rustc::mir::mono::Linkage;
use rustc::ty::subst::Substs;
use rustc::ty::subst::{UnpackedKind, Substs};
use rustc::ty::GenericParamDefKind;
use rustc::ty::{ToPredicate, ReprOptions};
use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt};
use rustc::ty::maps::Providers;
@ -1096,15 +1097,17 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
let substs = ty::ClosureSubsts {
substs: Substs::for_item(
tcx,
def_id,
|def, _| {
let region = def.to_early_bound_region_data();
tcx.mk_region(ty::ReEarlyBound(region))
},
|def, _| tcx.mk_ty_param_from_def(def)
)
substs: Substs::for_item(tcx, def_id, |param, _| {
match param.kind {
GenericParamDefKind::Lifetime => {
let region = param.to_early_bound_region_data();
UnpackedKind::Lifetime(tcx.mk_region(ty::ReEarlyBound(region)))
}
GenericParamDefKind::Type(_) => {
UnpackedKind::Type(tcx.mk_ty_param_from_def(param))
}
}
})
};
tcx.mk_closure(def_id, substs)