Skip to content

Commit f3e8b6a

Browse files
committed
Derive traversables over generic interners
1 parent 8f87cc3 commit f3e8b6a

File tree

3 files changed

+40
-40
lines changed

3 files changed

+40
-40
lines changed

compiler/rustc_macros/src/lib.rs

+10-12
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,12 @@ decl_derive!(
9595
/// to miscompilation if user expectations are not met!** Nevertheless, such can be achieved
9696
/// via a `#[skip_traversal(despite_potential_miscompilation_because = "<reason>"]` attribute.
9797
///
98-
/// If the annotated type has a `'tcx` lifetime parameter, then that will be used as the
99-
/// lifetime for the type context/interner; otherwise the lifetime of the type context/interner
100-
/// will be unrelated to the annotated type. It therefore matters how any lifetime parameters of
101-
/// the annotated type are named. For example, deriving `TypeFoldable` for both `Foo<'a>` and
102-
/// `Bar<'tcx>` will respectively produce:
98+
/// The derived implementation will use `TyCtxt<'tcx>` as the interner iff the annotated type
99+
/// has a `'tcx` lifetime parameter; otherwise it will be generic over all interners. It
100+
/// therefore matters how any lifetime parameters of the annotated type are named. For example,
101+
/// deriving `TypeFoldable` for both `Foo<'a>` and `Bar<'tcx>` will respectively produce:
103102
///
104-
/// `impl<'a, 'tcx> TypeFoldable<TyCtxt<'tcx>> for Foo<'a>`
103+
/// `impl<'a, I: Interner> TypeFoldable<I> for Foo<'a>`
105104
///
106105
/// and
107106
///
@@ -130,13 +129,12 @@ decl_derive!(
130129
/// to miscompilation if user expectations are not met!** Nevertheless, such can be achieved
131130
/// via a `#[skip_traversal(despite_potential_miscompilation_because = "<reason>"]` attribute.
132131
///
133-
/// If the annotated type has a `'tcx` lifetime parameter, then that will be used as the
134-
/// lifetime for the type context/interner; otherwise the lifetime of the type context/interner
135-
/// will be unrelated to the annotated type. It therefore matters how any lifetime parameters of
136-
/// the annotated type are named. For example, deriving `TypeVisitable` for both `Foo<'a>` and
137-
/// `Bar<'tcx>` will respectively produce:
132+
/// The derived implementation will use `TyCtxt<'tcx>` as the interner iff the annotated type
133+
/// has a `'tcx` lifetime parameter; otherwise it will be generic over all interners. It
134+
/// therefore matters how any lifetime parameters of the annotated type are named. For example,
135+
/// deriving `TypeVisitable` for both `Foo<'a>` and `Bar<'tcx>` will respectively produce:
138136
///
139-
/// `impl<'a, 'tcx> TypeVisitable<TyCtxt<'tcx>> for Foo<'a>`
137+
/// `impl<'a, I: Interner> TypeVisitable<I> for Foo<'a>`
140138
///
141139
/// and
142140
///

compiler/rustc_macros/src/traversable.rs

+20-18
Original file line numberDiff line numberDiff line change
@@ -142,28 +142,30 @@ impl WhenToSkip {
142142
}
143143
}
144144

145-
pub struct Interner<'a>(Option<&'a Lifetime>);
145+
pub enum Interner<'a> {
146+
Middle(&'a Lifetime),
147+
Generic(Ident),
148+
}
146149

