about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-08-27 21:04:34 +0000
committerMichael Goulet <michael@errs.io>2023-08-30 15:01:58 -0700
commit0100a94231344987bc93998d5975e656bfd7767d (patch)
tree5fd77277b1918ed078d24645b2e3364f07b86ddd
parent59a8294849358a878a72358aa6d5fe5b9d312867 (diff)
downloadrust-0100a94231344987bc93998d5975e656bfd7767d.tar.gz
rust-0100a94231344987bc93998d5975e656bfd7767d.zip
rustc_layout_scalar_valid_range makes ctors unsafe
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs17
-rw-r--r--tests/ui/unsafe/initializing-ranged-via-ctor.rs11
-rw-r--r--tests/ui/unsafe/initializing-ranged-via-ctor.stderr16
3 files changed, 36 insertions, 8 deletions
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 334e0541c76..01e40c62a8b 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -38,6 +38,7 @@ use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
 use rustc_trait_selection::traits::ObligationCtxt;
 use std::iter;
+use std::ops::Bound;
 
 mod generics_of;
 mod item_bounds;
@@ -1144,15 +1145,15 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<ty::PolyFnSig<
         }
 
         Ctor(data) | Variant(hir::Variant { data, .. }) if data.ctor().is_some() => {
-            let ty = tcx.type_of(tcx.hir().get_parent_item(hir_id)).instantiate_identity();
+            let adt_def_id = tcx.hir().get_parent_item(hir_id).def_id.to_def_id();
+            let ty = tcx.type_of(adt_def_id).instantiate_identity();
             let inputs = data.fields().iter().map(|f| tcx.type_of(f.def_id).instantiate_identity());
-            ty::Binder::dummy(tcx.mk_fn_sig(
-                inputs,
-                ty,
-                false,
-                hir::Unsafety::Normal,
-                abi::Abi::Rust,
-            ))
+            // constructors for structs with `layout_scalar_valid_range` are unsafe to call
+            let safety = match tcx.layout_scalar_valid_range(adt_def_id) {
+                (Bound::Unbounded, Bound::Unbounded) => hir::Unsafety::Normal,
+                _ => hir::Unsafety::Unsafe,
+            };
+            ty::Binder::dummy(tcx.mk_fn_sig(inputs, ty, false, safety, abi::Abi::Rust))
         }
 
         Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
diff --git a/tests/ui/unsafe/initializing-ranged-via-ctor.rs b/tests/ui/unsafe/initializing-ranged-via-ctor.rs
new file mode 100644
index 00000000000..ca44fa7e4e7
--- /dev/null
+++ b/tests/ui/unsafe/initializing-ranged-via-ctor.rs
@@ -0,0 +1,11 @@
+#![feature(rustc_attrs)]
+#![allow(internal_features)]
+
+#[derive(Debug)]
+#[rustc_layout_scalar_valid_range_start(2)]
+struct NonZeroAndOneU8(u8);
+
+fn main() {
+    println!("{:?}", Some(1).map(NonZeroAndOneU8).unwrap());
+    //~^ ERROR found `unsafe fn(u8) -> NonZeroAndOneU8 {NonZeroAndOneU8}`
+}
diff --git a/tests/ui/unsafe/initializing-ranged-via-ctor.stderr b/tests/ui/unsafe/initializing-ranged-via-ctor.stderr
new file mode 100644
index 00000000000..d34554c6641
--- /dev/null
+++ b/tests/ui/unsafe/initializing-ranged-via-ctor.stderr
@@ -0,0 +1,16 @@
+error[E0277]: expected a `FnOnce<({integer},)>` closure, found `unsafe fn(u8) -> NonZeroAndOneU8 {NonZeroAndOneU8}`
+  --> $DIR/initializing-ranged-via-ctor.rs:9:34
+   |
+LL |     println!("{:?}", Some(1).map(NonZeroAndOneU8).unwrap());
+   |                              --- ^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |                              |
+   |                              required by a bound introduced by this call
+   |
+   = help: the trait `FnOnce<({integer},)>` is not implemented for fn item `unsafe fn(u8) -> NonZeroAndOneU8 {NonZeroAndOneU8}`
+   = note: unsafe function cannot be called generically without an unsafe block
+note: required by a bound in `Option::<T>::map`
+  --> $SRC_DIR/core/src/option.rs:LL:COL
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.