Skip to content

Commit 3503a9c

Browse files
Rollup merge of #156956 - Jamesbarford:feat/extend-lift-generic-capabilities, r=lcnr
Support generic params in `Lift_Generic` Handle generic type parameters, including nested occurrences, when deriving `Lift_Generic`. This lets types like `Binder<I, T>` use `#[derive(Lift_Generic)]` instead of requiring a manual `Lift` impl. Concretely it can now handle structs as follows; ```rs // Generic type parameter struct Binder<I: Interner, T> { // body } // Nested generic type parameter pub struct Binder<I: Interner, T = SomeKind<I>> { // } ``` Split off from the `Alias` refactor work; #156538 r? @lcnr
2 parents 730bc39 + 57da2f6 commit 3503a9c

8 files changed

Lines changed: 172 additions & 92 deletions

File tree

compiler/rustc_middle/src/ty/context.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1687,16 +1687,20 @@ macro_rules! nop_lift {
16871687

16881688
macro_rules! nop_list_lift {
16891689
($set:ident; $ty:ty => $lifted:ty) => {
1690-
impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for &'a List<$ty> {
1691-
type Lifted = &'tcx List<$lifted>;
1690+
nop_list_lift! { $set: List; $ty => $lifted }
1691+
};
1692+
// Allows defining own list type
1693+
($set:ident: $list:ident; $ty:ty => $lifted:ty) => {
1694+
impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for &'a $list<$ty> {
1695+
type Lifted = &'tcx $list<$lifted>;
16921696
fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Self::Lifted {
16931697
// Assert that the set has the right type.
16941698
if false {
1695-
let _x: &InternedSet<'tcx, List<$lifted>> = &tcx.interners.$set;
1699+
let _x: &InternedSet<'tcx, $list<$lifted>> = &tcx.interners.$set;
16961700
}
16971701

16981702
if self.is_empty() {
1699-
return List::empty();
1703+
return $list::empty();
17001704
}
17011705
assert!(tcx.interners.$set.contains_pointer_to(&InternedInSet(self)));
17021706
// SAFETY: we just checked that `self` is interned and therefore is valid for the
@@ -1718,10 +1722,15 @@ nop_lift! { layout; Layout<'a> => Layout<'tcx> }
17181722
nop_lift! { valtree; ValTree<'a> => ValTree<'tcx> }
17191723

17201724
nop_list_lift! { type_lists; Ty<'a> => Ty<'tcx> }
1725+
nop_list_lift! { clauses: ListWithCachedTypeInfo; Clause<'a> => Clause<'tcx> }
17211726
nop_list_lift! {
17221727
poly_existential_predicates; PolyExistentialPredicate<'a> => PolyExistentialPredicate<'tcx>
17231728
}
17241729
nop_list_lift! { bound_variable_kinds; ty::BoundVariableKind<'a> => ty::BoundVariableKind<'tcx> }
1730+
nop_list_lift! { patterns; Pattern<'a> => Pattern<'tcx> }
1731+
nop_list_lift! {
1732+
outlives; ty::ArgOutlivesPredicate<'a> => ty::ArgOutlivesPredicate<'tcx>
1733+
}
17251734

17261735
// This is the impl for `&'a GenericArgs<'a>`.
17271736
nop_list_lift! { args; GenericArg<'a> => GenericArg<'tcx> }

compiler/rustc_middle/src/ty/structural_impls.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,6 @@ impl<'tcx> fmt::Debug for Region<'tcx> {
184184
// For things for which the type library provides traversal implementations
185185
// for all Interners, we only need to provide a Lift implementation.
186186
TrivialLiftImpls! {
187-
(),
188187
bool,
189188
usize,
190189
u64,
@@ -197,6 +196,7 @@ TrivialLiftImpls! {
197196
rustc_abi::Size,
198197
rustc_hir::Safety,
199198
rustc_middle::mir::ConstValue,
199+
rustc_span::Symbol,
200200
rustc_type_ir::BoundConstness,
201201
rustc_type_ir::PredicatePolarity,
202202
// tidy-alphabetical-end
@@ -269,6 +269,14 @@ TrivialTypeTraversalAndLiftImpls! {
269269
///////////////////////////////////////////////////////////////////////////
270270
// Lift implementations
271271

272+
impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for ty::ParamEnv<'a> {
273+
type Lifted = ty::ParamEnv<'tcx>;
274+
275+
fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Self::Lifted {
276+
ty::ParamEnv::new(tcx.lift(self.caller_bounds()))
277+
}
278+
}
279+
272280
impl<'tcx, T: Lift<TyCtxt<'tcx>>> Lift<TyCtxt<'tcx>> for Option<T> {
273281
type Lifted = Option<T::Lifted>;
274282
fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Self::Lifted {

compiler/rustc_type_ir/src/binder.rs

Lines changed: 5 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ use tracing::instrument;
1414
use crate::data_structures::SsoHashSet;
1515
use crate::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable};
1616
use crate::inherent::*;
17-
use crate::lift::Lift;
1817
use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
1918
use crate::{self as ty, DebruijnIndex, Interner, UniverseIndex, Unnormalized};
2019

@@ -27,7 +26,7 @@ use crate::{self as ty, DebruijnIndex, Interner, UniverseIndex, Unnormalized};
2726
///
2827
/// `Decodable` and `Encodable` are implemented for `Binder<T>` using the `impl_binder_encode_decode!` macro.
2928
#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner, T)]
30-
#[derive(GenericTypeVisitable)]
29+
#[derive(GenericTypeVisitable, Lift_Generic)]
3130
#[cfg_attr(feature = "nightly", derive(StableHash_NoContext))]
3231
pub struct Binder<I: Interner, T> {
3332
value: T,
@@ -36,23 +35,6 @@ pub struct Binder<I: Interner, T> {
3635

3736
impl<I: Interner, T: Eq> Eq for Binder<I, T> {}
3837

39-
// FIXME: We manually derive `Lift` because the `derive(Lift_Generic)` doesn't
40-
// understand how to turn `T` to `T::Lifted` in the output `type Lifted`.
41-
impl<I: Interner, U: Interner, T> Lift<U> for Binder<I, T>
42-
where
43-
T: Lift<U>,
44-
I::BoundVarKinds: Lift<U, Lifted = U::BoundVarKinds>,
45-
{
46-
type Lifted = Binder<U, T::Lifted>;
47-
48-
fn lift_to_interner(self, cx: U) -> Self::Lifted {
49-
Binder {
50-
value: self.value.lift_to_interner(cx),
51-
bound_vars: self.bound_vars.lift_to_interner(cx),
52-
}
53-
}
54-
}
55-
5638
#[cfg(feature = "nightly")]
5739
macro_rules! impl_binder_encode_decode {
5840
($($t:ty),+ $(,)?) => {
@@ -966,12 +948,13 @@ pub enum BoundVarIndexKind {
966948
/// identified by both a universe, as well as a name residing within that universe. Distinct bound
967949
/// regions/types/consts within the same universe simply have an unknown relationship to one
968950
#[derive_where(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash; I: Interner, T)]
969-
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, GenericTypeVisitable)]
951+
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, GenericTypeVisitable, Lift_Generic)]
970952
#[cfg_attr(
971953
feature = "nightly",
972954
derive(Encodable_NoContext, Decodable_NoContext, StableHash_NoContext)
973955
)]
974956
pub struct Placeholder<I: Interner, T> {
957+
#[lift(identity)]
975958
pub universe: UniverseIndex,
976959
pub bound: T,
977960
#[type_foldable(identity)]
@@ -989,21 +972,6 @@ impl<I: Interner, T: fmt::Debug> fmt::Debug for ty::Placeholder<I, T> {
989972
}
990973
}
991974

992-
impl<I: Interner, U: Interner, T> Lift<U> for Placeholder<I, T>
993-
where
994-
T: Lift<U>,
995-
{
996-
type Lifted = Placeholder<U, T::Lifted>;
997-
998-
fn lift_to_interner(self, cx: U) -> Self::Lifted {
999-
Placeholder {
1000-
universe: self.universe,
1001-
bound: self.bound.lift_to_interner(cx),
1002-
_tcx: PhantomData,
1003-
}
1004-
}
1005-
}
1006-
1007975
#[derive_where(Clone, Copy, PartialEq, Eq, Hash; I: Interner)]
1008976
#[derive(Lift_Generic, GenericTypeVisitable)]
1009977
#[cfg_attr(
@@ -1174,27 +1142,17 @@ impl<I: Interner> PlaceholderRegion<I> {
11741142
}
11751143

11761144
#[derive_where(Clone, Copy, PartialEq, Eq, Hash; I: Interner)]
1177-
#[derive(GenericTypeVisitable)]
1145+
#[derive(GenericTypeVisitable, Lift_Generic)]
11781146
#[cfg_attr(
11791147
feature = "nightly",
11801148
derive(Encodable_NoContext, Decodable_NoContext, StableHash_NoContext)
11811149
)]
11821150
pub struct BoundTy<I: Interner> {
1151+
#[lift(identity)]
11831152
pub var: ty::BoundVar,
11841153
pub kind: BoundTyKind<I>,
11851154
}
11861155

1187-
impl<I: Interner, U: Interner> Lift<U> for BoundTy<I>
1188-
where
1189-
BoundTyKind<I>: Lift<U, Lifted = BoundTyKind<U>>,
1190-
{
1191-
type Lifted = BoundTy<U>;
1192-
1193-
fn lift_to_interner(self, cx: U) -> Self::Lifted {
1194-
BoundTy { var: self.var, kind: self.kind.lift_to_interner(cx) }
1195-
}
1196-
}
1197-
11981156
impl<I: Interner> fmt::Debug for ty::BoundTy<I> {
11991157
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12001158
match self.kind {

compiler/rustc_type_ir/src/interner.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,52 @@ pub trait Interner:
474474
fn item_name(self, item_index: Self::DefId) -> Self::Symbol;
475475
}
476476

477+
macro_rules! declare_lift_into {
478+
($($assoc:ident),* $(,)?) => {
479+
/// An interner whose associated types can be lifted into another interner `J`.
480+
///
481+
/// These are associated type bounds rather than `where` clauses so a caller with
482+
/// `I: LiftInto<J>` can rely on the individual associated type `Lift` bounds being
483+
/// implied.
484+
pub trait LiftInto<J>: Interner<$($assoc: crate::lift::Lift<J, Lifted = J::$assoc>,)*>
485+
where
486+
J: Interner,
487+
{}
488+
489+
impl<I, J> LiftInto<J> for I
490+
where
491+
J: Interner,
492+
I: Interner<$($assoc: crate::lift::Lift<J, Lifted = J::$assoc>,)*>,
493+
{}
494+
};
495+
}
496+
497+
declare_lift_into! {
498+
BoundVarKinds,
499+
Const,
500+
DefId,
501+
FreeConstAliasId,
502+
FreeTyAliasId,
503+
GenericArg,
504+
GenericArgs,
505+
InherentAssocConstId,
506+
InherentAssocTyId,
507+
OpaqueTyId,
508+
ParamEnv,
509+
PatList,
510+
Region,
511+
RegionAssumptions,
512+
Symbol,
513+
Term,
514+
TraitAssocConstId,
515+
TraitAssocTermId,
516+
TraitAssocTyId,
517+
TraitId,
518+
Ty,
519+
Tys,
520+
UnevaluatedConstId,
521+
}
522+
477523
/// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter`
478524
/// that produces `T` items. You could combine them with
479525
/// `f(&iter.collect::<Vec<_>>())`, but this requires allocating memory for the

compiler/rustc_type_ir/src/lift.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,9 @@ pub trait Lift<I>: std::fmt::Debug {
1919
type Lifted: std::fmt::Debug;
2020
fn lift_to_interner(self, cx: I) -> Self::Lifted;
2121
}
22+
23+
impl<I> Lift<I> for () {
24+
type Lifted = ();
25+
26+
fn lift_to_interner(self, _: I) -> Self::Lifted {}
27+
}

compiler/rustc_type_ir/src/predicate.rs

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,14 @@ use rustc_type_ir_macros::{
99
};
1010

1111
use crate::inherent::*;
12-
use crate::lift::Lift;
1312
use crate::upcast::{Upcast, UpcastFrom};
1413
use crate::visit::TypeVisitableExt as _;
1514
use crate::{self as ty, AliasTyKind, Interner, UnevaluatedConstKind};
1615

1716
/// `A: 'region`
1817
#[derive_where(Clone, Hash, PartialEq, Debug; I: Interner, A)]
1918
#[derive_where(Copy; I: Interner, A: Copy)]
20-
#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic)]
19+
#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic, Lift_Generic)]
2120
#[cfg_attr(
2221
feature = "nightly",
2322
derive(Decodable_NoContext, Encodable_NoContext, StableHash_NoContext)
@@ -26,20 +25,6 @@ pub struct OutlivesPredicate<I: Interner, A>(pub A, pub I::Region);
2625

2726
impl<I: Interner, A: Eq> Eq for OutlivesPredicate<I, A> {}
2827

29-
// FIXME: We manually derive `Lift` because the `derive(Lift_Generic)` doesn't
30-
// understand how to turn `A` to `A::Lifted` in the output `type Lifted`.
31-
impl<I: Interner, U: Interner, A> Lift<U> for OutlivesPredicate<I, A>
32-
where
33-
A: Lift<U>,
34-
I::Region: Lift<U, Lifted = U::Region>,
35-
{
36-
type Lifted = OutlivesPredicate<U, A::Lifted>;
37-
38-
fn lift_to_interner(self, cx: U) -> Self::Lifted {
39-
OutlivesPredicate(self.0.lift_to_interner(cx), self.1.lift_to_interner(cx))
40-
}
41-
}
42-
4328
/// `'a == 'b`.
4429
/// For the rationale behind having this instead of a pair of bidirectional
4530
/// `'a: 'b` and `'b: 'a`, see
@@ -210,6 +195,7 @@ pub struct TraitPredicate<I: Interner> {
210195
/// If polarity is Negative: we are proving that a negative impl of this trait
211196
/// exists. (Note that coherence also checks whether negative impls of supertraits
212197
/// exist via a series of predicates.)
198+
#[lift(identity)]
213199
pub polarity: PredicatePolarity,
214200
}
215201

@@ -1036,6 +1022,7 @@ impl<I: Interner> fmt::Debug for NormalizesTo<I> {
10361022
)]
10371023
pub struct HostEffectPredicate<I: Interner> {
10381024
pub trait_ref: ty::TraitRef<I>,
1025+
#[lift(identity)]
10391026
pub constness: BoundConstness,
10401027
}
10411028

@@ -1081,6 +1068,7 @@ impl<I: Interner> ty::Binder<I, HostEffectPredicate<I>> {
10811068
derive(Decodable_NoContext, Encodable_NoContext, StableHash_NoContext)
10821069
)]
10831070
pub struct SubtypePredicate<I: Interner> {
1071+
#[lift(identity)]
10841072
pub a_is_expected: bool,
10851073
pub a: I::Ty,
10861074
pub b: I::Ty,

compiler/rustc_type_ir/src/ty_kind.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -764,14 +764,15 @@ impl<I: Interner> Eq for TypeAndMut<I> {}
764764
/// Contains the packed non-type fields of a function signature.
765765
// FIXME(splat): add the splatted argument index as a u16
766766
#[derive_where(Copy, Clone, PartialEq, Eq, Hash; I: Interner)]
767-
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
767+
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
768768
#[cfg_attr(
769769
feature = "nightly",
770770
derive(Encodable_NoContext, Decodable_NoContext, StableHash_NoContext)
771771
)]
772772
pub struct FnSigKind<I: Interner> {
773773
/// Holds the c_variadic and safety bitflags, and 6 bits for the `ExternAbi` variant and unwind
774774
/// flag.
775+
#[lift(identity)]
775776
#[type_visitable(ignore)]
776777
#[type_foldable(identity)]
777778
flags: u8,
@@ -780,13 +781,6 @@ pub struct FnSigKind<I: Interner> {
780781
_marker: PhantomData<fn() -> I>,
781782
}
782783

783-
impl<I: Interner, J: Interner> crate::lift::Lift<J> for FnSigKind<I> {
784-
type Lifted = FnSigKind<J>;
785-
fn lift_to_interner(self, _cx: J) -> Self::Lifted {
786-
FnSigKind { flags: self.flags, _marker: PhantomData }
787-
}
788-
}
789-
790784
impl<I: Interner> fmt::Debug for FnSigKind<I> {
791785
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
792786
let mut f = f.debug_tuple("FnSigKind");

0 commit comments

Comments
 (0)