Add generic consts to BottomUpFolder
Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
This commit is contained in:
parent
77447deb21
commit
d7fdeffafc
4 changed files with 60 additions and 14 deletions
|
|
@ -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,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue