about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDrMeepster <19316085+DrMeepster@users.noreply.github.com>2023-04-16 14:13:29 -0700
committerDrMeepster <19316085+DrMeepster@users.noreply.github.com>2023-04-21 02:14:03 -0700
commitb92c2f792c33fbb180358997c5368f336f8912d2 (patch)
tree810354c07ce694399c29c46949fc722e48aa712e
parentb95852b93c8a7b70f9238b0bbd787de68c9241bd (diff)
downloadrust-b92c2f792c33fbb180358997c5368f336f8912d2.tar.gz
rust-b92c2f792c33fbb180358997c5368f336f8912d2.zip
fix incorrect param env in dead code lint
-rw-r--r--compiler/rustc_passes/src/dead.rs9
-rw-r--r--library/core/tests/mem.rs2
-rw-r--r--tests/ui/lint/dead-code/offset-of-correct-param-env.rs40
-rw-r--r--tests/ui/lint/dead-code/offset-of.rs (renamed from tests/ui/liveness/liveness-offset-of.rs)0
-rw-r--r--tests/ui/lint/dead-code/offset-of.stderr (renamed from tests/ui/liveness/liveness-offset-of.stderr)0
5 files changed, 46 insertions, 5 deletions
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 82b55df106c..170b0b91e57 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -242,7 +242,9 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
         let &(container, ref indices) =
             data.get(expr.hir_id).expect("no offset_of_data for offset_of");
 
-        let mut last_did = expr.hir_id.owner.to_def_id();
+        let body_did = self.typeck_results().hir_owner.to_def_id();
+        let param_env = self.tcx.param_env(body_did);
+
         let mut current_ty = container;
 
         for &index in indices {
@@ -253,15 +255,14 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
                     self.insert_def_id(field.did);
                     let field_ty = field.ty(self.tcx, subst);
 
-                    last_did = field.did;
                     current_ty =
-                        self.tcx.normalize_erasing_regions(self.tcx.param_env(field.did), field_ty);
+                        self.tcx.normalize_erasing_regions(param_env, field_ty);
                 }
                 // we don't need to mark tuple fields as live,
                 // but we may need to mark subfields
                 ty::Tuple(tys) => {
                     current_ty = self.tcx.normalize_erasing_regions(
-                        self.tcx.param_env(last_did),
+                        param_env,
                         tys[index.as_usize()],
                     );
                 }
diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs
index 2351406ddd2..b2a7df6b2e9 100644
--- a/library/core/tests/mem.rs
+++ b/library/core/tests/mem.rs
@@ -458,4 +458,4 @@ fn offset_of_addr() {
     assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, y), ptr::addr_of!(base.y).addr());
     assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, z.0), ptr::addr_of!(base.z.0).addr());
     assert_eq!(ptr::addr_of!(base).addr() + offset_of!(Foo, z.1), ptr::addr_of!(base.z.1).addr());
-}
+}
\ No newline at end of file
diff --git a/tests/ui/lint/dead-code/offset-of-correct-param-env.rs b/tests/ui/lint/dead-code/offset-of-correct-param-env.rs
new file mode 100644
index 00000000000..b7444049a88
--- /dev/null
+++ b/tests/ui/lint/dead-code/offset-of-correct-param-env.rs
@@ -0,0 +1,40 @@
+// check-pass
+
+#![feature(offset_of)]
+#![deny(dead_code)]
+
+// This struct contains a projection that can only be normalized after getting the field type.
+struct A<T: Project> {
+    a: <T as Project>::EquateParamTo,
+}
+
+// This is the inner struct that we want to get.
+struct MyFieldIsNotDead {
+    not_dead: u8,
+}
+
+// These are some helpers.
+// Inside the param env of `test`, we want to make it so that it considers T=MyFieldIsNotDead.
+struct GenericIsEqual<T>(T);
+trait Project {
+    type EquateParamTo;
+}
+impl<T> Project for GenericIsEqual<T> {
+    type EquateParamTo = T;
+}
+
+fn test<T>() -> usize
+where
+    GenericIsEqual<T>: Project<EquateParamTo = MyFieldIsNotDead>,
+{
+	// The first field of the A that we construct here is `<GenericIsEqual<T>> as Project>::EquateParamTo`.
+	// Typeck normalizes this and figures that the not_dead field is totally fine and accessible.
+	// But importantly, the normalization ends up with T, which, as we've declared in our param env is MyFieldDead.
+	// When we're in the param env of the `a` field, the where bound above is not in scope, so we don't know what T is - it's generic.
+	// We cannot access a field on T. Boom!
+    std::mem::offset_of!(A<GenericIsEqual<T>>, a.not_dead)
+}
+
+fn main() {
+    test::<MyFieldIsNotDead>();
+}
\ No newline at end of file
diff --git a/tests/ui/liveness/liveness-offset-of.rs b/tests/ui/lint/dead-code/offset-of.rs
index da91de3862f..da91de3862f 100644
--- a/tests/ui/liveness/liveness-offset-of.rs
+++ b/tests/ui/lint/dead-code/offset-of.rs
diff --git a/tests/ui/liveness/liveness-offset-of.stderr b/tests/ui/lint/dead-code/offset-of.stderr
index afc4c590eeb..afc4c590eeb 100644
--- a/tests/ui/liveness/liveness-offset-of.stderr
+++ b/tests/ui/lint/dead-code/offset-of.stderr