about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2023-09-18 13:02:19 +0200
committerGitHub <noreply@github.com>2023-09-18 13:02:19 +0200
commit0d29cdd18794dd72901d2f4093b99bf0fec32ca7 (patch)
tree7ddd2636950502bff925b72f98c9b717172a46a8
parent497701876f549cd2c39eb789cc98b30a850265ab (diff)
parent3b817b2810ff7ecacab02f901f2a1a2902e5e72f (diff)
downloadrust-0d29cdd18794dd72901d2f4093b99bf0fec32ca7.tar.gz
rust-0d29cdd18794dd72901d2f4093b99bf0fec32ca7.zip
Rollup merge of #115907 - RalfJung:interner-check, r=compiler-errors
nop_lift macros: ensure that we are using the right interner

Right now someone could put down the wrong list name when using these macros, and everything would still build. Nothing does a type-check to ensure that the `$set` contains element of type `Self::Lifted`. Let's fix that.

For lists this is fairly easy; for the other interners we need to unwrap some newtypes which makes this more complicated.
-rw-r--r--compiler/rustc_middle/src/ty/context.rs24
1 files changed, 24 insertions, 0 deletions
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 880d3029451..e8d50a1c025 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1214,6 +1214,25 @@ macro_rules! nop_lift {
         impl<'a, 'tcx> Lift<'tcx> for $ty {
             type Lifted = $lifted;
             fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+                // Assert that the set has the right type.
+                // Given an argument that has an interned type, the return type has the type of
+                // the corresponding interner set. This won't actually return anything, we're
+                // just doing this to compute said type!
+                fn _intern_set_ty_from_interned_ty<'tcx, Inner>(
+                    _x: Interned<'tcx, Inner>,
+                ) -> InternedSet<'tcx, Inner> {
+                    unreachable!()
+                }
+                fn _type_eq<T>(_x: &T, _y: &T) {}
+                fn _test<'tcx>(x: $lifted, tcx: TyCtxt<'tcx>) {
+                    // If `x` is a newtype around an `Interned<T>`, then `interner` is an
+                    // interner of appropriate type. (Ideally we'd also check that `x` is a
+                    // newtype with just that one field. Not sure how to do that.)
+                    let interner = _intern_set_ty_from_interned_ty(x.0);
+                    // Now check that this is the same type as `interners.$set`.
+                    _type_eq(&interner, &tcx.interners.$set);
+                }
+
                 tcx.interners
                     .$set
                     .contains_pointer_to(&InternedInSet(&*self.0.0))
@@ -1230,6 +1249,11 @@ macro_rules! nop_list_lift {
         impl<'a, 'tcx> Lift<'tcx> for &'a List<$ty> {
             type Lifted = &'tcx List<$lifted>;
             fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
+                // Assert that the set has the right type.
+                if false {
+                    let _x: &InternedSet<'tcx, List<$lifted>> = &tcx.interners.$set;
+                }
+
                 if self.is_empty() {
                     return Some(List::empty());
                 }