Skip to content

Commit 09db709

Browse files
committed
Derive traversables over generic interners
1 parent 488d6ce commit 09db709

File tree

3 files changed

+40
-40
lines changed

3 files changed

+40
-40
lines changed

compiler/rustc_macros/src/lib.rs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,12 @@ decl_derive!(
9393
/// to miscompilation if user expectations are not met!** Nevertheless, such can be achieved
9494
/// via a `#[skip_traversal(despite_potential_miscompilation_because = "<reason>"]` attribute.
9595
///
96-
/// If the annotated type has a `'tcx` lifetime parameter, then that will be used as the
97-
/// lifetime for the type context/interner; otherwise the lifetime of the type context/interner
98-
/// will be unrelated to the annotated type. It therefore matters how any lifetime parameters of
99-
/// the annotated type are named. For example, deriving `TypeFoldable` for both `Foo<'a>` and
100-
/// `Bar<'tcx>` will respectively produce:
96+
/// The derived implementation will use `TyCtxt<'tcx>` as the interner iff the annotated type
97+
/// has a `'tcx` lifetime parameter; otherwise it will be generic over all interners. It
98+
/// therefore matters how any lifetime parameters of the annotated type are named. For example,
99+
/// deriving `TypeFoldable` for both `Foo<'a>` and `Bar<'tcx>` will respectively produce:
101100
///
102-
/// `impl<'a, 'tcx> TypeFoldable<TyCtxt<'tcx>> for Foo<'a>`
101+
/// `impl<'a, I: Interner> TypeFoldable<I> for Foo<'a>`
103102
///
104103
/// and
105104
///
@@ -125,13 +124,12 @@ decl_derive!(
125124
/// to miscompilation if user expectations are not met!** Nevertheless, such can be achieved
126125
/// via a `#[skip_traversal(despite_potential_miscompilation_because = "<reason>"]` attribute.
127126
///
128-
/// If the annotated type has a `'tcx` lifetime parameter, then that will be used as the
129-
/// lifetime for the type context/interner; otherwise the lifetime of the type context/interner
130-
/// will be unrelated to the annotated type. It therefore matters how any lifetime parameters of
131-
/// the annotated type are named. For example, deriving `TypeVisitable` for both `Foo<'a>` and
132-
/// `Bar<'tcx>` will respectively produce:
127+
/// The derived implementation will use `TyCtxt<'tcx>` as the interner iff the annotated type
128+
/// has a `'tcx` lifetime parameter; otherwise it will be generic over all interners. It
129+
/// therefore matters how any lifetime parameters of the annotated type are named. For example,
130+
/// deriving `TypeVisitable` for both `Foo<'a>` and `Bar<'tcx>` will respectively produce:
133131
///
134-
/// `impl<'a, 'tcx> TypeVisitable<TyCtxt<'tcx>> for Foo<'a>`
132+
/// `impl<'a, I: Interner> TypeVisitable<I> for Foo<'a>`
135133
///
136134
/// and
137135
///

compiler/rustc_macros/src/traversable.rs

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -113,28 +113,30 @@ impl WhenToSkip {
113113
}
114114
}
115115

116-
pub struct Interner<'a>(Option<&'a Lifetime>);
116+
pub enum Interner<'a> {
117+
Middle(&'a Lifetime),
118+
Generic(Ident),
119+
}
117120