147150
impl<'a> Interner<'a> {
148-
/// Return the `TyCtxt` interner for the given `structure`.
151+
/// Return the interner for the given `structure`.
149152
///
150-
/// If the input represented by `structure` has a `'tcx` lifetime parameter, then that will be used
151-
/// used as the lifetime of the `TyCtxt`. Otherwise a `'tcx` lifetime parameter that is unrelated
152-
/// to the input will be used.
153-
fn resolve(generics: &'a Generics) -> Self {
154-
Self(
155-
generics
156-
.lifetimes()
157-
.find_map(|def| (def.lifetime.ident == "tcx").then_some(&def.lifetime)),
158-
)
153+
/// If the input represented by `structure` has a `'tcx` lifetime parameter, then `Middle('tcx)`
154+
/// will be returned; otherwise our derived implementation will be generic over a new parameter.
155+
fn resolve(suffix: impl ToString, generics: &'a Generics) -> Self {
156+
generics
157+
.lifetimes()
158+
.find_map(|def| (def.lifetime.ident == "tcx").then_some(Self::Middle(&def.lifetime)))
159+
.unwrap_or_else(|| Self::Generic(gen_param(suffix, generics)))
159160
}
160161
}
161162

162163
impl ToTokens for Interner<'_> {
163164
fn to_tokens(&self, tokens: &mut TokenStream) {
164-
let default = parse_quote! { 'tcx };
165-
let lt = self.0.unwrap_or(&default);
166-
tokens.extend(quote! { ::rustc_middle::ty::TyCtxt<#lt> });
165+
match self {
166+
Interner::Middle(lt) => tokens.extend(quote! { ::rustc_middle::ty::TyCtxt<#lt> }),
167+
Interner::Generic(ident) => ident.to_tokens(tokens),
168+
}
167169
}
168170
}
169171

@@ -301,7 +303,7 @@ impl Interner<'_> {
301303

302304
if !referenced_ty_params.is_empty() {
303305
Generic
304-
} else if let Some(interner) = &self.0 && fields.into_iter().any(|field| {
306+
} else if let Interner::Middle(interner) = self && fields.into_iter().any(|field| {
305307
let mut info = Info { interner, contains_interner: false };
306308
info.visit_type(&field.ty);
307309
info.contains_interner
@@ -320,7 +322,7 @@ pub fn traversable_derive<T: Traversable>(
320322

321323
let ast = structure.ast();
322324

323-
let interner = Interner::resolve(&ast.generics);
325+
let interner = Interner::resolve("I", &ast.generics);
324326
let traverser = gen_param("T", &ast.generics);
325327
let traversable = T::traversable(&interner);
326328

@@ -331,8 +333,8 @@ pub fn traversable_derive<T: Traversable>(
331333
structure.add_bounds(synstructure::AddBounds::None);
332334
structure.bind_with(|_| synstructure::BindStyle::Move);
333335

334-
let not_generic = if interner.0.is_none() {
335-
structure.add_impl_generic(parse_quote! { 'tcx });
336+
let not_generic = if let Interner::Generic(ident) = &interner {
337+
structure.add_impl_generic(parse_quote! { #ident: ::rustc_type_ir::Interner });
336338
Trivial
337339
} else {
338340
NotGeneric

compiler/rustc_macros/src/traversable/tests.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -284,11 +284,11 @@ fn skipping_generic_type_requires_justification() {
284284
#[skip_traversal(despite_potential_miscompilation_because = ".")]
285285
struct SomethingInteresting<T>;
286286
} => {
287-
impl<'tcx, T> TypeFoldable<TyCtxt<'tcx>> for SomethingInteresting<T>
287+
impl<I: Interner, T> TypeFoldable<I> for SomethingInteresting<T>
288288
where
289-
Self: TypeVisitable<TyCtxt<'tcx>>
289+
Self: TypeVisitable<I>
290290
{
291-
fn try_fold_with<_T: FallibleTypeFolder<TyCtxt<'tcx>>>(self, folder: &mut _T) -> Result<Self, _T::Error> {
291+
fn try_fold_with<_T: FallibleTypeFolder<I>>(self, folder: &mut _T) -> Result<Self, _T::Error> {
292292
Ok(self) // no attempt to fold fields
293293
}
294294
}
@@ -312,12 +312,12 @@ fn skipping_generic_field_requires_justification() {
312312
T,
313313
);
314314
} => {
315-
impl<'tcx, T> TypeFoldable<TyCtxt<'tcx>> for SomethingInteresting<T>
315+
impl<I: Interner, T> TypeFoldable<I> for SomethingInteresting<T>
316316
where
317-
Self: TypeVisitable<TyCtxt<'tcx>>,
318-
TyCtxt<'tcx>: TriviallyTraverses<T> // `because_trivial`
317+
I: TriviallyTraverses<T>, // `because_trivial`
318+
Self: TypeVisitable<I>
319319
{
320-
fn try_fold_with<_T: FallibleTypeFolder<TyCtxt<'tcx>>>(self, folder: &mut _T) -> Result<Self, _T::Error> {
320+
fn try_fold_with<_T: FallibleTypeFolder<I>>(self, folder: &mut _T) -> Result<Self, _T::Error> {
321321
Ok(match self {
322322
SomethingInteresting(__binding_0,) => { SomethingInteresting(__binding_0,) } // not folded
323323
})
@@ -331,11 +331,11 @@ fn skipping_generic_field_requires_justification() {
331331
T,
332332
);
333333
} => {
334-
impl<'tcx, T> TypeFoldable<TyCtxt<'tcx>> for SomethingInteresting<T>
334+
impl<I: Interner, T> TypeFoldable<I> for SomethingInteresting<T>
335335
where
336-
Self: TypeVisitable<TyCtxt<'tcx>> // no constraint on T
336+
Self: TypeVisitable<I> // no constraint on T
337337
{
338-
fn try_fold_with<_T: FallibleTypeFolder<TyCtxt<'tcx>>>(self, folder: &mut _T) -> Result<Self, _T::Error> {
338+
fn try_fold_with<_T: FallibleTypeFolder<I>>(self, folder: &mut _T) -> Result<Self, _T::Error> {
339339
Ok(match self {
340340
SomethingInteresting(__binding_0,) => { SomethingInteresting(__binding_0,) } // not folded
341341
})

0 commit comments

Comments
 (0)