diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2014-11-26 06:36:09 -0500 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2014-12-22 12:27:07 -0500 |
| commit | f46099575a304ae9032f45c7921b496c4d220697 (patch) | |
| tree | 7631fb43337868e152aafb545493d482a8981994 | |
| parent | 8c8cb997a592f7348958e58c98117be03764d8b0 (diff) | |
| download | rust-f46099575a304ae9032f45c7921b496c4d220697.tar.gz rust-f46099575a304ae9032f45c7921b496c4d220697.zip | |
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.
22 files changed, 161 insertions, 114 deletions
diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index a91ea8bfef8..e08dd64d4d4 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -127,7 +127,11 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) -> bool { ast::ExprCast(ref from, _) => { let toty = ty::expr_ty(v.tcx, e); let fromty = ty::expr_ty(v.tcx, &**from); - if !ty::type_is_numeric(toty) && !ty::type_is_unsafe_ptr(toty) { + let is_legal_cast = + ty::type_is_numeric(toty) || + ty::type_is_unsafe_ptr(toty) || + (ty::type_is_bare_fn(toty) && ty::type_is_bare_fn_item(fromty)); + if !is_legal_cast { span_err!(v.tcx.sess, e.span, E0012, "can not cast to `{}` in a constant expression", ppaux::ty_to_string(v.tcx, toty)); diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index abc3c8d0d8f..046a2894b5d 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -824,10 +824,12 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> { None => { } Some(adjustment) => { match *adjustment { - ty::AdjustAddEnv(..) => { - // Creating a closure consumes the input and stores it - // into the resulting rvalue. - debug!("walk_adjustment(AutoAddEnv)"); + ty::AdjustAddEnv(..) | + ty::AdjustReifyFnPointer(..) => { + // Creating a closure/fn-pointer consumes the + // input and stores it into the resulting + // rvalue. + debug!("walk_adjustment(AutoAddEnv|AdjustReifyFnPointer)"); let cmt_unadjusted = return_if_err!(self.mc.cat_expr_unadjusted(expr)); self.delegate_consume(expr.id, expr.span, cmt_unadjusted); diff --git a/src/librustc/middle/infer/coercion.rs b/src/librustc/middle/infer/coercion.rs index ca9ac10341c..08336da0d8a 100644 --- a/src/librustc/middle/infer/coercion.rs +++ b/src/librustc/middle/infer/coercion.rs @@ -486,8 +486,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { b.repr(self.tcx())); match a.sty { - ty::ty_bare_fn(ref f) => { - self.coerce_from_bare_fn(a, f, b) + ty::ty_bare_fn(Some(a_def_id), ref f) => { + self.coerce_from_fn_item(a, a_def_id, f, b) } _ => { self.subtype(a, b) @@ -495,32 +495,46 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } } - /// Attempts to coerce from a bare Rust function (`extern "Rust" fn`) into a closure or a - /// `proc`. - fn coerce_from_bare_fn(&self, a: Ty<'tcx>, fn_ty_a: &ty::BareFnTy<'tcx>, b: Ty<'tcx>) + fn coerce_from_fn_item(&self, + a: Ty<'tcx>, + fn_def_id_a: ast::DefId, + fn_ty_a: &ty::BareFnTy<'tcx>, + b: Ty<'tcx>) -> CoerceResult<'tcx> { - self.unpack_actual_value(b, |b| { + /*! + * Attempts to coerce from the type of a Rust function item + * into a closure or a `proc`. + */ + self.unpack_actual_value(b, |b| { debug!("coerce_from_bare_fn(a={}, b={})", - a.repr(self.get_ref().infcx.tcx), b.repr(self.get_ref().infcx.tcx)); + a.repr(self.tcx()), b.repr(self.tcx())); - if fn_ty_a.abi != abi::Rust || fn_ty_a.unsafety != ast::Unsafety::Normal { - return self.subtype(a, b); - } + match b.sty { + ty::ty_closure(ref f) => { + if fn_ty_a.abi != abi::Rust || fn_ty_a.unsafety != ast::Unsafety::Normal { + return self.subtype(a, b); + } - let fn_ty_b = match b.sty { - ty::ty_closure(ref f) => (*f).clone(), - _ => return self.subtype(a, b) - }; - - let adj = ty::AdjustAddEnv(fn_ty_b.store); - let a_closure = ty::mk_closure(self.get_ref().infcx.tcx, - ty::ClosureTy { - sig: fn_ty_a.sig.clone(), - .. *fn_ty_b - }); - try!(self.subtype(a_closure, b)); - Ok(Some(adj)) + let fn_ty_b = (*f).clone(); + let adj = ty::AdjustAddEnv(fn_def_id_a, fn_ty_b.store); + let a_closure = ty::mk_closure(self.tcx(), + ty::ClosureTy { + sig: fn_ty_a.sig.clone(), + .. *fn_ty_b + }); + try!(self.subtype(a_closure, b)); + Ok(Some(adj)) + } + ty::ty_bare_fn(None, _) => { + let a_fn_pointer = ty::mk_bare_fn(self.tcx(), None, (*fn_ty_a).clone()); + try!(self.subtype(a_fn_pointer, b)); + Ok(Some(ty::AdjustReifyFnPointer(fn_def_id_a))) + } + _ => { + return self.subtype(a, b) + } + } }) } diff --git a/src/librustc/middle/infer/combine.rs b/src/librustc/middle/infer/combine.rs index 82ddbcee5a7..fc240faac44 100644 --- a/src/librustc/middle/infer/combine.rs +++ b/src/librustc/middle/infer/combine.rs @@ -568,11 +568,12 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C, } } - (&ty::ty_bare_fn(ref a_fty), &ty::ty_bare_fn(ref b_fty)) => { - this.bare_fn_tys(a_fty, b_fty).and_then(|fty| { - Ok(ty::mk_bare_fn(tcx, fty)) - }) - } + (&ty::ty_bare_fn(a_opt_def_id, ref a_fty), &ty::ty_bare_fn(b_opt_def_id, ref b_fty)) + if a_opt_def_id == b_opt_def_id => + { + let fty = try!(this.bare_fn_tys(a_fty, b_fty)); + Ok(ty::mk_bare_fn(tcx, a_opt_def_id, fty)) + } (&ty::ty_closure(ref a_fty), &ty::ty_closure(ref b_fty)) => { this.closure_tys(&**a_fty, &**b_fty).and_then(|fty| { diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index dce75579ca0..5aac988948f 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -441,8 +441,8 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { Some(adjustment) => { match *adjustment { - ty::AdjustAddEnv(..) => { - debug!("cat_expr(AdjustAddEnv): {}", + ty::AdjustAddEnv(..) | ty::AdjustReifyFnPointer(..) => { + debug!("cat_expr(AdjustAddEnv|AdjustReifyFnPointer): {}", expr.repr(self.tcx())); // Convert a bare fn to a closure by adding NULL env. // Result is an rvalue. diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 50a6fb9d0ca..4130d07aed0 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -293,7 +293,8 @@ pub enum Variance { #[deriving(Clone, Show)] pub enum AutoAdjustment<'tcx> { - AdjustAddEnv(ty::TraitStore), + AdjustAddEnv(ast::DefId, ty::TraitStore), + AdjustReifyFnPointer(ast::DefId), // go from a fn-item type to a fn-pointer type AdjustDerefRef(AutoDerefRef<'tcx>) } @@ -1243,11 +1244,17 @@ pub enum sty<'tcx> { ty_vec(Ty<'tcx>, Option<uint>), // Second field is length. ty_ptr(mt<'tcx>), ty_rptr(Region, mt<'tcx>), - ty_bare_fn(BareFnTy<'tcx>), + + // If the def-id is Some(_), then this is the type of a specific + // fn item. Otherwise, if None(_), it a fn pointer type. + ty_bare_fn(Option<DefId>, BareFnTy<'tcx>), + ty_closure(Box<ClosureTy<'tcx>>), ty_trait(Box<TyTrait<'tcx>>), ty_struct(DefId, Substs<'tcx>), + ty_unboxed_closure(DefId, Region, Substs<'tcx>), + ty_tup(Vec<Ty<'tcx>>), ty_param(ParamTy), // type parameter @@ -2339,15 +2346,19 @@ pub fn mk_closure<'tcx>(cx: &ctxt<'tcx>, fty: ClosureTy<'tcx>) -> Ty<'tcx> { mk_t(cx, ty_closure(box fty)) } -pub fn mk_bare_fn<'tcx>(cx: &ctxt<'tcx>, fty: BareFnTy<'tcx>) -> Ty<'tcx> { - mk_t(cx, ty_bare_fn(fty)) +pub fn mk_bare_fn<'tcx>(cx: &ctxt<'tcx>, + opt_def_id: Option<ast::DefId>, + fty: BareFnTy<'tcx>) -> Ty<'tcx> { + mk_t(cx, ty_bare_fn(opt_def_id, fty)) } pub fn mk_ctor_fn<'tcx>(cx: &ctxt<'tcx>, + def_id: ast::DefId, input_tys: &[Ty<'tcx>], output: Ty<'tcx>) -> Ty<'tcx> { let input_args = input_tys.iter().map(|ty| *ty).collect(); mk_bare_fn(cx, + Some(def_id), BareFnTy { unsafety: ast::Unsafety::Normal, abi: abi::Rust, @@ -3560,6 +3571,13 @@ pub fn type_is_bare_fn(ty: Ty) -> bool { } } +pub fn type_is_bare_fn_item(ty: Ty) -> bool { + match ty.sty { + ty_bare_fn(Some(_), _) => true, + _ => false + } +} + pub fn type_is_fp(ty: Ty) -> bool { match ty.sty { ty_infer(FloatVar(_)) | ty_float(_) => true, @@ -3975,9 +3993,9 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>, return match adjustment { Some(adjustment) => { match *adjustment { - AdjustAddEnv(store) => { + AdjustAddEnv(_, store) => { match unadjusted_ty.sty { - ty::ty_bare_fn(ref b) => { + ty::ty_bare_fn(Some(_), ref b) => { let bounds = ty::ExistentialBounds { region_bound: ReStatic, builtin_bounds: all_builtin_bounds(), @@ -3994,7 +4012,21 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>, } ref b => { cx.sess.bug( - format!("add_env adjustment on non-bare-fn: \ + format!("add_env adjustment on non-fn-item: \ + {}", + b).as_slice()); + } + } + } + + AdjustReifyFnPointer(_) => { + match unadjusted_ty.sty { + ty::ty_bare_fn(Some(_), ref b) => { + ty::mk_bare_fn(cx, None, (*b).clone()) + } + ref b => { + cx.sess.bug( + format!("AdjustReifyFnPointer adjustment on non-fn-item: \ {}", b).as_slice()); } @@ -4353,7 +4385,8 @@ pub fn ty_sort_string<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> String { ty_vec(_, None) => "slice".to_string(), ty_ptr(_) => "*-ptr".to_string(), ty_rptr(_, _) => "&-ptr".to_string(), - ty_bare_fn(_) => "extern fn".to_string(), + ty_bare_fn(Some(_), _) => format!("fn item"), + ty_bare_fn(None, _) => "fn pointer".to_string(), ty_closure(_) => "fn".to_string(), ty_trait(ref inner) => { 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) - region(state, r); mt(state, m); } - ty_bare_fn(ref b) => { + ty_bare_fn(opt_def_id, ref b) => { byte!(14); + hash!(opt_def_id); hash!(b.unsafety); hash!(b.abi); fn_sig(state, &b.sig); @@ -6252,6 +6286,7 @@ impl<'tcx> AutoAdjustment<'tcx> { pub fn is_identity(&self) -> bool { match *self { AdjustAddEnv(..) => false, + AdjustReifyFnPointer(..) => false, AdjustDerefRef(ref r) => r.is_identity(), } } @@ -6367,8 +6402,11 @@ impl DebruijnIndex { impl<'tcx> Repr<'tcx> for AutoAdjustment<'tcx> { fn repr(&self, tcx: &ctxt<'tcx>) -> String { match *self { - AdjustAddEnv(ref trait_store) => { - format!("AdjustAddEnv({})", trait_store) + AdjustAddEnv(def_id, ref trait_store) => { + format!("AdjustAddEnv({},{})", def_id.repr(tcx), trait_store) + } + AdjustReifyFnPointer(def_id) => { + format!("AdjustAddEnv({})", def_id.repr(tcx)) } AdjustDerefRef(ref data) => { data.repr(tcx) diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index d69ae96d07e..a35ea30b217 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -538,8 +538,8 @@ pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T, ty::ty_tup(ref ts) => { ty::ty_tup(ts.fold_with(this)) } - ty::ty_bare_fn(ref f) => { - ty::ty_bare_fn(f.fold_with(this)) + ty::ty_bare_fn(opt_def_id, ref f) => { + ty::ty_bare_fn(opt_def_id, f.fold_with(this)) } ty::ty_closure(ref f) => { ty::ty_closure(box f.fold_with(this)) diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index ca1e0d7de72..8b2c7f3a78a 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -542,6 +542,7 @@ pub fn get_res_dtor<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let class_ty = ty::lookup_item_type(tcx, parent_id).ty.subst(tcx, substs); let llty = type_of_dtor(ccx, class_ty); let dtor_ty = ty::mk_ctor_fn(ccx.tcx(), + did, &[glue::get_drop_glue_type(ccx, t)], ty::mk_nil(ccx.tcx())); get_extern_fn(ccx, diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 1a753901f7e..7e7a6dfc48a 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -18,10 +18,9 @@ pub use self::AutorefArg::*; pub use self::CalleeData::*; pub use self::CallArgs::*; -use arena::TypedArena; -use back::{abi,link}; +use back::abi; use session; -use llvm::{ValueRef, get_param}; +use llvm::{ValueRef}; use llvm; use metadata::csearch; use middle::def; diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs index d5d954f5a90..bbf8cb1c070 100644 --- a/src/librustc_trans/trans/closure.rs +++ b/src/librustc_trans/trans/closure.rs @@ -13,7 +13,6 @@ pub use self::ClosureKind::*; use back::abi; use back::link::mangle_internal_name_by_path_and_seq; use llvm::ValueRef; -use middle::def; use middle::mem_categorization::Typer; use trans::adt; use trans::base::*; @@ -603,21 +602,10 @@ pub fn trans_unboxed_closure<'blk, 'tcx>( pub fn get_wrapper_for_bare_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, closure_ty: Ty<'tcx>, - def: def::Def, + def_id: ast::DefId, fn_ptr: ValueRef, - is_local: bool) -> ValueRef { - - let def_id = match def { - def::DefFn(did, _) | def::DefStaticMethod(did, _) | - def::DefVariant(_, did, _) | def::DefStruct(did) => did, - _ => { - ccx.sess().bug(format!("get_wrapper_for_bare_fn: \ - expected a statically resolved fn, got \ - {}", - def).as_slice()); - } - }; - + is_local: bool) -> ValueRef +{ match ccx.closure_bare_wrapper_cache().borrow().get(&fn_ptr) { Some(&llval) => return llval, None => {} @@ -697,11 +685,11 @@ pub fn get_wrapper_for_bare_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, pub fn make_closure_from_bare_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, closure_ty: Ty<'tcx>, - def: def::Def, + def_id: ast::DefId, fn_ptr: ValueRef) -> DatumBlock<'blk, 'tcx, Expr> { let scratch = rvalue_scratch_datum(bcx, closure_ty, "__adjust"); - let wrapper = get_wrapper_for_bare_fn(bcx.ccx(), closure_ty, def, fn_ptr, true); + let wrapper = get_wrapper_for_bare_fn(bcx.ccx(), closure_ty, def_id, fn_ptr, true); fill_fn_pair(bcx, scratch.val, wrapper, C_null(Type::i8p(bcx.ccx()))); DatumBlock::new(bcx, scratch.to_expr_datum()) diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index e4f0543b5e7..1125a2aa529 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -190,16 +190,15 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, e: &ast::Expr) None => { } Some(adj) => { match adj { - ty::AdjustAddEnv(ty::RegionTraitStore(ty::ReStatic, _)) => { - let def = ty::resolve_expr(cx.tcx(), e); + ty::AdjustAddEnv(def_id, ty::RegionTraitStore(ty::ReStatic, _)) => { let wrapper = closure::get_wrapper_for_bare_fn(cx, ety_adjusted, - def, + def_id, llconst, true); llconst = C_struct(cx, &[wrapper, C_null(Type::i8p(cx))], false) } - ty::AdjustAddEnv(store) => { + ty::AdjustAddEnv(_, store) => { cx.sess() .span_bug(e.span, format!("unexpected static function: {}", diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index 81892e5fa83..3e3252a347d 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -54,7 +54,7 @@ use trans::inline; use trans::tvec; use trans::type_of; use middle::ty::{struct_fields, tup_fields}; -use middle::ty::{AdjustDerefRef, AdjustAddEnv, AutoUnsafe}; +use middle::ty::{AdjustDerefRef, AdjustReifyFnPointer, AdjustAddEnv, AutoUnsafe}; use middle::ty::{AutoPtr}; use middle::ty::{mod, Ty}; use middle::ty::MethodCall; @@ -177,8 +177,9 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, datum.to_string(bcx.ccx()), adjustment.repr(bcx.tcx())); match adjustment { - AdjustAddEnv(..) => { - datum = unpack_datum!(bcx, add_env(bcx, expr, datum)); + AdjustAddEnv(def_id, _) => { + datum = unpack_datum!(bcx, add_env(bcx, def_id, expr, datum)); + } } AdjustDerefRef(ref adj) => { let (autoderefs, use_autoref) = match adj.autoref { @@ -466,6 +467,7 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } fn add_env<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, + def_id: ast::DefId, expr: &ast::Expr, datum: Datum<'tcx, Expr>) -> DatumBlock<'blk, 'tcx, Expr> { @@ -477,8 +479,7 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let closure_ty = expr_ty_adjusted(bcx, expr); let fn_ptr = datum.to_llscalarish(bcx); - let def = ty::resolve_expr(bcx.tcx(), expr); - closure::make_closure_from_bare_fn(bcx, closure_ty, def, fn_ptr) + closure::make_closure_from_bare_fn(bcx, closure_ty, def_id, fn_ptr) } } diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs index dea095ecaf5..e3c1e4b12bf 100644 --- a/src/librustc_trans/trans/glue.rs +++ b/src/librustc_trans/trans/glue.rs @@ -289,6 +289,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } let dtor_ty = ty::mk_ctor_fn(bcx.tcx(), + class_did, &[get_drop_glue_type(bcx.ccx(), t)], ty::mk_nil(bcx.tcx())); let (_, variant_cx) = invoke(variant_cx, dtor_addr, args[], dtor_ty, None, false); diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 15f6d7bc3f4..de7adda6bfd 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -639,7 +639,8 @@ fn emit_vtable_methods<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, m.repr(tcx), substs.repr(tcx)); if m.generics.has_type_params(subst::FnSpace) || - ty::type_has_self(ty::mk_bare_fn(tcx, m.fty.clone())) { + ty::type_has_self(ty::mk_bare_fn(tcx, None, m.fty.clone())) + { debug!("(making impl vtable) method has self or type \ params: {}", token::get_name(name)); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 175763c874e..cd711deabed 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -954,7 +954,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( tcx.sess.span_err(ast_ty.span, "variadic function must have C calling convention"); } - ty::mk_bare_fn(tcx, ty_of_bare_fn(this, bf.unsafety, bf.abi, &*bf.decl)) + ty::mk_bare_fn(tcx, None, ty_of_bare_fn(this, bf.unsafety, bf.abi, &*bf.decl)) } ast::TyClosure(ref f) => { // Use corresponding trait store to figure out default bounds diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 2c220f29826..10801563f61 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -113,7 +113,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { self.add_obligations(&pick, &method_bounds_substs, &method_bounds); // Create the final `MethodCallee`. - let fty = ty::mk_bare_fn(self.tcx(), ty::BareFnTy { + let fty = ty::mk_bare_fn(self.tcx(), None, ty::BareFnTy { sig: ty::Binder(method_sig), unsafety: pick.method_ty.fty.unsafety, abi: pick.method_ty.fty.abi.clone(), diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 3b7eb22e56c..af5434e94fe 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -199,7 +199,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>, infer::FnCall, &fn_sig).0; let transformed_self_ty = fn_sig.inputs[0]; - let fty = ty::mk_bare_fn(tcx, ty::BareFnTy { + let fty = ty::mk_bare_fn(tcx, None, ty::BareFnTy { sig: ty::Binder(fn_sig), unsafety: bare_fn_ty.unsafety, abi: bare_fn_ty.abi.clone(), diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index cd9a09efe08..7078f1e58c7 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1132,9 +1132,9 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, } // Compute skolemized form of impl and trait method tys. - let impl_fty = ty::mk_bare_fn(tcx, impl_m.fty.clone()); + let impl_fty = ty::mk_bare_fn(tcx, None, impl_m.fty.clone()); let impl_fty = impl_fty.subst(tcx, &impl_to_skol_substs); - let trait_fty = ty::mk_bare_fn(tcx, trait_m.fty.clone()); + let trait_fty = ty::mk_bare_fn(tcx, None, trait_m.fty.clone()); let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs); // Check the impl method type IM is a subtype of the trait method @@ -1389,6 +1389,8 @@ fn check_cast(fcx: &FnCtxt, }, t_e, None); } + let t_e_is_bare_fn_item = ty::type_is_bare_fn_item(t_e); + let t_1_is_scalar = ty::type_is_scalar(t_1); let t_1_is_char = ty::type_is_char(t_1); let t_1_is_bare_fn = ty::type_is_bare_fn(t_1); @@ -1396,7 +1398,9 @@ fn check_cast(fcx: &FnCtxt, // 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 ty::type_is_c_like_enum(fcx.tcx(), t_e) && t_1_is_trivial { + if t_e_is_bare_fn_item && t_1_is_bare_fn { + demand::coerce(fcx, e.span, t_1, &*e); + } else if ty::type_is_c_like_enum(fcx.tcx(), t_e) && t_1_is_trivial { if t_1_is_float || ty::type_is_unsafe_ptr(t_1) { fcx.type_error_message(span, |actual| { format!("illegal cast; cast through an \ @@ -1634,7 +1638,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, adj: &ty::AutoAdjustment<'tcx>) { match *adj { - ty::AdjustAddEnv(..) => { } + ty::AdjustAddEnv(..) | + ty::AdjustReifyFnPointer(..) => { + } ty::AdjustDerefRef(ref d_r) => { match d_r.autoref { Some(ref a_r) => { @@ -5627,7 +5633,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) { }; (n_tps, inputs, ty::FnConverging(output)) }; - let fty = ty::mk_bare_fn(tcx, ty::BareFnTy { + let fty = ty::mk_bare_fn(tcx, None, ty::BareFnTy { unsafety: ast::Unsafety::Unsafe, abi: abi::RustIntrinsic, sig: ty::Binder(FnSig { diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 700d1211606..b123d97d897 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -15,7 +15,6 @@ use self::ResolveReason::*; use astconv::AstConv; use check::FnCtxt; -use middle::def; use middle::pat_util; use middle::ty::{mod, Ty, MethodCall, MethodCallee}; use middle::ty_fold::{TypeFolder,TypeFoldable}; @@ -267,25 +266,12 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { Some(adjustment) => { let adj_object = ty::adjust_is_object(&adjustment); let resolved_adjustment = match adjustment { - ty::AdjustAddEnv(store) => { - // FIXME(eddyb) #2190 Allow only statically resolved - // bare functions to coerce to a closure to avoid - // constructing (slower) indirect call wrappers. - match self.tcx().def_map.borrow().get(&id) { - Some(&def::DefFn(..)) | - Some(&def::DefStaticMethod(..)) | - Some(&def::DefVariant(..)) | - Some(&def::DefStruct(_)) => { - } - _ => { - span_err!(self.tcx().sess, reason.span(self.tcx()), E0100, - "cannot coerce non-statically resolved bare fn to closure"); - span_help!(self.tcx().sess, reason.span(self.tcx()), - "consider embedding the function in a closure"); - } - } + ty::AdjustAddEnv(def_id, store) => { + ty::AdjustAddEnv(def_id, self.resolve(&store, reason)) + } - ty::AdjustAddEnv(self.resolve(&store, reason)) + ty::AdjustReifyFnPointer(def_id) => { + ty::AdjustReifyFnPointer(def_id) } ty::AdjustDerefRef(adj) => { diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 5d0bb6622c2..bba6af95845 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -235,7 +235,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { // impl, plus its own. let new_polytype = ty::Polytype { generics: new_method_ty.generics.clone(), - ty: ty::mk_bare_fn(tcx, new_method_ty.fty.clone()) + ty: ty::mk_bare_fn(tcx, Some(new_did), new_method_ty.fty.clone()) }; debug!("new_polytype={}", new_polytype.repr(tcx)); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 3f59b50337f..af996da5543 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -211,13 +211,15 @@ pub fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // Create a set of parameter types shared among all the variants. for variant in variants.iter() { + let variant_def_id = local_def(variant.node.id); + // Nullary enum constructors get turned into constants; n-ary enum // constructors get turned into functions. let result_ty = match variant.node.kind { ast::TupleVariantKind(ref args) if args.len() > 0 => { let rs = ExplicitRscope; let input_tys: Vec<_> = args.iter().map(|va| ccx.to_ty(&rs, &*va.ty)).collect(); - ty::mk_ctor_fn(tcx, input_tys.as_slice(), enum_ty) + ty::mk_ctor_fn(tcx, variant_def_id, input_tys.as_slice(), enum_ty) } ast::TupleVariantKind(_) => { @@ -246,7 +248,7 @@ pub fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ty: result_ty }; - tcx.tcache.borrow_mut().insert(local_def(variant.node.id), pty); + tcx.tcache.borrow_mut().insert(variant_def_id, pty); write_ty_to_tcx(tcx, variant.node.id, result_ty); } @@ -353,7 +355,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, m.def_id, Polytype { generics: m.generics.clone(), - ty: ty::mk_bare_fn(ccx.tcx, m.fty.clone()) }); + ty: ty::mk_bare_fn(ccx.tcx, Some(m.def_id), m.fty.clone()) }); } fn ty_method_of_trait_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, @@ -519,6 +521,7 @@ fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>, tcx.sess.span_err(m.span, "duplicate method in trait impl"); } + let m_def_id = local_def(m.id); let mty = Rc::new(ty_of_method(ccx, convert_method_context, container, @@ -526,13 +529,13 @@ fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>, untransformed_rcvr_ty, rcvr_ty_generics, rcvr_visibility)); - let fty = ty::mk_bare_fn(tcx, mty.fty.clone()); + let fty = ty::mk_bare_fn(tcx, Some(m_def_id), mty.fty.clone()); debug!("method {} (id {}) has type {}", m.pe_ident().repr(tcx), m.id, fty.repr(tcx)); tcx.tcache.borrow_mut().insert( - local_def(m.id), + m_def_id, Polytype { generics: mty.generics.clone(), ty: fty @@ -1279,6 +1282,7 @@ pub fn convert_struct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, |field| (*tcx.tcache.borrow())[ local_def(field.node.id)].ty).collect(); let ctor_fn_ty = ty::mk_ctor_fn(tcx, + local_def(ctor_id), inputs.as_slice(), selfty); write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty); @@ -1461,7 +1465,7 @@ pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item) }; let pty = Polytype { generics: ty_generics, - ty: ty::mk_bare_fn(ccx.tcx, tofd) + ty: ty::mk_bare_fn(ccx.tcx, Some(local_def(it.id)), tofd) }; debug!("type of {} (id {}) is {}", token::get_ident(it.ident), @@ -2138,6 +2142,7 @@ pub fn ty_of_foreign_fn_decl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let t_fn = ty::mk_bare_fn( ccx.tcx, + None, ty::BareFnTy { abi: abi, unsafety: ast::Unsafety::Unsafe, diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 49c5f13fa73..c30293e4765 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -102,6 +102,7 @@ use util::ppaux; use syntax::codemap::Span; use syntax::print::pprust::*; use syntax::{ast, ast_map, abi}; +use syntax::ast_util::local_def; #[cfg(stage0)] mod diagnostics; @@ -224,7 +225,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt, } _ => () } - let se_ty = ty::mk_bare_fn(tcx, ty::BareFnTy { + let se_ty = ty::mk_bare_fn(tcx, Some(local_def(main_id)), ty::BareFnTy { unsafety: ast::Unsafety::Normal, abi: abi::Rust, sig: ty::Binder(ty::FnSig { @@ -272,7 +273,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt, _ => () } - let se_ty = ty::mk_bare_fn(tcx, ty::BareFnTy { + let se_ty = ty::mk_bare_fn(tcx, Some(local_def(start_id)), ty::BareFnTy { unsafety: ast::Unsafety::Normal, abi: abi::Rust, sig: ty::Binder(ty::FnSig { |