118121
impl<'a> Interner<'a> {
119-
/// Return the `TyCtxt` interner for the given `structure`.
122+
/// Return the interner for the given `structure`.
120123
///
121-
/// If the input represented by `structure` has a `'tcx` lifetime parameter, then that will be used
122-
/// used as the lifetime of the `TyCtxt`. Otherwise a `'tcx` lifetime parameter that is unrelated
123-
/// to the input will be used.
124-
fn resolve(generics: &'a Generics) -> Self {
125-
Self(
126-
generics
127-
.lifetimes()
128-
.find_map(|def| (def.lifetime.ident == "tcx").then_some(&def.lifetime)),
129-
)
124+
/// If the input represented by `structure` has a `'tcx` lifetime parameter, then `Middle('tcx)`
125+
/// will be returned; otherwise our derived implementation will be generic over a new parameter.
126+
fn resolve(suffix: impl ToString, generics: &'a Generics) -> Self {
127+
generics
128+
.lifetimes()
129+
.find_map(|def| (def.lifetime.ident == "tcx").then_some(Self::Middle(&def.lifetime)))
130+
.unwrap_or_else(|| Self::Generic(gen_param(suffix, generics)))
130131
}
131132
}
132133

133134
impl ToTokens for Interner<'_> {
134135
fn to_tokens(&self, tokens: &mut TokenStream) {
135-
let default = parse_quote! { 'tcx };
136-
let lt = self.0.unwrap_or(&default);
137-
tokens.extend(quote! { ::rustc_middle::ty::TyCtxt<#lt> });
136+
match self {
137+
Interner::Middle(lt) => tokens.extend(quote! { ::rustc_middle::ty::TyCtxt<#lt> }),
138+
Interner::Generic(ident) => ident.to_tokens(tokens),
139+
}
138140
}
139141
}
140142

@@ -273,8 +275,8 @@ impl Interner<'_> {
273275
if !referenced_ty_params.is_empty() {
274276
Generic
275277
} else {
276-
match &self.0 {
277-
Some(interner)
278+
match self {
279+
Interner::Middle(interner)
278280
if fields.into_iter().any(|field| {
279281
let mut visitor = Visitor { interner, contains_interner: false };
280282
visitor.visit_type(&field.ty);
@@ -298,16 +300,16 @@ pub fn traversable_derive<T: Traversable>(
298300

299301
let ast = structure.ast();
300302

301-
let interner = Interner::resolve(&ast.generics);
303+
let interner = Interner::resolve("I", &ast.generics);
302304
let traverser = gen_param("T", &ast.generics);
303305
let traversable = T::traversable(&interner);
304306

305307
structure.underscore_const(true);
306308
structure.add_bounds(synstructure::AddBounds::None);
307309
structure.bind_with(|_| synstructure::BindStyle::Move);
308310

309-
let not_generic = if interner.0.is_none() {
310-
structure.add_impl_generic(parse_quote! { 'tcx });
311+
let not_generic = if let Interner::Generic(ident) = &interner {
312+
structure.add_impl_generic(parse_quote! { #ident: ::rustc_type_ir::Interner });
311313
Boring
312314
} else {
313315
NotGeneric

compiler/rustc_macros/src/traversable/tests.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -275,11 +275,11 @@ fn skipping_generic_type_requires_justification() {
275275
#[skip_traversal(despite_potential_miscompilation_because = ".")]
276276
struct SomethingInteresting<T>;
277277
} => {
278-
impl<'tcx, T> TypeFoldable<TyCtxt<'tcx>> for SomethingInteresting<T>
278+
impl<I: Interner, T> TypeFoldable<I> for SomethingInteresting<T>
279279
where
280-
Self: TypeVisitable<TyCtxt<'tcx>>
280+
Self: TypeVisitable<I>
281281
{
282-
fn try_fold_with<_T: FallibleTypeFolder<TyCtxt<'tcx>>>(self, folder: &mut _T) -> Result<Self, _T::Error> {
282+
fn try_fold_with<_T: FallibleTypeFolder<I>>(self, folder: &mut _T) -> Result<Self, _T::Error> {
283283
Ok(self) // no attempt to fold fields
284284
}
285285
}
@@ -303,12 +303,12 @@ fn skipping_generic_field_requires_justification() {
303303
T,
304304
);
305305
} => {
306-
impl<'tcx, T> TypeFoldable<TyCtxt<'tcx>> for SomethingInteresting<T>
306+
impl<I: Interner, T> TypeFoldable<I> for SomethingInteresting<T>
307307
where
308-
Self: TypeVisitable<TyCtxt<'tcx>>,
308+
Self: TypeVisitable<I>,
309309
T: BoringTraversable // `because_boring`
310310
{
311-
fn try_fold_with<_T: FallibleTypeFolder<TyCtxt<'tcx>>>(self, folder: &mut _T) -> Result<Self, _T::Error> {
311+
fn try_fold_with<_T: FallibleTypeFolder<I>>(self, folder: &mut _T) -> Result<Self, _T::Error> {
312312
Ok(match self {
313313
SomethingInteresting(__binding_0,) => { SomethingInteresting(__binding_0,) } // not folded
314314
})
@@ -322,11 +322,11 @@ fn skipping_generic_field_requires_justification() {
322322
T,
323323
);
324324
} => {
325-
impl<'tcx, T> TypeFoldable<TyCtxt<'tcx>> for SomethingInteresting<T>
325+
impl<I: Interner, T> TypeFoldable<I> for SomethingInteresting<T>
326326
where
327-
Self: TypeVisitable<TyCtxt<'tcx>> // no constraint on T
327+
Self: TypeVisitable<I> // no constraint on T
328328
{
329-
fn try_fold_with<_T: FallibleTypeFolder<TyCtxt<'tcx>>>(self, folder: &mut _T) -> Result<Self, _T::Error> {
329+
fn try_fold_with<_T: FallibleTypeFolder<I>>(self, folder: &mut _T) -> Result<Self, _T::Error> {
330330
Ok(match self {
331331
SomethingInteresting(__binding_0,) => { SomethingInteresting(__binding_0,) } // not folded
332332
})

0 commit comments

Comments
 (0)