Skip to content

Commit f460995

Browse files
committed
Make ty_bare_fn carry an optional def-id indicating whether it is the
type of a fn item or a fn pointer, which are now differentiated. Introduce coercion from fn item to fn pointer.
1 parent 8c8cb99 commit f460995

File tree

22 files changed

+161
-114
lines changed

22 files changed

+161
-114
lines changed

src/librustc/middle/check_const.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,11 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) -> bool {
127127
ast::ExprCast(ref from, _) => {
128128
let toty = ty::expr_ty(v.tcx, e);
129129
let fromty = ty::expr_ty(v.tcx, &**from);
130-
if !ty::type_is_numeric(toty) && !ty::type_is_unsafe_ptr(toty) {
130+
let is_legal_cast =
131+
ty::type_is_numeric(toty) ||
132+
ty::type_is_unsafe_ptr(toty) ||
133+
(ty::type_is_bare_fn(toty) && ty::type_is_bare_fn_item(fromty));
134+
if !is_legal_cast {
131135
span_err!(v.tcx.sess, e.span, E0012,
132136
"can not cast to `{}` in a constant expression",
133137
ppaux::ty_to_string(v.tcx, toty));

src/librustc/middle/expr_use_visitor.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -824,10 +824,12 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
824824
None => { }
825825
Some(adjustment) => {
826826
match *adjustment {
827-
ty::AdjustAddEnv(..) => {
828-
// Creating a closure consumes the input and stores it
829-
// into the resulting rvalue.
830-
debug!("walk_adjustment(AutoAddEnv)");
827+
ty::AdjustAddEnv(..) |
828+
ty::AdjustReifyFnPointer(..) => {
829+
// Creating a closure/fn-pointer consumes the
830+
// input and stores it into the resulting
831+
// rvalue.
832+
debug!("walk_adjustment(AutoAddEnv|AdjustReifyFnPointer)");
831833
let cmt_unadjusted =
832834
return_if_err!(self.mc.cat_expr_unadjusted(expr));
833835
self.delegate_consume(expr.id, expr.span, cmt_unadjusted);

src/librustc/middle/infer/coercion.rs

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -486,41 +486,55 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
486486
b.repr(self.tcx()));
487487

488488
match a.sty {
489-
ty::ty_bare_fn(ref f) => {
490-
self.coerce_from_bare_fn(a, f, b)
489+
ty::ty_bare_fn(Some(a_def_id), ref f) => {
490+
self.coerce_from_fn_item(a, a_def_id, f, b)
491491
}
492492
_ => {
493493
self.subtype(a, b)
494494
}
495495
}
496496
}
497497

498-
/// Attempts to coerce from a bare Rust function (`extern "Rust" fn`) into a closure or a
499-
/// `proc`.
500-
fn coerce_from_bare_fn(&self, a: Ty<'tcx>, fn_ty_a: &ty::BareFnTy<'tcx>, b: Ty<'tcx>)
498+
fn coerce_from_fn_item(&self,
499+
a: Ty<'tcx>,
500+
fn_def_id_a: ast::DefId,
501+
fn_ty_a: &ty::BareFnTy<'tcx>,
502+
b: Ty<'tcx>)
501503
-> CoerceResult<'tcx> {
502-
self.unpack_actual_value(b, |b| {
504+
/*!
505+
* Attempts to coerce from the type of a Rust function item
506+
* into a closure or a `proc`.
507+
*/
503508

509+
self.unpack_actual_value(b, |b| {
504510
debug!("coerce_from_bare_fn(a={}, b={})",
505-
a.repr(self.get_ref().infcx.tcx), b.repr(self.get_ref().infcx.tcx));
511+
a.repr(self.tcx()), b.repr(self.tcx()));
506512

507-
if fn_ty_a.abi != abi::Rust || fn_ty_a.unsafety != ast::Unsafety::Normal {
508-
return self.subtype(a, b);
509-
}
513+
match b.sty {
514+
ty::ty_closure(ref f) => {
515+
if fn_ty_a.abi != abi::Rust || fn_ty_a.unsafety != ast::Unsafety::Normal {
516+
return self.subtype(a, b);
517+
}
510518

511-
let fn_ty_b = match b.sty {
512-
ty::ty_closure(ref f) => (*f).clone(),
513-
_ => return self.subtype(a, b)
514-
};
515-
516-
let adj = ty::AdjustAddEnv(fn_ty_b.store);
517-
let a_closure = ty::mk_closure(self.get_ref().infcx.tcx,
518-
ty::ClosureTy {
519-
sig: fn_ty_a.sig.clone(),
520-
.. *fn_ty_b
521-
});
522-
try!(self.subtype(a_closure, b));
523-
Ok(Some(adj))
519+
let fn_ty_b = (*f).clone();
520+
let adj = ty::AdjustAddEnv(fn_def_id_a, fn_ty_b.store);
521+
let a_closure = ty::mk_closure(self.tcx(),
522+
ty::ClosureTy {
523+
sig: fn_ty_a.sig.clone(),
524+
.. *fn_ty_b
525+
});
526+
try!(self.subtype(a_closure, b));
527+
Ok(Some(adj))
528+
}
529+
ty::ty_bare_fn(None, _) => {
530+
let a_fn_pointer = ty::mk_bare_fn(self.tcx(), None, (*fn_ty_a).clone());
531+
try!(self.subtype(a_fn_pointer, b));
532+
Ok(Some(ty::AdjustReifyFnPointer(fn_def_id_a)))
533+
}
534+
_ => {
535+
return self.subtype(a, b)
536+
}
537+
}
524538
})
525539
}
526540

src/librustc/middle/infer/combine.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -568,11 +568,12 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C,
568568
}
569569
}
570570

571-
(&ty::ty_bare_fn(ref a_fty), &ty::ty_bare_fn(ref b_fty)) => {
572-
this.bare_fn_tys(a_fty, b_fty).and_then(|fty| {
573-
Ok(ty::mk_bare_fn(tcx, fty))
574-
})
575-
}
571+
(&ty::ty_bare_fn(a_opt_def_id, ref a_fty), &ty::ty_bare_fn(b_opt_def_id, ref b_fty))
572+
if a_opt_def_id == b_opt_def_id =>
573+
{
574+
let fty = try!(this.bare_fn_tys(a_fty, b_fty));
575+
Ok(ty::mk_bare_fn(tcx, a_opt_def_id, fty))
576+
}
576577

577578
(&ty::ty_closure(ref a_fty), &ty::ty_closure(ref b_fty)) => {
578579
this.closure_tys(&**a_fty, &**b_fty).and_then(|fty| {

src/librustc/middle/mem_categorization.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -441,8 +441,8 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
441441

442442
Some(adjustment) => {
443443
match *adjustment {
444-
ty::AdjustAddEnv(..) => {
445-
debug!("cat_expr(AdjustAddEnv): {}",
444+
ty::AdjustAddEnv(..) | ty::AdjustReifyFnPointer(..) => {
445+
debug!("cat_expr(AdjustAddEnv|AdjustReifyFnPointer): {}",
446446
expr.repr(self.tcx()));
447447
// Convert a bare fn to a closure by adding NULL env.
448448
// Result is an rvalue.

src/librustc/middle/ty.rs

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,8 @@ pub enum Variance {
293293

294294
#[deriving(Clone, Show)]
295295
pub enum AutoAdjustment<'tcx> {
296-
AdjustAddEnv(ty::TraitStore),
296+
AdjustAddEnv(ast::DefId, ty::TraitStore),
297+
AdjustReifyFnPointer(ast::DefId), // go from a fn-item type to a fn-pointer type
297298
AdjustDerefRef(AutoDerefRef<'tcx>)
298299
}
299300

@@ -1243,11 +1244,17 @@ pub enum sty<'tcx> {
12431244
ty_vec(Ty<'tcx>, Option<uint>), // Second field is length.
12441245
ty_ptr(mt<'tcx>),
12451246
ty_rptr(Region, mt<'tcx>),
1246-
ty_bare_fn(BareFnTy<'tcx>),
1247+
1248+
// If the def-id is Some(_), then this is the type of a specific
1249+
// fn item. Otherwise, if None(_), it a fn pointer type.
1250+
ty_bare_fn(Option<DefId>, BareFnTy<'tcx>),
1251+
12471252
ty_closure(Box<ClosureTy<'tcx>>),
12481253
ty_trait(Box<TyTrait<'tcx>>),
12491254
ty_struct(DefId, Substs<'tcx>),
1255+
12501256
ty_unboxed_closure(DefId, Region, Substs<'tcx>),
1257+
12511258
ty_tup(Vec<Ty<'tcx>>),
12521259

12531260
ty_param(ParamTy), // type parameter
@@ -2339,15 +2346,19 @@ pub fn mk_closure<'tcx>(cx: &ctxt<'tcx>, fty: ClosureTy<'tcx>) -> Ty<'tcx> {
23392346
mk_t(cx, ty_closure(box fty))
23402347
}
23412348

2342-
pub fn mk_bare_fn<'tcx>(cx: &ctxt<'tcx>, fty: BareFnTy<'tcx>) -> Ty<'tcx> {
2343-
mk_t(cx, ty_bare_fn(fty))
2349+
pub fn mk_bare_fn<'tcx>(cx: &ctxt<'tcx>,
2350+
opt_def_id: Option<ast::DefId>,
2351+
fty: BareFnTy<'tcx>) -> Ty<'tcx> {
2352+
mk_t(cx, ty_bare_fn(opt_def_id, fty))
23442353
}
23452354

23462355
pub fn mk_ctor_fn<'tcx>(cx: &ctxt<'tcx>,
2356+
def_id: ast::DefId,
23472357
input_tys: &[Ty<'tcx>],
23482358
output: Ty<'tcx>) -> Ty<'tcx> {
23492359
let input_args = input_tys.iter().map(|ty| *ty).collect();
23502360
mk_bare_fn(cx,
2361+
Some(def_id),
23512362
BareFnTy {
23522363
unsafety: ast::Unsafety::Normal,
23532364
abi: abi::Rust,
@@ -3560,6 +3571,13 @@ pub fn type_is_bare_fn(ty: Ty) -> bool {
35603571
}
35613572
}
35623573

3574+
pub fn type_is_bare_fn_item(ty: Ty) -> bool {
3575+
match ty.sty {
3576+
ty_bare_fn(Some(_), _) => true,
3577+
_ => false
3578+
}
3579+
}
3580+
35633581
pub fn type_is_fp(ty: Ty) -> bool {
35643582
match ty.sty {
35653583
ty_infer(FloatVar(_)) | ty_float(_) => true,
@@ -3975,9 +3993,9 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>,
39753993
return match adjustment {
39763994
Some(adjustment) => {
39773995
match *adjustment {
3978-
AdjustAddEnv(store) => {
3996+
AdjustAddEnv(_, store) => {
39793997
match unadjusted_ty.sty {
3980-
ty::ty_bare_fn(ref b) => {
3998+
ty::ty_bare_fn(Some(_), ref b) => {
39813999
let bounds = ty::ExistentialBounds {
39824000
region_bound: ReStatic,
39834001
builtin_bounds: all_builtin_bounds(),
@@ -3994,7 +4012,21 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>,
39944012
}
39954013
ref b => {
39964014
cx.sess.bug(
3997-
format!("add_env adjustment on non-bare-fn: \
4015+
format!("add_env adjustment on non-fn-item: \
4016+
{}",
4017+
b).as_slice());
4018+
}
4019+
}
4020+
}
4021+
4022+
AdjustReifyFnPointer(_) => {
4023+
match unadjusted_ty.sty {
4024+
ty::ty_bare_fn(Some(_), ref b) => {
4025+
ty::mk_bare_fn(cx, None, (*b).clone())
4026+
}
4027+
ref b => {
4028+
cx.sess.bug(
4029+
format!("AdjustReifyFnPointer adjustment on non-fn-item: \
39984030
{}",
39994031
b).as_slice());
40004032
}
@@ -4353,7 +4385,8 @@ pub fn ty_sort_string<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> String {
43534385
ty_vec(_, None) => "slice".to_string(),
43544386
ty_ptr(_) => "*-ptr".to_string(),
43554387
ty_rptr(_, _) => "&-ptr".to_string(),
4356-
ty_bare_fn(_) => "extern fn".to_string(),
4388+
ty_bare_fn(Some(_), _) => format!("fn item"),
4389+
ty_bare_fn(None, _) => "fn pointer".to_string(),
43574390
ty_closure(_) => "fn".to_string(),
43584391
ty_trait(ref inner) => {
43594392
format!("trait {}", item_path_str(cx, inner.principal.def_id()))
@@ -5884,8 +5917,9 @@ pub fn hash_crate_independent<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh) -
58845917
region(state, r);
58855918
mt(state, m);
58865919
}
5887-
ty_bare_fn(ref b) => {
5920+
ty_bare_fn(opt_def_id, ref b) => {
58885921
byte!(14);
5922+
hash!(opt_def_id);
58895923
hash!(b.unsafety);
58905924
hash!(b.abi);
58915925
fn_sig(state, &b.sig);
@@ -6252,6 +6286,7 @@ impl<'tcx> AutoAdjustment<'tcx> {
62526286
pub fn is_identity(&self) -> bool {
62536287
match *self {
62546288
AdjustAddEnv(..) => false,
6289+
AdjustReifyFnPointer(..) => false,
62556290
AdjustDerefRef(ref r) => r.is_identity(),
62566291
}
62576292
}
@@ -6367,8 +6402,11 @@ impl DebruijnIndex {
63676402
impl<'tcx> Repr<'tcx> for AutoAdjustment<'tcx> {
63686403
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
63696404
match *self {
6370-
AdjustAddEnv(ref trait_store) => {
6371-
format!("AdjustAddEnv({})", trait_store)
6405+
AdjustAddEnv(def_id, ref trait_store) => {
6406+
format!("AdjustAddEnv({},{})", def_id.repr(tcx), trait_store)
6407+
}
6408+
AdjustReifyFnPointer(def_id) => {
6409+
format!("AdjustAddEnv({})", def_id.repr(tcx))
63726410
}
63736411
AdjustDerefRef(ref data) => {
63746412
data.repr(tcx)

src/librustc/middle/ty_fold.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -538,8 +538,8 @@ pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
538538
ty::ty_tup(ref ts) => {
539539
ty::ty_tup(ts.fold_with(this))
540540
}
541-
ty::ty_bare_fn(ref f) => {
542-
ty::ty_bare_fn(f.fold_with(this))
541+
ty::ty_bare_fn(opt_def_id, ref f) => {
542+
ty::ty_bare_fn(opt_def_id, f.fold_with(this))
543543
}
544544
ty::ty_closure(ref f) => {
545545
ty::ty_closure(box f.fold_with(this))

src/librustc_trans/trans/base.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,7 @@ pub fn get_res_dtor<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
542542
let class_ty = ty::lookup_item_type(tcx, parent_id).ty.subst(tcx, substs);
543543
let llty = type_of_dtor(ccx, class_ty);
544544
let dtor_ty = ty::mk_ctor_fn(ccx.tcx(),
545+
did,
545546
&[glue::get_drop_glue_type(ccx, t)],
546547
ty::mk_nil(ccx.tcx()));
547548
get_extern_fn(ccx,

src/librustc_trans/trans/callee.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,9 @@ pub use self::AutorefArg::*;
1818
pub use self::CalleeData::*;
1919
pub use self::CallArgs::*;
2020

21-
use arena::TypedArena;
22-
use back::{abi,link};
21+
use back::abi;
2322
use session;
24-
use llvm::{ValueRef, get_param};
23+
use llvm::{ValueRef};
2524
use llvm;
2625
use metadata::csearch;
2726
use middle::def;

src/librustc_trans/trans/closure.rs

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ pub use self::ClosureKind::*;
1313
use back::abi;
1414
use back::link::mangle_internal_name_by_path_and_seq;
1515
use llvm::ValueRef;
16-
use middle::def;
1716
use middle::mem_categorization::Typer;
1817
use trans::adt;
1918
use trans::base::*;
@@ -603,21 +602,10 @@ pub fn trans_unboxed_closure<'blk, 'tcx>(
603602

604603
pub fn get_wrapper_for_bare_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
605604
closure_ty: Ty<'tcx>,
606-
def: def::Def,
605+
def_id: ast::DefId,
607606
fn_ptr: ValueRef,
608-
is_local: bool) -> ValueRef {
609-
610-
let def_id = match def {
611-
def::DefFn(did, _) | def::DefStaticMethod(did, _) |
612-
def::DefVariant(_, did, _) | def::DefStruct(did) => did,
613-
_ => {
614-
ccx.sess().bug(format!("get_wrapper_for_bare_fn: \
615-
expected a statically resolved fn, got \
616-
{}",
617-
def).as_slice());
618-
}
619-
};
620-
607+
is_local: bool) -> ValueRef
608+
{
621609
match ccx.closure_bare_wrapper_cache().borrow().get(&fn_ptr) {
622610
Some(&llval) => return llval,
623611
None => {}
@@ -697,11 +685,11 @@ pub fn get_wrapper_for_bare_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
697685

698686
pub fn make_closure_from_bare_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
699687
closure_ty: Ty<'tcx>,
700-
def: def::Def,
688+
def_id: ast::DefId,
701689
fn_ptr: ValueRef)
702690
-> DatumBlock<'blk, 'tcx, Expr> {
703691
let scratch = rvalue_scratch_datum(bcx, closure_ty, "__adjust");
704-
let wrapper = get_wrapper_for_bare_fn(bcx.ccx(), closure_ty, def, fn_ptr, true);
692+
let wrapper = get_wrapper_for_bare_fn(bcx.ccx(), closure_ty, def_id, fn_ptr, true);
705693
fill_fn_pair(bcx, scratch.val, wrapper, C_null(Type::i8p(bcx.ccx())));
706694

707695
DatumBlock::new(bcx, scratch.to_expr_datum())

src/librustc_trans/trans/consts.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -190,16 +190,15 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, e: &ast::Expr)
190190
None => { }
191191
Some(adj) => {
192192
match adj {
193-
ty::AdjustAddEnv(ty::RegionTraitStore(ty::ReStatic, _)) => {
194-
let def = ty::resolve_expr(cx.tcx(), e);
193+
ty::AdjustAddEnv(def_id, ty::RegionTraitStore(ty::ReStatic, _)) => {
195194
let wrapper = closure::get_wrapper_for_bare_fn(cx,
196195
ety_adjusted,
197-
def,
196+
def_id,
198197
llconst,
199198
true);
200199
llconst = C_struct(cx, &[wrapper, C_null(Type::i8p(cx))], false)
201200
}
202-
ty::AdjustAddEnv(store) => {
201+
ty::AdjustAddEnv(_, store) => {
203202
cx.sess()
204203
.span_bug(e.span,
205204
format!("unexpected static function: {}",

0 commit comments

Comments
 (0)