Skip to content

Commit 6c0950d

Browse files
authored
Rollup merge of #64104 - Mark-Simulacrum:intrinsic-fn-ptr-ice, r=estebank
Emit error on intrinsic to fn ptr casts I'm not sure if a type error is the best way of doing this but it seemed like a relatively correct place to do it, and I expect this is a pretty rare case to hit anyway. Fixes #15694
2 parents 7bfbaca + dd323f8 commit 6c0950d

File tree

7 files changed

+57
-0
lines changed

7 files changed

+57
-0
lines changed

Diff for: src/librustc/infer/error_reporting/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1636,6 +1636,9 @@ impl<'tcx> ObligationCause<'tcx> {
16361636
TypeError::CyclicTy(ty) if ty.is_closure() || ty.is_generator() => {
16371637
Error0644("closure/generator type that references itself")
16381638
}
1639+
TypeError::IntrinsicCast => {
1640+
Error0308("cannot coerce intrinsics to function pointers")
1641+
}
16391642
_ => Error0308("mismatched types"),
16401643
},
16411644
}

Diff for: src/librustc/ty/error.rs

+5
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ pub enum TypeError<'tcx> {
4646
ExistentialMismatch(ExpectedFound<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>),
4747

4848
ConstMismatch(ExpectedFound<&'tcx ty::Const<'tcx>>),
49+
50+
IntrinsicCast,
4951
}
5052

5153
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
@@ -179,6 +181,9 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
179181
ConstMismatch(ref values) => {
180182
write!(f, "expected `{}`, found `{}`", values.expected, values.found)
181183
}
184+
IntrinsicCast => {
185+
write!(f, "cannot coerce intrinsics to function pointers")
186+
}
182187
}
183188
}
184189
}

Diff for: src/librustc/ty/structural_impls.rs

+2
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> {
748748
Sorts(ref x) => return tcx.lift(x).map(Sorts),
749749
ExistentialMismatch(ref x) => return tcx.lift(x).map(ExistentialMismatch),
750750
ConstMismatch(ref x) => return tcx.lift(x).map(ConstMismatch),
751+
IntrinsicCast => IntrinsicCast,
751752
})
752753
}
753754
}
@@ -1338,6 +1339,7 @@ EnumTypeFoldableImpl! {
13381339
(ty::error::TypeError::Sorts)(x),
13391340
(ty::error::TypeError::ExistentialMismatch)(x),
13401341
(ty::error::TypeError::ConstMismatch)(x),
1342+
(ty::error::TypeError::IntrinsicCast),
13411343
}
13421344
}
13431345

Diff for: src/librustc_typeck/check/cast.rs

+4
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ use rustc::ty::{self, Ty, TypeFoldable, TypeAndMut};
4040
use rustc::ty::subst::SubstsRef;
4141
use rustc::ty::adjustment::AllowTwoPhase;
4242
use rustc::ty::cast::{CastKind, CastTy};
43+
use rustc::ty::error::TypeError;
4344
use rustc::middle::lang_items;
4445
use syntax::ast;
4546
use syntax_pos::Span;
@@ -461,6 +462,9 @@ impl<'a, 'tcx> CastCheck<'tcx> {
461462
self.expr_ty,
462463
fcx.tcx.mk_fn_ptr(f),
463464
AllowTwoPhase::No);
465+
if let Err(TypeError::IntrinsicCast) = res {
466+
return Err(CastError::IllegalCast);
467+
}
464468
if res.is_err() {
465469
return Err(CastError::NonScalar);
466470
}

Diff for: src/librustc_typeck/check/coercion.rs

+6
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ use std::ops::Deref;
7070
use syntax::feature_gate;
7171
use syntax::symbol::sym;
7272
use syntax_pos;
73+
use rustc_target::spec::abi::Abi;
7374

7475
struct Coerce<'a, 'tcx> {
7576
fcx: &'a FnCtxt<'a, 'tcx>,
@@ -689,6 +690,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
689690
match b.sty {
690691
ty::FnPtr(_) => {
691692
let a_sig = a.fn_sig(self.tcx);
693+
// Intrinsics are not coercible to function pointers
694+
if a_sig.abi() == Abi::RustIntrinsic ||
695+
a_sig.abi() == Abi::PlatformIntrinsic {
696+
return Err(TypeError::IntrinsicCast);
697+
}
692698
let InferOk { value: a_sig, mut obligations } =
693699
self.normalize_associated_types_in_as_infer_ok(self.cause.span, &a_sig);
694700

Diff for: src/test/ui/reify-intrinsic.rs

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// check-fail
2+
3+
#![feature(intrinsics)]
4+
5+
fn a() {
6+
let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::transmute;
7+
//~^ ERROR cannot coerce
8+
}
9+
10+
fn b() {
11+
let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize) -> usize;
12+
//~^ ERROR casting
13+
}
14+
15+
fn main() {}

Diff for: src/test/ui/reify-intrinsic.stderr

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error[E0308]: cannot coerce intrinsics to function pointers
2+
--> $DIR/reify-intrinsic.rs:6:64
3+
|
4+
LL | let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::transmute;
5+
| ^^^^^^^^^^^^^^^^^^^
6+
| |
7+
| cannot coerce intrinsics to function pointers
8+
| help: use parentheses to call this function: `std::mem::transmute(...)`
9+
|
10+
= note: expected type `unsafe extern "rust-intrinsic" fn(isize) -> usize`
11+
found type `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}`
12+
13+
error[E0606]: casting `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}` as `unsafe extern "rust-intrinsic" fn(isize) -> usize` is invalid
14+
--> $DIR/reify-intrinsic.rs:11:13
15+
|
16+
LL | let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize) -> usize;
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
18+
19+
error: aborting due to 2 previous errors
20+
21+
Some errors have detailed explanations: E0308, E0606.
22+
For more information about an error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)