Skip to content

Commit af62adf

Browse files
committed
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
2 parents f9cea4b + e538c95 commit af62adf

File tree

3 files changed

+38
-2
lines changed

3 files changed

+38
-2
lines changed

src/librustc/middle/ty.rs

+7
Original file line numberDiff line numberDiff line change
@@ -2423,6 +2423,13 @@ pub fn type_is_char(ty: t) -> bool {
24232423
}
24242424
}
24252425

2426+
pub fn type_is_bare_fn(ty: t) -> bool {
2427+
match get(ty).sty {
2428+
ty_bare_fn(*) => true,
2429+
_ => false
2430+
}
2431+
}
2432+
24262433
pub fn type_is_fp(ty: t) -> bool {
24272434
match get(ty).sty {
24282435
ty_infer(FloatVar(_)) | ty_float(_) => true,

src/librustc/middle/typeck/check/mod.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -3022,10 +3022,13 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
30223022

30233023
let t1 = structurally_resolved_type(fcx, e.span, t_1);
30243024
let te = structurally_resolved_type(fcx, e.span, t_e);
3025+
let t_1_is_scalar = type_is_scalar(fcx, expr.span, t_1);
30253026
let t_1_is_char = type_is_char(fcx, expr.span, t_1);
3027+
let t_1_is_bare_fn = type_is_bare_fn(fcx, expr.span, t_1);
30263028

3027-
// casts to scalars other than `char` are allowed
3028-
let t_1_is_trivial = type_is_scalar(fcx, expr.span, t_1) && !t_1_is_char;
3029+
// casts to scalars other than `char` and `bare fn` are trivial
3030+
let t_1_is_trivial = t_1_is_scalar &&
3031+
!t_1_is_char && !t_1_is_bare_fn;
30293032

30303033
if type_is_c_like_enum(fcx, expr.span, t_e) && t_1_is_trivial {
30313034
// 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 {
38253828
return ty::type_is_char(typ_s);
38263829
}
38273830

3831+
pub fn type_is_bare_fn(fcx: @mut FnCtxt, sp: Span, typ: ty::t) -> bool {
3832+
let typ_s = structurally_resolved_type(fcx, sp, typ);
3833+
return ty::type_is_bare_fn(typ_s);
3834+
}
3835+
38283836
pub fn type_is_unsafe_ptr(fcx: @mut FnCtxt, sp: Span, typ: ty::t) -> bool {
38293837
let typ_s = structurally_resolved_type(fcx, sp, typ);
38303838
return ty::type_is_unsafe_ptr(typ_s);
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn foo(_x: int) { }
12+
13+
#[fixed_stack_segment]
14+
fn main() {
15+
let v: u64 = 5;
16+
let x = foo as extern "C" fn() -> int;
17+
//~^ ERROR non-scalar cast
18+
let y = v as extern "Rust" fn(int) -> (int, int);
19+
//~^ ERROR non-scalar cast
20+
y(x());
21+
}

0 commit comments

Comments
 (0)