introduce from_ref helper for replacement

This commit is contained in:
csmoe 2019-09-26 22:23:13 +08:00
parent d046ffddc4
commit 8ab82c147a
6 changed files with 86 additions and 13 deletions

View File

@ -220,7 +220,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
let ty_msg = match local_visitor.found_ty {
Some(ty::TyS { kind: ty::Closure(def_id, substs), .. }) => {
let fn_sig = substs.closure_sig(*def_id, self.tcx);
let fn_sig = ty::ClosureSubsts::from_ref(substs).closure_sig(*def_id, self.tcx);
let args = closure_args(&fn_sig);
let ret = fn_sig.output().skip_binder().to_string();
format!(" for the closure `fn({}) -> {}`", args, ret)

View File

@ -722,7 +722,7 @@ where
ty::Closure(def_id, ref substs) => {
// Skip lifetime parameters of the enclosing item(s)
for upvar_ty in substs.upvar_tys(def_id, self.tcx) {
for upvar_ty in ty::ClosureSubsts::from_ref(substs).upvar_tys(def_id, self.tcx) {
upvar_ty.visit_with(self);
}
@ -886,7 +886,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
let generics = self.tcx.generics_of(def_id);
let substs =
self.tcx.mk_substs(substs.substs.iter().enumerate().map(|(index, &kind)| {
self.tcx.mk_substs(substs.iter().enumerate().map(|(index, &kind)| {
if index < generics.parent_count {
// Accommodate missing regions in the parent kinds...
self.fold_kind_mapping_missing_regions_to_empty(kind)

View File

@ -745,7 +745,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
// During upvar inference we may not know the
// closure kind, just use the LATTICE_BOTTOM value.
Some(infcx) =>
infcx.closure_kind(closure_def_id, closure_substs)
infcx.closure_kind(closure_def_id, ty::ClosureSubsts::from_ref(closure_substs))
.unwrap_or(ty::ClosureKind::LATTICE_BOTTOM),
None =>

View File

@ -3370,17 +3370,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
)?);
// FIXME: chalk
if !self.tcx().sess.opts.debugging_opts.chalk {
obligations.push(Obligation::new(
obligation.cause.clone(),
obligation.param_env,
ty::Predicate::ClosureKind(closure_def_id, substs, kind),
ty::Predicate::ClosureKind(closure_def_id, ty::ClosureSubsts::from_ref(substs.clone()), kind),
));
}
Ok(VtableClosureData {
closure_def_id,
substs: substs.clone(),
substs: ty::ClosureSubsts::from_ref(substs),
nested: obligations,
})
}
@ -3869,7 +3870,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
&mut self,
obligation: &TraitObligation<'tcx>,
closure_def_id: DefId,
substs: ty::ClosureSubsts<'tcx>,
substs: SubstsRef<'tcx>,
) -> ty::PolyTraitRef<'tcx> {
debug!(
"closure_trait_ref_unnormalized(obligation={:?}, closure_def_id={:?}, substs={:?})",

View File

@ -158,7 +158,7 @@ pub enum TyKind<'tcx> {
/// The anonymous type of a closure. Used to represent the type of
/// `|a| a`.
Closure(DefId, ClosureSubsts<'tcx>),
Closure(DefId, SubstsRef<'tcx>),
/// The anonymous type of a generator. Used to represent the type of
/// `|a| yield a`.
@ -317,13 +317,18 @@ pub struct ClosureSubsts<'tcx> {
/// Struct returned by `split()`. Note that these are subslices of the
/// parent slice and not canonical substs themselves.
struct SplitClosureSubsts<'tcx> {
closure_kind_ty: Ty<'tcx>,
closure_sig_ty: Ty<'tcx>,
upvar_kinds: &'tcx [GenericArg<'tcx>],
pub(crate) struct SplitClosureSubsts<'tcx> {
pub(crate) closure_kind_ty: Ty<'tcx>,
pub(crate) closure_sig_ty: Ty<'tcx>,
pub(crate) upvar_kinds: &'tcx [GenericArg<'tcx>],
}
impl<'tcx> ClosureSubsts<'tcx> {
// FIXME(csmoe): remove this method once the migration is done.
pub fn from_ref(substs: SubstsRef<'tcx>) -> Self {
Self { substs }
}
/// Divides the closure substs into their respective
/// components. Single source of truth with respect to the
/// ordering.
@ -2147,7 +2152,7 @@ impl<'tcx> TyS<'tcx> {
Adt(_, substs) | Opaque(_, substs) => {
out.extend(substs.regions())
}
Closure(_, ClosureSubsts { ref substs }) |
Closure(_, ref substs ) |
Generator(_, GeneratorSubsts { ref substs }, _) => {
out.extend(substs.regions())
}

View File

@ -5,6 +5,7 @@ use crate::infer::canonical::Canonical;
use crate::ty::{self, Lift, List, Ty, TyCtxt, InferConst, ParamConst};
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use crate::mir::interpret::ConstValue;
use crate::ty::sty::SplitClosureSubsts;
use rustc_serialize::{self, Encodable, Encoder, Decodable, Decoder};
use syntax_pos::{Span, DUMMY_SP};
@ -379,6 +380,72 @@ impl<'a, 'tcx> InternalSubsts<'tcx> {
pub fn truncate_to(&self, tcx: TyCtxt<'tcx>, generics: &ty::Generics) -> SubstsRef<'tcx> {
tcx.mk_substs(self.iter().take(generics.count()).cloned())
}
/// Divides the closure substs into their respective
/// components. Single source of truth with respect to the
/// ordering.
fn split(self, def_id: DefId, tcx: TyCtxt<'_>) -> SplitClosureSubsts<'tcx> {
let generics = tcx.generics_of(def_id);
let parent_len = generics.parent_count;
SplitClosureSubsts {
closure_kind_ty: self.substs.type_at(parent_len),
closure_sig_ty: self.substs.type_at(parent_len + 1),
upvar_kinds: &self.substs[parent_len + 2..],
}
}
#[inline]
pub fn upvar_tys(
&self,
def_id: DefId,
tcx: TyCtxt<'_>,
) -> impl Iterator<Item = Ty<'tcx>> + 'tcx {
let SplitClosureSubsts { upvar_kinds, .. } = self.split(def_id, tcx);
upvar_kinds.iter().map(|t| {
if let UnpackedKind::Type(ty) = t.unpack() {
ty
} else {
bug!("upvar should be type")
}
})
}
/// Returns the closure kind for this closure; may return a type
/// variable during inference. To get the closure kind during
/// inference, use `infcx.closure_kind(def_id, substs)`.
pub fn closure_kind_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> {
self.split(def_id, tcx).closure_kind_ty
}
/// Returns the type representing the closure signature for this
/// closure; may contain type variables during inference. To get
/// the closure signature during inference, use
/// `infcx.fn_sig(def_id)`.
pub fn closure_sig_ty(self, def_id: DefId, tcx: TyCtxt<'_>) -> Ty<'tcx> {
self.split(def_id, tcx).closure_sig_ty
}
/// Returns the closure kind for this closure; only usable outside
/// of an inference context, because in that context we know that
/// there are no type variables.
///
/// If you have an inference context, use `infcx.closure_kind()`.
pub fn closure_kind(self, def_id: DefId, tcx: TyCtxt<'tcx>) -> ty::ClosureKind {
self.split(def_id, tcx).closure_kind_ty.to_opt_closure_kind().unwrap()
}
/// Extracts the signature from the closure; only usable outside
/// of an inference context, because in that context we know that
/// there are no type variables.
///
/// If you have an inference context, use `infcx.closure_sig()`.
pub fn closure_sig(self, def_id: DefId, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> {
let ty = self.closure_sig_ty(def_id, tcx);
match ty.kind {
ty::FnPtr(sig) => sig,
_ => bug!("closure_sig_ty is not a fn-ptr: {:?}", ty.kind),
}
}
}
impl<'tcx> TypeFoldable<'tcx> for SubstsRef<'tcx> {