1
Fork 0

Move binder for dyn to each list item

This commit is contained in:
Jack Huey 2020-12-11 15:02:46 -05:00
parent 58d2bad9f7
commit ed80815bf2
25 changed files with 307 additions and 261 deletions

View file

@ -321,10 +321,14 @@ impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<Ty<'tcx>> {
}
}
impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<ty::ExistentialPredicate<'tcx>> {
impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D>
for ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>>
{
fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
let len = decoder.read_usize()?;
Ok(decoder.tcx().mk_existential_predicates((0..len).map(|_| Decodable::decode(decoder)))?)
Ok(decoder
.tcx()
.mk_poly_existential_predicates((0..len).map(|_| Decodable::decode(decoder)))?)
}
}
@ -373,7 +377,7 @@ impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [mir::abstract_const::N
impl_decodable_via_ref! {
&'tcx ty::TypeckResults<'tcx>,
&'tcx ty::List<Ty<'tcx>>,
&'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
&'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>>,
&'tcx Allocation,
&'tcx mir::Body<'tcx>,
&'tcx mir::UnsafetyCheckResult,

View file

@ -87,7 +87,7 @@ pub struct CtxtInterners<'tcx> {
substs: InternedSet<'tcx, InternalSubsts<'tcx>>,
canonical_var_infos: InternedSet<'tcx, List<CanonicalVarInfo<'tcx>>>,
region: InternedSet<'tcx, RegionKind>,
existential_predicates: InternedSet<'tcx, List<ExistentialPredicate<'tcx>>>,
poly_existential_predicates: InternedSet<'tcx, List<ty::Binder<ExistentialPredicate<'tcx>>>>,
predicate: InternedSet<'tcx, PredicateInner<'tcx>>,
predicates: InternedSet<'tcx, List<Predicate<'tcx>>>,
projs: InternedSet<'tcx, List<ProjectionKind>>,
@ -103,7 +103,7 @@ impl<'tcx> CtxtInterners<'tcx> {
type_list: Default::default(),
substs: Default::default(),
region: Default::default(),
existential_predicates: Default::default(),
poly_existential_predicates: Default::default(),
canonical_var_infos: Default::default(),
predicate: Default::default(),
predicates: Default::default(),
@ -1610,7 +1610,7 @@ nop_lift! {const_; &'a Const<'a> => &'tcx Const<'tcx>}
nop_lift! {predicate; &'a PredicateInner<'a> => &'tcx PredicateInner<'tcx>}
nop_list_lift! {type_list; Ty<'a> => Ty<'tcx>}
nop_list_lift! {existential_predicates; ExistentialPredicate<'a> => ExistentialPredicate<'tcx>}
nop_list_lift! {poly_existential_predicates; ty::Binder<ExistentialPredicate<'a>> => ty::Binder<ExistentialPredicate<'tcx>>}
nop_list_lift! {predicates; Predicate<'a> => Predicate<'tcx>}
nop_list_lift! {canonical_var_infos; CanonicalVarInfo<'a> => CanonicalVarInfo<'tcx>}
nop_list_lift! {projs; ProjectionKind => ProjectionKind}
@ -2051,7 +2051,8 @@ slice_interners!(
type_list: _intern_type_list(Ty<'tcx>),
substs: _intern_substs(GenericArg<'tcx>),
canonical_var_infos: _intern_canonical_var_infos(CanonicalVarInfo<'tcx>),
existential_predicates: _intern_existential_predicates(ExistentialPredicate<'tcx>),
poly_existential_predicates:
_intern_poly_existential_predicates(ty::Binder<ExistentialPredicate<'tcx>>),
predicates: _intern_predicates(Predicate<'tcx>),
projs: _intern_projs(ProjectionKind),
place_elems: _intern_place_elems(PlaceElem<'tcx>),
@ -2282,7 +2283,7 @@ impl<'tcx> TyCtxt<'tcx> {
#[inline]
pub fn mk_dynamic(
self,
obj: ty::Binder<&'tcx List<ExistentialPredicate<'tcx>>>,
obj: &'tcx List<ty::Binder<ExistentialPredicate<'tcx>>>,
reg: ty::Region<'tcx>,
) -> Ty<'tcx> {
self.mk_ty(Dynamic(obj, reg))
@ -2412,13 +2413,17 @@ impl<'tcx> TyCtxt<'tcx> {
Place { local: place.local, projection: self.intern_place_elems(&projection) }
}
pub fn intern_existential_predicates(
pub fn intern_poly_existential_predicates(
self,
eps: &[ExistentialPredicate<'tcx>],
) -> &'tcx List<ExistentialPredicate<'tcx>> {
eps: &[ty::Binder<ExistentialPredicate<'tcx>>],
) -> &'tcx List<ty::Binder<ExistentialPredicate<'tcx>>> {
assert!(!eps.is_empty());
assert!(eps.array_windows().all(|[a, b]| a.stable_cmp(self, b) != Ordering::Greater));
self._intern_existential_predicates(eps)
assert!(
eps.array_windows()
.all(|[a, b]| a.skip_binder().stable_cmp(self, &b.skip_binder())
!= Ordering::Greater)
);
self._intern_poly_existential_predicates(eps)
}
pub fn intern_predicates(self, preds: &[Predicate<'tcx>]) -> &'tcx List<Predicate<'tcx>> {
@ -2475,13 +2480,16 @@ impl<'tcx> TyCtxt<'tcx> {
})
}
pub fn mk_existential_predicates<
I: InternAs<[ExistentialPredicate<'tcx>], &'tcx List<ExistentialPredicate<'tcx>>>,
pub fn mk_poly_existential_predicates<
I: InternAs<
[ty::Binder<ExistentialPredicate<'tcx>>],
&'tcx List<ty::Binder<ExistentialPredicate<'tcx>>>,
>,
>(
self,
iter: I,
) -> I::Output {
iter.intern_with(|xs| self.intern_existential_predicates(xs))
iter.intern_with(|xs| self.intern_poly_existential_predicates(xs))
}
pub fn mk_predicates<I: InternAs<[Predicate<'tcx>], &'tcx List<Predicate<'tcx>>>>(

View file

@ -58,7 +58,7 @@ pub enum TypeError<'tcx> {
CyclicTy(Ty<'tcx>),
CyclicConst(&'tcx ty::Const<'tcx>),
ProjectionMismatched(ExpectedFound<DefId>),
ExistentialMismatch(ExpectedFound<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>),
ExistentialMismatch(ExpectedFound<&'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>>>),
ObjectUnsafeCoercion(DefId),
ConstMismatch(ExpectedFound<&'tcx ty::Const<'tcx>>),

View file

@ -160,19 +160,15 @@ impl FlagComputation {
}
&ty::Dynamic(obj, r) => {
self.bound_computation(obj, |computation, obj| {
for predicate in obj.iter() {
match predicate {
ty::ExistentialPredicate::Trait(tr) => {
computation.add_substs(tr.substs)
}
ty::ExistentialPredicate::Projection(p) => {
computation.add_existential_projection(&p);
}
ty::ExistentialPredicate::AutoTrait(_) => {}
for predicate in obj.iter() {
self.bound_computation(predicate, |computation, predicate| match predicate {
ty::ExistentialPredicate::Trait(tr) => computation.add_substs(tr.substs),
ty::ExistentialPredicate::Projection(p) => {
computation.add_existential_projection(&p);
}
}
});
ty::ExistentialPredicate::AutoTrait(_) => {}
});
}
self.add_region(r);
}

View file

@ -63,7 +63,7 @@ pub trait Printer<'tcx>: Sized {
fn print_dyn_existential(
self,
predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
predicates: &'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>>,
) -> Result<Self::DynExistential, Self::Error>;
fn print_const(self, ct: &'tcx ty::Const<'tcx>) -> Result<Self::Const, Self::Error>;
@ -343,7 +343,9 @@ impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for Ty<'tcx> {
}
}
impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> {
impl<'tcx, P: Printer<'tcx>> Print<'tcx, P>
for &'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>>
{
type Output = P::DynExistential;
type Error = P::Error;
fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {

View file

@ -209,6 +209,17 @@ pub trait PrettyPrinter<'tcx>:
value.as_ref().skip_binder().print(self)
}
fn wrap_binder<T, F: Fn(&T, Self) -> Result<Self, fmt::Error>>(
self,
value: &ty::Binder<T>,
f: F,
) -> Result<Self, Self::Error>
where
T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>,
{
f(value.as_ref().skip_binder(), self)
}
/// Prints comma-separated elements.
fn comma_sep<T>(mut self, mut elems: impl Iterator<Item = T>) -> Result<Self, Self::Error>
where
@ -753,72 +764,77 @@ pub trait PrettyPrinter<'tcx>:
fn pretty_print_dyn_existential(
mut self,
predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
predicates: &'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>>,
) -> Result<Self::DynExistential, Self::Error> {
define_scoped_cx!(self);
// Generate the main trait ref, including associated types.
let mut first = true;
if let Some(principal) = predicates.principal() {
p!(print_def_path(principal.def_id, &[]));
self = self.wrap_binder(&principal, |principal, mut cx| {
define_scoped_cx!(cx);
p!(print_def_path(principal.def_id, &[]));
let mut resugared = false;
let mut resugared = false;
// Special-case `Fn(...) -> ...` and resugar it.
let fn_trait_kind = self.tcx().fn_trait_kind_from_lang_item(principal.def_id);
if !self.tcx().sess.verbose() && fn_trait_kind.is_some() {
if let ty::Tuple(ref args) = principal.substs.type_at(0).kind() {
let mut projections = predicates.projection_bounds();
if let (Some(proj), None) = (projections.next(), projections.next()) {
let tys: Vec<_> = args.iter().map(|k| k.expect_ty()).collect();
p!(pretty_fn_sig(&tys, false, proj.ty));
resugared = true;
// Special-case `Fn(...) -> ...` and resugar it.
let fn_trait_kind = cx.tcx().fn_trait_kind_from_lang_item(principal.def_id);
if !cx.tcx().sess.verbose() && fn_trait_kind.is_some() {
if let ty::Tuple(ref args) = principal.substs.type_at(0).kind() {
let mut projections = predicates.projection_bounds();
if let (Some(proj), None) = (projections.next(), projections.next()) {
let tys: Vec<_> = args.iter().map(|k| k.expect_ty()).collect();
p!(pretty_fn_sig(&tys, false, proj.skip_binder().ty));
resugared = true;
}
}
}
}
// HACK(eddyb) this duplicates `FmtPrinter`'s `path_generic_args`,
// in order to place the projections inside the `<...>`.
if !resugared {
// Use a type that can't appear in defaults of type parameters.
let dummy_self = self.tcx().mk_ty_infer(ty::FreshTy(0));
let principal = principal.with_self_ty(self.tcx(), dummy_self);
// HACK(eddyb) this duplicates `FmtPrinter`'s `path_generic_args`,
// in order to place the projections inside the `<...>`.
if !resugared {
// Use a type that can't appear in defaults of type parameters.
let dummy_cx = cx.tcx().mk_ty_infer(ty::FreshTy(0));
let principal = principal.with_self_ty(cx.tcx(), dummy_cx);
let args = self.generic_args_to_print(
self.tcx().generics_of(principal.def_id),
principal.substs,
);
let args = cx.generic_args_to_print(
cx.tcx().generics_of(principal.def_id),
principal.substs,
);
// Don't print `'_` if there's no unerased regions.
let print_regions = args.iter().any(|arg| match arg.unpack() {
GenericArgKind::Lifetime(r) => *r != ty::ReErased,
_ => false,
});
let mut args = args.iter().cloned().filter(|arg| match arg.unpack() {
GenericArgKind::Lifetime(_) => print_regions,
_ => true,
});
let mut projections = predicates.projection_bounds();
// Don't print `'_` if there's no unerased regions.
let print_regions = args.iter().any(|arg| match arg.unpack() {
GenericArgKind::Lifetime(r) => *r != ty::ReErased,
_ => false,
});
let mut args = args.iter().cloned().filter(|arg| match arg.unpack() {
GenericArgKind::Lifetime(_) => print_regions,
_ => true,
});
let mut projections = predicates.projection_bounds();
let arg0 = args.next();
let projection0 = projections.next();
if arg0.is_some() || projection0.is_some() {
let args = arg0.into_iter().chain(args);
let projections = projection0.into_iter().chain(projections);
let arg0 = args.next();
let projection0 = projections.next();
if arg0.is_some() || projection0.is_some() {
let args = arg0.into_iter().chain(args);
let projections = projection0.into_iter().chain(projections);
p!(generic_delimiters(|mut cx| {
cx = cx.comma_sep(args)?;
if arg0.is_some() && projection0.is_some() {
write!(cx, ", ")?;
}
cx.comma_sep(projections)
}));
p!(generic_delimiters(|mut cx| {
cx = cx.comma_sep(args)?;
if arg0.is_some() && projection0.is_some() {
write!(cx, ", ")?;
}
cx.comma_sep(projections)
}));
}
}
}
Ok(cx)
})?;
first = false;
}
define_scoped_cx!(self);
// Builtin bounds.
// FIXME(eddyb) avoid printing twice (needed to ensure
// that the auto traits are sorted *and* printed via cx).
@ -1391,7 +1407,7 @@ impl<F: fmt::Write> Printer<'tcx> for FmtPrinter<'_, 'tcx, F> {
fn print_dyn_existential(
self,
predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
predicates: &'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>>,
) -> Result<Self::DynExistential, Self::Error> {
self.pretty_print_dyn_existential(predicates)
}
@ -1537,6 +1553,17 @@ impl<F: fmt::Write> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> {
self.pretty_in_binder(value)
}
fn wrap_binder<T, C: Fn(&T, Self) -> Result<Self, Self::Error>>(
self,
value: &ty::Binder<T>,
f: C,
) -> Result<Self, Self::Error>
where
T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx>,
{
self.pretty_wrap_binder(value, f)
}
fn typed_value(
mut self,
f: impl FnOnce(Self) -> Result<Self, Self::Error>,
@ -1790,6 +1817,22 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
Ok(inner)
}
pub fn pretty_wrap_binder<T, C: Fn(&T, Self) -> Result<Self, fmt::Error>>(
self,
value: &ty::Binder<T>,
f: C,
) -> Result<Self, fmt::Error>
where
T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>,
{
let old_region_index = self.region_index;
let (new, new_value) = self.name_all_regions(value)?;
let mut inner = f(&new_value.0, new)?;
inner.region_index = old_region_index;
inner.binder_depth -= 1;
Ok(inner)
}
fn prepare_late_bound_region_info<T>(&mut self, value: &ty::Binder<T>)
where
T: TypeFoldable<'tcx>,
@ -1906,12 +1949,12 @@ impl ty::Binder<ty::TraitRef<'tcx>> {
forward_display_to_print! {
Ty<'tcx>,
&'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
&'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>>,
&'tcx ty::Const<'tcx>,
// HACK(eddyb) these are exhaustive instead of generic,
// because `for<'tcx>` isn't possible yet.
ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
ty::Binder<ty::ExistentialPredicate<'tcx>>,
ty::Binder<ty::TraitRef<'tcx>>,
ty::Binder<TraitRefPrintOnlyTraitPath<'tcx>>,
ty::Binder<ty::FnSig<'tcx>>,

View file

@ -603,7 +603,7 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
new_const_val.map(|val| tcx.mk_const(ty::Const { val, ty: a.ty }))
}
impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> {
impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>> {
fn relate<R: TypeRelation<'tcx>>(
relation: &mut R,
a: Self,
@ -616,9 +616,9 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> {
// in `a`.
let mut a_v: Vec<_> = a.into_iter().collect();
let mut b_v: Vec<_> = b.into_iter().collect();
a_v.sort_by(|a, b| a.stable_cmp(tcx, b));
a_v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
a_v.dedup();
b_v.sort_by(|a, b| a.stable_cmp(tcx, b));
b_v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
b_v.dedup();
if a_v.len() != b_v.len() {
return Err(TypeError::ExistentialMismatch(expected_found(relation, a, b)));
@ -626,14 +626,18 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> {
let v = a_v.into_iter().zip(b_v.into_iter()).map(|(ep_a, ep_b)| {
use crate::ty::ExistentialPredicate::*;
match (ep_a, ep_b) {
(Trait(a), Trait(b)) => Ok(Trait(relation.relate(a, b)?)),
(Projection(a), Projection(b)) => Ok(Projection(relation.relate(a, b)?)),
(AutoTrait(a), AutoTrait(b)) if a == b => Ok(AutoTrait(a)),
match (ep_a.skip_binder(), ep_b.skip_binder()) {
(Trait(a), Trait(b)) => Ok(ty::Binder::bind(Trait(
relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(),
))),
(Projection(a), Projection(b)) => Ok(ty::Binder::bind(Projection(
relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(),
))),
(AutoTrait(a), AutoTrait(b)) if a == b => Ok(ep_a.rebind(AutoTrait(a))),
_ => Err(TypeError::ExistentialMismatch(expected_found(relation, a, b))),
}
});
Ok(tcx.mk_existential_predicates(v)?)
Ok(tcx.mk_poly_existential_predicates(v)?)
}
}

View file

@ -843,9 +843,9 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<T> {
}
}
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> {
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Binder<ty::ExistentialPredicate<'tcx>>> {
fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
ty::util::fold_list(self, folder, |tcx, v| tcx.intern_existential_predicates(v))
ty::util::fold_list(self, folder, |tcx, v| tcx.intern_poly_existential_predicates(v))
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {

View file

@ -152,7 +152,7 @@ pub enum TyKind<'tcx> {
FnPtr(PolyFnSig<'tcx>),
/// A trait, defined with `trait`.
Dynamic(Binder<&'tcx List<ExistentialPredicate<'tcx>>>, ty::Region<'tcx>),
Dynamic(&'tcx List<Binder<ExistentialPredicate<'tcx>>>, ty::Region<'tcx>),
/// The anonymous type of a closure. Used to represent the type of
/// `|a| a`.
@ -762,7 +762,7 @@ impl<'tcx> Binder<ExistentialPredicate<'tcx>> {
}
}
impl<'tcx> List<ExistentialPredicate<'tcx>> {
impl<'tcx> List<ty::Binder<ExistentialPredicate<'tcx>>> {
/// Returns the "principal `DefId`" of this set of existential predicates.
///
/// A Rust trait object type consists (in addition to a lifetime bound)
@ -788,64 +788,42 @@ impl<'tcx> List<ExistentialPredicate<'tcx>> {
/// is `{Send, Sync}`, while there is no principal. These trait objects
/// have a "trivial" vtable consisting of just the size, alignment,
/// and destructor.
pub fn principal(&self) -> Option<ExistentialTraitRef<'tcx>> {
match self[0] {
ExistentialPredicate::Trait(tr) => Some(tr),
_ => None,
}
pub fn principal(&self) -> Option<ty::Binder<ExistentialTraitRef<'tcx>>> {
self[0]
.map_bound(|this| match this {
ExistentialPredicate::Trait(tr) => Some(tr),
_ => None,
})
.transpose()
}
pub fn principal_def_id(&self) -> Option<DefId> {
self.principal().map(|trait_ref| trait_ref.def_id)
self.principal().map(|trait_ref| trait_ref.skip_binder().def_id)
}
#[inline]
pub fn projection_bounds<'a>(
&'a self,
) -> impl Iterator<Item = ExistentialProjection<'tcx>> + 'a {
self.iter().filter_map(|predicate| match predicate {
ExistentialPredicate::Projection(projection) => Some(projection),
_ => None,
) -> impl Iterator<Item = ty::Binder<ExistentialProjection<'tcx>>> + 'a {
self.iter().filter_map(|predicate| {
predicate
.map_bound(|pred| match pred {
ExistentialPredicate::Projection(projection) => Some(projection),
_ => None,
})
.transpose()
})
}
#[inline]
pub fn auto_traits<'a>(&'a self) -> impl Iterator<Item = DefId> + 'a {
self.iter().filter_map(|predicate| match predicate {
self.iter().filter_map(|predicate| match predicate.skip_binder() {
ExistentialPredicate::AutoTrait(did) => Some(did),
_ => None,
})
}
}
impl<'tcx> Binder<&'tcx List<ExistentialPredicate<'tcx>>> {
pub fn principal(&self) -> Option<ty::Binder<ExistentialTraitRef<'tcx>>> {
self.map_bound(|b| b.principal()).transpose()
}
pub fn principal_def_id(&self) -> Option<DefId> {
self.skip_binder().principal_def_id()
}
#[inline]
pub fn projection_bounds<'a>(
&'a self,
) -> impl Iterator<Item = PolyExistentialProjection<'tcx>> + 'a {
self.skip_binder().projection_bounds().map(Binder::bind)
}
#[inline]
pub fn auto_traits<'a>(&'a self) -> impl Iterator<Item = DefId> + 'a {
self.skip_binder().auto_traits()
}
pub fn iter<'a>(
&'a self,
) -> impl DoubleEndedIterator<Item = Binder<ExistentialPredicate<'tcx>>> + 'tcx {
self.skip_binder().iter().map(Binder::bind)
}
}
/// A complete reference to a trait. These take numerous guises in syntax,
/// but perhaps the most recognizable form is in a where-clause:
///