Skip to content

rustc_layout_scalar_valid_range makes ctors unsafe #115290

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 { .. }, .. }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,12 +266,10 @@ impl<T> Trait<T> for X {
}
}
}
(ty::FnPtr(_), ty::FnDef(def, _))
if let hir::def::DefKind::Fn = tcx.def_kind(def) => {
diag.note(
"when the arguments and return types match, functions can be coerced \
to function pointers",
);
(ty::FnPtr(sig), ty::FnDef(def_id, _)) | (ty::FnDef(def_id, _), ty::FnPtr(sig)) => {
if tcx.fn_sig(*def_id).skip_binder().unsafety() < sig.unsafety() {
diag.note("unsafe functions cannot be coerced into safe function pointers");
}
}
_ => {}
}
Expand Down
1 change: 0 additions & 1 deletion tests/ui/argument-suggestions/two-mismatch-notes.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ LL | foo(f, w);
| ^
= note: expected fn pointer `fn(i32)`
found fn item `fn(u32) {f}`
= note: when the arguments and return types match, functions can be coerced to function pointers
note: expected `Wrapper<i32>`, found `Wrapper<isize>`
--> $DIR/two-mismatch-notes.rs:10:12
|
Expand Down
2 changes: 0 additions & 2 deletions tests/ui/c-variadic/variadic-ffi-1.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ LL | let x: unsafe extern "C" fn(f: isize, x: u8) = foo;
|
= note: expected fn pointer `unsafe extern "C" fn(_, _)`
found fn item `unsafe extern "C" fn(_, _, ...) {foo}`
= note: when the arguments and return types match, functions can be coerced to function pointers

error[E0308]: mismatched types
--> $DIR/variadic-ffi-1.rs:26:54
Expand All @@ -58,7 +57,6 @@ LL | let y: extern "C" fn(f: isize, x: u8, ...) = bar;
|
= note: expected fn pointer `extern "C" fn(_, _, ...)`
found fn item `extern "C" fn(_, _) {bar}`
= note: when the arguments and return types match, functions can be coerced to function pointers

error[E0617]: can't pass `f32` to variadic function
--> $DIR/variadic-ffi-1.rs:28:19
Expand Down
1 change: 0 additions & 1 deletion tests/ui/fn/fn-pointer-mismatch.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ LL | let e: &fn(u32) -> u32 = &foo;
= note: expected reference `&fn(u32) -> u32`
found reference `&fn(u32) -> u32 {foo}`
= note: fn items are distinct from fn pointers
= note: when the arguments and return types match, functions can be coerced to function pointers
help: consider casting to a fn pointer
|
LL | let e: &fn(u32) -> u32 = &(foo as fn(u32) -> u32);
Expand Down
1 change: 0 additions & 1 deletion tests/ui/fn/signature-error-reporting-under-verbose.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,4 @@ fn main() {
//~| NOTE expected fn pointer, found fn item
//~| NOTE expected fn pointer `fn(i32, u32)`
//~| NOTE arguments to this function are incorrect
//~| NOTE when the arguments and return types match, functions can be coerced to function pointers
}
1 change: 0 additions & 1 deletion tests/ui/fn/signature-error-reporting-under-verbose.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ LL | needs_ptr(foo);
|
= note: expected fn pointer `fn(i32, u32)`
found fn item `fn(i32, i32) {foo}`
= note: when the arguments and return types match, functions can be coerced to function pointers
note: function defined here
--> $DIR/signature-error-reporting-under-verbose.rs:5:4
|
Expand Down
1 change: 0 additions & 1 deletion tests/ui/issues/issue-10764.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ LL | fn main() { f(bar) }
|
= note: expected fn pointer `fn()`
found fn item `extern "C" fn() {bar}`
= note: when the arguments and return types match, functions can be coerced to function pointers
note: function defined here
--> $DIR/issue-10764.rs:1:4
|
Expand Down
1 change: 0 additions & 1 deletion tests/ui/mismatched_types/normalize-fn-sig.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ LL | needs_i32_ref_fn(foo::<()>);
|
= note: expected fn pointer `fn(&'static i32, i32)`
found fn item `fn(i32, &'static i32) {foo::<()>}`
= note: when the arguments and return types match, functions can be coerced to function pointers
note: function defined here
--> $DIR/normalize-fn-sig.rs:11:4
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ LL | let _: fn(&mut &isize, &mut &isize) = a;
|
= note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b isize, &'c mut &'d isize)`
found fn item `for<'a, 'b> fn(&'a mut &isize, &'b mut &isize) {a::<'_, '_>}`
= note: when the arguments and return types match, functions can be coerced to function pointers

error: aborting due to previous error

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a;
|
= note: expected fn pointer `for<'a, 'b, 'c, 'd, 'e, 'f> fn(&'a mut &'b isize, &'c mut &'d isize, &'e mut &'f isize)`
found fn item `for<'a, 'b, 'c> fn(&'a mut &isize, &'b mut &isize, &'c mut &isize) {a::<'_, '_, '_>}`
= note: when the arguments and return types match, functions can be coerced to function pointers

error: aborting due to previous error

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ LL | want_G(baz);
|
= note: expected fn pointer `for<'cx> fn(&'cx S) -> &'static S`
found fn item `for<'a> fn(&'a S) -> &'a S {baz}`
= note: when the arguments and return types match, functions can be coerced to function pointers
note: function defined here
--> $DIR/regions-fn-subtyping-return-static-fail.rs:20:4
|
Expand Down
1 change: 0 additions & 1 deletion tests/ui/regions/regions-lifetime-bounds-on-fns.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ LL | let _: fn(&mut &isize, &mut &isize) = a;
|
= note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b isize, &'c mut &'d isize)`
found fn item `for<'a, 'b> fn(&'a mut &isize, &'b mut &isize) {a::<'_, '_>}`
= note: when the arguments and return types match, functions can be coerced to function pointers

error: aborting due to previous error

Expand Down
1 change: 0 additions & 1 deletion tests/ui/reify-intrinsic.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ LL | let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::tr
|
= note: expected fn pointer `unsafe extern "rust-intrinsic" fn(isize) -> usize`
found fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}`
= note: when the arguments and return types match, functions can be coerced to function pointers

