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:
Geoff Hill 2013-10-09 15:36:26 -07:00
parent 11d5670647
commit e538c95e4d
3 changed files with 38 additions and 2 deletions

View file

@ -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,

View file

@ -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);

View 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());
}