auto merge of #9788 : geoffhill/rust/bare-fn-cast, r=pnkfelix
Bare functions are another example of a scalar but non-numeric type (like char) that should be handled separately in casts. This disallows expressions like `0 as extern "Rust" fn() -> int;`. It might be advantageous to allow casts between bare functions and raw pointers in unsafe code in the future, to pass function pointers between Rust and C. Closes #8728
This commit is contained in:
commit
af62adfad0
@ -2423,6 +2423,13 @@ pub fn type_is_char(ty: t) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_is_bare_fn(ty: t) -> bool {
|
||||
match get(ty).sty {
|
||||
ty_bare_fn(*) => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_is_fp(ty: t) -> bool {
|
||||
match get(ty).sty {
|
||||
ty_infer(FloatVar(_)) | ty_float(_) => true,
|
||||
|
@ -3022,10 +3022,13 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
|
||||
|
||||
let t1 = structurally_resolved_type(fcx, e.span, t_1);
|
||||
let te = structurally_resolved_type(fcx, e.span, t_e);
|
||||
let t_1_is_scalar = type_is_scalar(fcx, expr.span, t_1);
|
||||
let t_1_is_char = type_is_char(fcx, expr.span, t_1);
|
||||
let t_1_is_bare_fn = type_is_bare_fn(fcx, expr.span, t_1);
|
||||
|
||||
// casts to scalars other than `char` are allowed
|
||||
let t_1_is_trivial = type_is_scalar(fcx, expr.span, t_1) && !t_1_is_char;
|
||||
// casts to scalars other than `char` and `bare fn` are trivial
|
||||
let t_1_is_trivial = t_1_is_scalar &&
|
||||
!t_1_is_char && !t_1_is_bare_fn;
|
||||
|
||||
if type_is_c_like_enum(fcx, expr.span, t_e) && t_1_is_trivial {
|
||||
// casts from C-like enums are allowed
|
||||
@ -3825,6 +3828,11 @@ pub fn type_is_char(fcx: @mut FnCtxt, sp: Span, typ: ty::t) -> bool {
|
||||
return ty::type_is_char(typ_s);
|
||||
}
|
||||
|
||||
pub fn type_is_bare_fn(fcx: @mut FnCtxt, sp: Span, typ: ty::t) -> bool {
|
||||
let typ_s = structurally_resolved_type(fcx, sp, typ);
|
||||
return ty::type_is_bare_fn(typ_s);
|
||||
}
|
||||
|
||||
pub fn type_is_unsafe_ptr(fcx: @mut FnCtxt, sp: Span, typ: ty::t) -> bool {
|
||||
let typ_s = structurally_resolved_type(fcx, sp, typ);
|
||||
return ty::type_is_unsafe_ptr(typ_s);
|
||||
|
21
src/test/compile-fail/cast-to-bare-fn.rs
Normal file
21
src/test/compile-fail/cast-to-bare-fn.rs
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn foo(_x: int) { }
|
||||
|
||||
#[fixed_stack_segment]
|
||||
fn main() {
|
||||
let v: u64 = 5;
|
||||
let x = foo as extern "C" fn() -> int;
|
||||
//~^ ERROR non-scalar cast
|
||||
let y = v as extern "Rust" fn(int) -> (int, int);
|
||||
//~^ ERROR non-scalar cast
|
||||
y(x());
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user