Add generic consts to BottomUpFolder

Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
This commit is contained in:
varkor 2019-03-08 01:15:23 +00:00
parent 77447deb21
commit d7fdeffafc
4 changed files with 60 additions and 14 deletions

View file

@ -676,8 +676,7 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
let tcx = self.infcx.tcx;
value.fold_with(&mut BottomUpFolder {
tcx,
reg_op: |reg| reg,
fldop: |ty| {
ty_op: |ty| {
if let ty::Opaque(def_id, substs) = ty.sty {
// Check that this is `impl Trait` type is
// declared by `parent_def_id` -- i.e., one whose
@ -776,6 +775,8 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
ty
},
lt_op: |lt| lt,
ct_op: |ct| ct,
})
}

View file

@ -193,29 +193,37 @@ pub trait TypeVisitor<'tcx> : Sized {
///////////////////////////////////////////////////////////////////////////
// Some sample folders
pub struct BottomUpFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a, F, G>
pub struct BottomUpFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a, F, G, H>
where F: FnMut(Ty<'tcx>) -> Ty<'tcx>,
G: FnMut(ty::Region<'tcx>) -> ty::Region<'tcx>,
H: FnMut(&'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx>,
{
pub tcx: TyCtxt<'a, 'gcx, 'tcx>,
pub fldop: F,
pub reg_op: G,
pub ty_op: F,
pub lt_op: G,
pub ct_op: H,
}
impl<'a, 'gcx, 'tcx, F, G> TypeFolder<'gcx, 'tcx> for BottomUpFolder<'a, 'gcx, 'tcx, F, G>
impl<'a, 'gcx, 'tcx, F, G, H> TypeFolder<'gcx, 'tcx> for BottomUpFolder<'a, 'gcx, 'tcx, F, G, H>
where F: FnMut(Ty<'tcx>) -> Ty<'tcx>,
G: FnMut(ty::Region<'tcx>) -> ty::Region<'tcx>,
H: FnMut(&'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx>,
{
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx }
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
let t1 = ty.super_fold_with(self);
(self.fldop)(t1)
let t = ty.super_fold_with(self);
(self.ty_op)(t)
}
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
let r = r.super_fold_with(self);
(self.reg_op)(r)
(self.lt_op)(r)
}
fn fold_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
let c = c.super_fold_with(self);
(self.ct_op)(c)
}
}

View file

@ -616,7 +616,7 @@ fn check_existential_types<'a, 'fcx, 'gcx, 'tcx>(
let mut substituted_predicates = Vec::new();
ty.fold_with(&mut ty::fold::BottomUpFolder {
tcx: fcx.tcx,
fldop: |ty| {
ty_op: |ty| {
if let ty::Opaque(def_id, substs) = ty.sty {
trace!("check_existential_types: opaque_ty, {:?}, {:?}", def_id, substs);
let generics = tcx.generics_of(def_id);
@ -739,7 +739,8 @@ fn check_existential_types<'a, 'fcx, 'gcx, 'tcx>(
} // if let Opaque
ty
},
reg_op: |reg| reg,
lt_op: |lt| lt,
ct_op: |ct| ct,
});
substituted_predicates
}

View file

@ -11,7 +11,8 @@ use rustc::infer::InferCtxt;
use rustc::ty::adjustment::{Adjust, Adjustment, PointerCast};
use rustc::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder};
use rustc::ty::subst::UnpackedKind;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::{self, Ty, TyCtxt, Const, LazyConst};
use rustc::mir::interpret::ConstValue;
use rustc::util::nodemap::DefIdSet;
use rustc_data_structures::sync::Lrc;
use std::mem;
@ -488,7 +489,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
// figures out the concrete type with `U`, but the stored type is with `T`
instantiated_ty.fold_with(&mut BottomUpFolder {
tcx: self.tcx().global_tcx(),
fldop: |ty| {
ty_op: |ty| {
trace!("checking type {:?}", ty);
// find a type parameter
if let ty::Param(..) = ty.sty {
@ -520,7 +521,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
}
ty
},
reg_op: |region| {
lt_op: |region| {
match region {
// ignore static regions
ty::ReStatic => region,
@ -564,6 +565,41 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
}
}
},
ct_op: |ct| {
trace!("checking const {:?}", ct);
// find a const parameter
if let LazyConst::Evaluated(Const { ty, val }) = ct {
if let ConstValue::Param(..) = val {
// look it up in the substitution list
assert_eq!(opaque_defn.substs.len(), generics.params.len());
for (subst, param) in opaque_defn.substs.iter()
.zip(&generics.params) {
if let UnpackedKind::Const(subst) = subst.unpack() {
if subst == ct {
// found it in the substitution list, replace with the
// parameter from the existential type
return self.tcx()
.global_tcx()
.mk_const_param(param.index, param.name, ty);
}
}
}
self.tcx()
.sess
.struct_span_err(
span,
&format!(
"const parameter `{}` is part of concrete type but not \
used in parameter list for existential type",
ct,
),
)
.emit();
return self.tcx().types.ct_err;
}
}
ct
}
})
};