auto merge of #6309 : nikomatsakis/rust/issue-3678-type-of-extern-fns, r=nikomatsakis
Lift restriction on calling extern C functions, and propagate the ABI as part of the type of an extern fn. cc #3678
This commit is contained in:
commit
1d7a136145
@ -1311,19 +1311,6 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
|
|||||||
// Extract the function signature from `in_fty`.
|
// Extract the function signature from `in_fty`.
|
||||||
let fn_sty = structure_of(fcx, f.span, fn_ty);
|
let fn_sty = structure_of(fcx, f.span, fn_ty);
|
||||||
|
|
||||||
// FIXME(#3678) For now, do not permit calls to C abi functions.
|
|
||||||
match fn_sty {
|
|
||||||
ty::ty_bare_fn(ty::BareFnTy {abis, _}) => {
|
|
||||||
if !abis.is_rust() {
|
|
||||||
fcx.tcx().sess.span_err(
|
|
||||||
call_expr.span,
|
|
||||||
fmt!("Calls to C ABI functions are not (yet) \
|
|
||||||
supported; be patient, dear user"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
let fn_sig = match fn_sty {
|
let fn_sig = match fn_sty {
|
||||||
ty::ty_bare_fn(ty::BareFnTy {sig: sig, _}) |
|
ty::ty_bare_fn(ty::BareFnTy {sig: sig, _}) |
|
||||||
ty::ty_closure(ty::ClosureTy {sig: sig, _}) => sig,
|
ty::ty_closure(ty::ClosureTy {sig: sig, _}) => sig,
|
||||||
@ -3607,7 +3594,7 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
|
|||||||
};
|
};
|
||||||
let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
|
let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
|
||||||
purity: ast::unsafe_fn,
|
purity: ast::unsafe_fn,
|
||||||
abis: AbiSet::Rust(),
|
abis: AbiSet::Intrinsic(),
|
||||||
sig: FnSig {bound_lifetime_names: opt_vec::Empty,
|
sig: FnSig {bound_lifetime_names: opt_vec::Empty,
|
||||||
inputs: inputs,
|
inputs: inputs,
|
||||||
output: output}
|
output: output}
|
||||||
|
@ -134,8 +134,8 @@ impl AstConv for CrateCtxt {
|
|||||||
Some(&ast_map::node_item(item, _)) => {
|
Some(&ast_map::node_item(item, _)) => {
|
||||||
ty_of_item(self, item)
|
ty_of_item(self, item)
|
||||||
}
|
}
|
||||||
Some(&ast_map::node_foreign_item(foreign_item, _, _, _)) => {
|
Some(&ast_map::node_foreign_item(foreign_item, abis, _, _)) => {
|
||||||
ty_of_foreign_item(self, foreign_item)
|
ty_of_foreign_item(self, foreign_item, abis)
|
||||||
}
|
}
|
||||||
ref x => {
|
ref x => {
|
||||||
self.tcx.sess.bug(fmt!("unexpected sort of item \
|
self.tcx.sess.bug(fmt!("unexpected sort of item \
|
||||||
@ -932,7 +932,20 @@ pub fn convert_foreign(ccx: &CrateCtxt, i: @ast::foreign_item) {
|
|||||||
// As above, this call populates the type table with the converted
|
// As above, this call populates the type table with the converted
|
||||||
// type of the foreign item. We simply write it into the node type
|
// type of the foreign item. We simply write it into the node type
|
||||||
// table.
|
// table.
|
||||||
let tpt = ty_of_foreign_item(ccx, i);
|
|
||||||
|
// For reasons I cannot fully articulate, I do so hate the AST
|
||||||
|
// map, and I regard each time that I use it as a personal and
|
||||||
|
// moral failing, but at the moment it seems like the only
|
||||||
|
// convenient way to extract the ABI. - ndm
|
||||||
|
let abis = match ccx.tcx.items.find(&i.id) {
|
||||||
|
Some(&ast_map::node_foreign_item(_, abis, _, _)) => abis,
|
||||||
|
ref x => {
|
||||||
|
ccx.tcx.sess.bug(fmt!("unexpected sort of item \
|
||||||
|
in get_item_ty(): %?", (*x)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let tpt = ty_of_foreign_item(ccx, i, abis);
|
||||||
write_ty_to_tcx(ccx.tcx, i.id, tpt.ty);
|
write_ty_to_tcx(ccx.tcx, i.id, tpt.ty);
|
||||||
ccx.tcx.tcache.insert(local_def(i.id), tpt);
|
ccx.tcx.tcache.insert(local_def(i.id), tpt);
|
||||||
}
|
}
|
||||||
@ -1103,14 +1116,17 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ty_of_foreign_item(ccx: &CrateCtxt, it: @ast::foreign_item)
|
pub fn ty_of_foreign_item(ccx: &CrateCtxt,
|
||||||
-> ty::ty_param_bounds_and_ty {
|
it: @ast::foreign_item,
|
||||||
|
abis: AbiSet) -> ty::ty_param_bounds_and_ty
|
||||||
|
{
|
||||||
match it.node {
|
match it.node {
|
||||||
ast::foreign_item_fn(ref fn_decl, _, ref generics) => {
|
ast::foreign_item_fn(ref fn_decl, _, ref generics) => {
|
||||||
ty_of_foreign_fn_decl(ccx,
|
ty_of_foreign_fn_decl(ccx,
|
||||||
fn_decl,
|
fn_decl,
|
||||||
local_def(it.id),
|
local_def(it.id),
|
||||||
generics)
|
generics,
|
||||||
|
abis)
|
||||||
}
|
}
|
||||||
ast::foreign_item_const(t) => {
|
ast::foreign_item_const(t) => {
|
||||||
ty::ty_param_bounds_and_ty {
|
ty::ty_param_bounds_and_ty {
|
||||||
@ -1197,7 +1213,8 @@ pub fn ty_generics(ccx: &CrateCtxt,
|
|||||||
pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
|
pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
|
||||||
decl: &ast::fn_decl,
|
decl: &ast::fn_decl,
|
||||||
def_id: ast::def_id,
|
def_id: ast::def_id,
|
||||||
ast_generics: &ast::Generics)
|
ast_generics: &ast::Generics,
|
||||||
|
abis: AbiSet)
|
||||||
-> ty::ty_param_bounds_and_ty {
|
-> ty::ty_param_bounds_and_ty {
|
||||||
let ty_generics = ty_generics(ccx, None, ast_generics, 0);
|
let ty_generics = ty_generics(ccx, None, ast_generics, 0);
|
||||||
let region_param_names = RegionParamNames::from_generics(ast_generics);
|
let region_param_names = RegionParamNames::from_generics(ast_generics);
|
||||||
@ -1208,7 +1225,7 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
|
|||||||
let t_fn = ty::mk_bare_fn(
|
let t_fn = ty::mk_bare_fn(
|
||||||
ccx.tcx,
|
ccx.tcx,
|
||||||
ty::BareFnTy {
|
ty::BareFnTy {
|
||||||
abis: AbiSet::Rust(),
|
abis: abis,
|
||||||
purity: ast::unsafe_fn,
|
purity: ast::unsafe_fn,
|
||||||
sig: ty::FnSig {bound_lifetime_names: opt_vec::Empty,
|
sig: ty::FnSig {bound_lifetime_names: opt_vec::Empty,
|
||||||
inputs: input_tys,
|
inputs: input_tys,
|
||||||
|
Loading…
Reference in New Issue
Block a user