error[E0606]: casting `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` as `unsafe extern "rust-intrinsic" fn(isize) -> usize` is invalid
--> $DIR/reify-intrinsic.rs:11:13
Expand Down
1 change: 0 additions & 1 deletion tests/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ LL | let foo: fn() = foo;
found fn item `fn() {foo}`
= note: fn items are distinct from fn pointers
= note: functions with `#[target_feature]` can only be coerced to `unsafe` function pointers
= note: when the arguments and return types match, functions can be coerced to function pointers
help: consider casting to a fn pointer
|
LL | let foo: fn() = foo as fn();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ LL | let foo: fn() = foo;
found fn item `fn() {foo}`
= note: fn items are distinct from fn pointers
= note: functions with `#[target_feature]` can only be coerced to `unsafe` function pointers
= note: when the arguments and return types match, functions can be coerced to function pointers
help: consider casting to a fn pointer
|
LL | let foo: fn() = foo as fn();
Expand Down
1 change: 0 additions & 1 deletion tests/ui/static/static-reference-to-fn-1.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ LL | func: &foo,
= note: expected reference `&fn() -> Option<isize>`
found reference `&fn() -> Option<isize> {foo}`
= note: fn items are distinct from fn pointers
= note: when the arguments and return types match, functions can be coerced to function pointers
help: consider casting to a fn pointer
|
LL | func: &(foo as fn() -> Option<isize>),
Expand Down
11 changes: 11 additions & 0 deletions tests/ui/unsafe/initializing-ranged-via-ctor.rs
Original file line number Diff line number Diff line change
@@ -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}`
}
16 changes: 16 additions & 0 deletions tests/ui/unsafe/initializing-ranged-via-ctor.stderr
Original file line number Diff line number Diff line change
@@ -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`.
10 changes: 10 additions & 0 deletions tests/ui/unsafe/ranged-ctor-as-fn-ptr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#![feature(rustc_attrs)]

#[derive(Debug)]
#[rustc_layout_scalar_valid_range_start(2)]
struct NonZeroAndOneU8(u8);

fn main() {
let x: fn(u8) -> NonZeroAndOneU8 = NonZeroAndOneU8;
//~^ ERROR mismatched types
}
15 changes: 15 additions & 0 deletions tests/ui/unsafe/ranged-ctor-as-fn-ptr.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error[E0308]: mismatched types
--> $DIR/ranged-ctor-as-fn-ptr.rs:8:40
|
LL | let x: fn(u8) -> NonZeroAndOneU8 = NonZeroAndOneU8;
| ------------------------- ^^^^^^^^^^^^^^^ expected normal fn, found unsafe fn
| |
| expected due to this
|
= note: expected fn pointer `fn(_) -> NonZeroAndOneU8`
found struct constructor `unsafe fn(_) -> NonZeroAndOneU8 {NonZeroAndOneU8}`
= note: unsafe functions cannot be coerced into safe function pointers

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.