about summary refs log tree commit diff
path: root/compiler/rustc_mir_build/src/thir
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-11-08 20:42:32 +0000
committerbors <bors@rust-lang.org>2023-11-08 20:42:32 +0000
commitfdaaaf9f923281ab98b865259aa40fbf93d72c7a (patch)
tree3a4c4d48c50672184c66f5f4605aade7275e864e /compiler/rustc_mir_build/src/thir
parent90fdc1fc270fef7d1a999207f1da29b41da70dac (diff)
parent30588657b753b9ae500b3514d58da18a4a155b08 (diff)
downloadrust-fdaaaf9f923281ab98b865259aa40fbf93d72c7a.tar.gz
rust-fdaaaf9f923281ab98b865259aa40fbf93d72c7a.zip
Auto merge of #116930 - RalfJung:raw-ptr-match, r=davidtwco
patterns: reject raw pointers that are not just integers

Matching against `0 as *const i32` is fine, matching against `&42 as *const i32` is not.

This extends the existing check against function pointers and wide pointers: we now uniformly reject all these pointer types during valtree construction, and then later lint because of that. See [here](https://github.com/rust-lang/rust/pull/116930#issuecomment-1784654073) for some more explanation and context.

Also fixes https://github.com/rust-lang/rust/issues/116929.

Cc `@oli-obk` `@lcnr`
Diffstat (limited to 'compiler/rustc_mir_build/src/thir')
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs61
1 files changed, 31 insertions, 30 deletions
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index fc03f7891a8..48a590f5d37 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -123,6 +123,8 @@ impl<'tcx> ConstToPat<'tcx> {
         });
         debug!(?check_body_for_struct_match_violation, ?mir_structural_match_violation);
 
+        let have_valtree =
+            matches!(cv, mir::Const::Ty(c) if matches!(c.kind(), ty::ConstKind::Value(_)));
         let inlined_const_as_pat = match cv {
             mir::Const::Ty(c) => match c.kind() {
                 ty::ConstKind::Param(_)
@@ -209,16 +211,6 @@ impl<'tcx> ConstToPat<'tcx> {
                 } else if !self.saw_const_match_lint.get() {
                     if let Some(mir_structural_match_violation) = mir_structural_match_violation {
                         match non_sm_ty.kind() {
-                            ty::RawPtr(pointee)
-                                if pointee.ty.is_sized(self.tcx(), self.param_env) => {}
-                            ty::FnPtr(..) | ty::RawPtr(..) => {
-                                self.tcx().emit_spanned_lint(
-                                    lint::builtin::POINTER_STRUCTURAL_MATCH,
-                                    self.id,
-                                    self.span,
-                                    PointerPattern,
-                                );
-                            }
                             ty::Adt(..) if mir_structural_match_violation => {
                                 self.tcx().emit_spanned_lint(
                                     lint::builtin::INDIRECT_STRUCTURAL_MATCH,
@@ -236,19 +228,15 @@ impl<'tcx> ConstToPat<'tcx> {
                         }
                     }
                 }
-            } else if !self.saw_const_match_lint.get() {
-                match cv.ty().kind() {
-                    ty::RawPtr(pointee) if pointee.ty.is_sized(self.tcx(), self.param_env) => {}
-                    ty::FnPtr(..) | ty::RawPtr(..) => {
-                        self.tcx().emit_spanned_lint(
-                            lint::builtin::POINTER_STRUCTURAL_MATCH,
-                            self.id,
-                            self.span,
-                            PointerPattern,
-                        );
-                    }
-                    _ => {}
-                }
+            } else if !have_valtree && !self.saw_const_match_lint.get() {
+                // The only way valtree construction can fail without the structural match
+                // checker finding a violation is if there is a pointer somewhere.
+                self.tcx().emit_spanned_lint(
+                    lint::builtin::POINTER_STRUCTURAL_MATCH,
+                    self.id,
+                    self.span,
+                    PointerPattern,
+                );
             }
 
             // Always check for `PartialEq`, even if we emitted other lints. (But not if there were
@@ -389,11 +377,19 @@ impl<'tcx> ConstToPat<'tcx> {
                 subpatterns: self
                     .field_pats(cv.unwrap_branch().iter().copied().zip(fields.iter()))?,
             },
-            ty::Adt(def, args) => PatKind::Leaf {
-                subpatterns: self.field_pats(cv.unwrap_branch().iter().copied().zip(
-                    def.non_enum_variant().fields.iter().map(|field| field.ty(self.tcx(), args)),
-                ))?,
-            },
+            ty::Adt(def, args) => {
+                assert!(!def.is_union()); // Valtree construction would never succeed for unions.
+                PatKind::Leaf {
+                    subpatterns: self.field_pats(
+                        cv.unwrap_branch().iter().copied().zip(
+                            def.non_enum_variant()
+                                .fields
+                                .iter()
+                                .map(|field| field.ty(self.tcx(), args)),
+                        ),
+                    )?,
+                }
+            }
             ty::Slice(elem_ty) => PatKind::Slice {
                 prefix: cv
                     .unwrap_branch()
@@ -480,10 +476,15 @@ impl<'tcx> ConstToPat<'tcx> {
                     }
                 }
             },
-            ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) => {
+            ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::RawPtr(..) => {
+                // The raw pointers we see here have been "vetted" by valtree construction to be
+                // just integers, so we simply allow them.
                 PatKind::Constant { value: mir::Const::Ty(ty::Const::new_value(tcx, cv, ty)) }
             }
-            ty::FnPtr(..) | ty::RawPtr(..) => unreachable!(),
+            ty::FnPtr(..) => {
+                // Valtree construction would never succeed for these, so this is unreachable.
+                unreachable!()
+            }
             _ => {
                 let err = InvalidPattern { span, non_sm_ty: ty };
                 let e = tcx.sess.emit_err(err);