Typeck: Disallow scalar casts to bare_fn.
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:
parent
11d5670647
commit
e538c95e4d
3 changed files with 38 additions and 2 deletions
|
|
@ -2539,6 +2539,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,
|
||||
|
|
|
|||
|
|
@ -2687,10 +2687,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
|
||||
|
|
@ -3448,6 +3451,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…
Add table
Add a link
Reference in a new issue