diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 01096c1fd4e96..778314f352c25 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -1230,6 +1230,7 @@ impl BTreeMap { #[unstable = "matches collection reform specification, waiting for dust to settle"] pub fn keys<'a>(&'a self) -> Keys<'a, K, V> { fn first((a, _): (A, B)) -> A { a } + let first: fn((&'a K, &'a V)) -> &'a K = first; // coerce to fn pointer Keys { inner: self.iter().map(first) } } @@ -1251,6 +1252,7 @@ impl BTreeMap { #[unstable = "matches collection reform specification, waiting for dust to settle"] pub fn values<'a>(&'a self) -> Values<'a, K, V> { fn second((_, b): (A, B)) -> B { b } + let second: fn((&'a K, &'a V)) -> &'a V = second; // coerce to fn pointer Values { inner: self.iter().map(second) } } diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index e4328a3cb202b..4ab9c7a4fcdd9 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -126,6 +126,7 @@ impl BTreeSet { #[unstable = "matches collection reform specification, waiting for dust to settle"] pub fn into_iter(self) -> MoveItems { fn first((a, _): (A, B)) -> A { a } + let first: fn((T, ())) -> T = first; // coerce to fn pointer MoveItems { iter: self.map.into_iter().map(first) } } diff --git a/src/libcollections/vec_map.rs b/src/libcollections/vec_map.rs index 1babde6066d06..553eae4d896d1 100644 --- a/src/libcollections/vec_map.rs +++ b/src/libcollections/vec_map.rs @@ -144,6 +144,7 @@ impl VecMap { #[unstable = "matches collection reform specification, waiting for dust to settle"] pub fn keys<'r>(&'r self) -> Keys<'r, V> { fn first((a, _): (A, B)) -> A { a } + let first: fn((uint, &'r V)) -> uint = first; // coerce to fn pointer Keys { iter: self.iter().map(first) } } @@ -153,6 +154,7 @@ impl VecMap { #[unstable = "matches collection reform specification, waiting for dust to settle"] pub fn values<'r>(&'r self) -> Values<'r, V> { fn second((_, b): (A, B)) -> B { b } + let second: fn((uint, &'r V)) -> &'r V = second; // coerce to fn pointer Values { iter: self.iter().map(second) } } @@ -239,6 +241,7 @@ impl VecMap { fn filter((i, v): (uint, Option)) -> Option<(uint, A)> { v.map(|v| (i, v)) } + let filter: fn((uint, Option)) -> Option<(uint, V)> = filter; // coerce to fn ptr let values = replace(&mut self.v, vec!()); MoveItems { iter: values.into_iter().enumerate().filter_map(filter) } diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index b592d1db274f6..1cd4d7b89d6d6 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -2612,6 +2612,9 @@ pub fn iterate(seed: T, f: F) -> Iterate where val.clone() } + // coerce to a fn pointer + let next: fn(&mut IterateState) -> Option = next; + Unfold::new((f, Some(seed), true), next) } diff --git a/src/libcore/str.rs b/src/libcore/str.rs index a89a7970ae9c4..8381deb2bf7d7 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -30,9 +30,9 @@ use iter::range; use kinds::Sized; use mem; use num::Int; +use ops::{Fn, FnMut}; use option::Option; use option::Option::{None, Some}; -use ops::{Fn, FnMut}; use ptr::RawPtr; use raw::{Repr, Slice}; use slice::{mod, SliceExt}; @@ -2100,6 +2100,7 @@ impl StrPrelude for str { else { line } } + let f: fn(&str) -> &str = f; // coerce to fn pointer self.lines().map(f) } diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index d8168814c6cd0..9d9b8780bbfb6 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -700,7 +700,7 @@ pub fn get_enum_variants<'tcx>(intr: Rc, cdata: Cmd, id: ast::Nod item, tcx, cdata); let name = item_name(&*intr, item); let (ctor_ty, arg_tys, arg_names) = match ctor_ty.sty { - ty::ty_bare_fn(ref f) => + ty::ty_bare_fn(_, ref f) => (Some(ctor_ty), f.sig.0.inputs.clone(), None), _ => { // Nullary or struct enum variant. let mut arg_names = Vec::new(); diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 9d3a2c1d66777..5b78265a41518 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -453,7 +453,11 @@ fn parse_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> Ty<'tcx> { return ty::mk_closure(st.tcx, parse_closure_ty(st, |x,y| conv(x,y))); } 'F' => { - return ty::mk_bare_fn(st.tcx, parse_bare_fn_ty(st, |x,y| conv(x,y))); + let def_id = parse_def(st, NominalType, |x,y| conv(x,y)); + return ty::mk_bare_fn(st.tcx, Some(def_id), parse_bare_fn_ty(st, |x,y| conv(x,y))); + } + 'G' => { + return ty::mk_bare_fn(st.tcx, None, parse_bare_fn_ty(st, |x,y| conv(x,y))); } '#' => { let pos = parse_hex(st); diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index ce63c467822db..7fa23620af4b6 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -123,8 +123,13 @@ pub fn enc_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, t: Ty<'t mywrite!(w, "f"); enc_closure_ty(w, cx, &**f); } - ty::ty_bare_fn(ref f) => { + ty::ty_bare_fn(Some(def_id), ref f) => { mywrite!(w, "F"); + mywrite!(w, "{}|", (cx.ds)(def_id)); + enc_bare_fn_ty(w, cx, f); + } + ty::ty_bare_fn(None, ref f) => { + mywrite!(w, "G"); enc_bare_fn_ty(w, cx, f); } ty::ty_infer(_) => { diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 69fbd59fd9241..592b509c0b4c1 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -1007,14 +1007,21 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> { self.emit_enum("AutoAdjustment", |this| { match *adj { - ty::AdjustAddEnv(store) => { - this.emit_enum_variant("AutoAddEnv", 0, 1, |this| { - this.emit_enum_variant_arg(0, |this| store.encode(this)) + ty::AdjustAddEnv(def_id, store) => { + this.emit_enum_variant("AdjustAddEnv", 0, 2, |this| { + this.emit_enum_variant_arg(0, |this| def_id.encode(this)); + this.emit_enum_variant_arg(1, |this| store.encode(this)) + }) + } + + ty::AdjustReifyFnPointer(def_id) => { + this.emit_enum_variant("AdjustReifyFnPointer", 1, 2, |this| { + this.emit_enum_variant_arg(0, |this| def_id.encode(this)) }) } ty::AdjustDerefRef(ref auto_deref_ref) => { - this.emit_enum_variant("AutoDerefRef", 1, 1, |this| { + this.emit_enum_variant("AdjustDerefRef", 2, 2, |this| { this.emit_enum_variant_arg(0, |this| Ok(this.emit_auto_deref_ref(ecx, auto_deref_ref))) }) @@ -1648,12 +1655,20 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> { this.read_enum_variant(&variants, |this, i| { Ok(match i { 0 => { + let def_id: ast::DefId = + this.read_def_id(dcx); let store: ty::TraitStore = this.read_enum_variant_arg(0, |this| Decodable::decode(this)).unwrap(); - ty::AdjustAddEnv(store.tr(dcx)) + ty::AdjustAddEnv(def_id, store.tr(dcx)) } 1 => { + let def_id: ast::DefId = + this.read_def_id(dcx); + + ty::AdjustReifyFnPointer(def_id) + } + 2 => { let auto_deref_ref: ty::AutoDerefRef = this.read_enum_variant_arg(0, |this| Ok(this.read_auto_deref_ref(dcx))).unwrap(); diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index a91ea8bfef8c7..e08dd64d4d411 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/effect.rs b/src/librustc/middle/effect.rs index 0c0cba6e53e06..52899aaba412f 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -32,7 +32,7 @@ enum UnsafeContext { fn type_is_unsafe_function(ty: Ty) -> bool { match ty.sty { - ty::ty_bare_fn(ref f) => f.unsafety == ast::Unsafety::Unsafe, + ty::ty_bare_fn(_, ref f) => f.unsafety == ast::Unsafety::Unsafe, ty::ty_closure(ref f) => f.unsafety == ast::Unsafety::Unsafe, _ => false, } diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index abc3c8d0d8fa4..046a2894b5dfc 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/fast_reject.rs b/src/librustc/middle/fast_reject.rs index 297d6bcb03cb9..62cf47da68701 100644 --- a/src/librustc/middle/fast_reject.rs +++ b/src/librustc/middle/fast_reject.rs @@ -83,7 +83,7 @@ pub fn simplify_type(tcx: &ty::ctxt, ty::ty_closure(ref f) => { Some(FunctionSimplifiedType(f.sig.0.inputs.len())) } - ty::ty_bare_fn(ref f) => { + ty::ty_bare_fn(_, ref f) => { Some(FunctionSimplifiedType(f.sig.0.inputs.len())) } ty::ty_param(_) => { diff --git a/src/librustc/middle/infer/coercion.rs b/src/librustc/middle/infer/coercion.rs index 64bfd1388026d..ec83b8fae9b7c 100644 --- a/src/librustc/middle/infer/coercion.rs +++ b/src/librustc/middle/infer/coercion.rs @@ -84,10 +84,14 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let Coerce(ref v) = *self; v } + fn tcx(&self) -> &ty::ctxt<'tcx> { + self.get_ref().infcx.tcx + } + pub fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> { debug!("Coerce.tys({} => {})", - a.repr(self.get_ref().infcx.tcx), - b.repr(self.get_ref().infcx.tcx)); + a.repr(self.tcx()), + b.repr(self.tcx())); // Consider coercing the subtype to a DST let unsize = self.unpack_actual_value(a, |a| { @@ -170,13 +174,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { self.unpack_actual_value(a, |a| { match a.sty { - ty::ty_bare_fn(ref a_f) => { - // Bare functions are coercible to any closure type. - // - // FIXME(#3320) this should go away and be - // replaced with proper inference, got a patch - // underway - ndm - self.coerce_from_bare_fn(a, a_f, b) + ty::ty_bare_fn(Some(a_def_id), ref a_f) => { + // Function items are coercible to any closure + // type; function pointers are not (that would + // require double indirection). + self.coerce_from_fn_item(a, a_def_id, a_f, b) } _ => { // Otherwise, just use subtyping rules. @@ -206,8 +208,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { mutbl_b: ast::Mutability) -> CoerceResult<'tcx> { debug!("coerce_borrowed_pointer(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 we have a parameter of type `&M T_a` and the value // provided is `expr`, we will be adding an implicit borrow, @@ -227,7 +229,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } }; - let a_borrowed = ty::mk_rptr(self.get_ref().infcx.tcx, + let a_borrowed = ty::mk_rptr(self.tcx(), r_borrow, mt {ty: inner_ty, mutbl: mutbl_b}); try!(sub.tys(a_borrowed, b)); @@ -247,8 +249,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { b: Ty<'tcx>) -> CoerceResult<'tcx> { debug!("coerce_unsized(a={}, b={})", - a.repr(self.get_ref().infcx.tcx), - b.repr(self.get_ref().infcx.tcx)); + a.repr(self.tcx()), + b.repr(self.tcx())); // Note, we want to avoid unnecessary unsizing. We don't want to coerce to // a DST unless we have to. This currently comes out in the wash since @@ -268,7 +270,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let coercion = Coercion(self.get_ref().trace.clone()); let r_borrow = self.get_ref().infcx.next_region_var(coercion); - let ty = ty::mk_rptr(self.get_ref().infcx.tcx, + let ty = ty::mk_rptr(self.tcx(), r_borrow, ty::mt{ty: ty, mutbl: mt_b.mutbl}); try!(self.get_ref().infcx.try(|_| sub.tys(ty, b))); @@ -292,7 +294,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { return Err(ty::terr_mutability); } - let ty = ty::mk_ptr(self.get_ref().infcx.tcx, + let ty = ty::mk_ptr(self.tcx(), ty::mt{ty: ty, mutbl: mt_b.mutbl}); try!(self.get_ref().infcx.try(|_| sub.tys(ty, b))); debug!("Success, coerced with AutoDerefRef(1, \ @@ -311,7 +313,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { self.unpack_actual_value(t_a, |a| { match self.unsize_ty(t_a, a, t_b) { Some((ty, kind)) => { - let ty = ty::mk_uniq(self.get_ref().infcx.tcx, ty); + let ty = ty::mk_uniq(self.tcx(), ty); try!(self.get_ref().infcx.try(|_| sub.tys(ty, b))); debug!("Success, coerced with AutoDerefRef(1, \ AutoUnsizeUniq({}))", kind); @@ -336,9 +338,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { a: Ty<'tcx>, ty_b: Ty<'tcx>) -> Option<(Ty<'tcx>, ty::UnsizeKind<'tcx>)> { - debug!("unsize_ty(a={}, ty_b={})", a, ty_b.repr(self.get_ref().infcx.tcx)); + debug!("unsize_ty(a={}, ty_b={})", a, ty_b.repr(self.tcx())); - let tcx = self.get_ref().infcx.tcx; + let tcx = self.tcx(); self.unpack_actual_value(ty_b, |b| match (&a.sty, &b.sty) { @@ -412,7 +414,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { b: Ty<'tcx>, b_mutbl: ast::Mutability) -> CoerceResult<'tcx> { - let tcx = self.get_ref().infcx.tcx; + let tcx = self.tcx(); debug!("coerce_borrowed_object(a={}, b={}, b_mutbl={})", a.repr(tcx), @@ -431,7 +433,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { b: Ty<'tcx>, b_mutbl: ast::Mutability) -> CoerceResult<'tcx> { - let tcx = self.get_ref().infcx.tcx; + let tcx = self.tcx(); debug!("coerce_unsafe_object(a={}, b={}, b_mutbl={})", a.repr(tcx), @@ -451,7 +453,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { F: FnOnce(Ty<'tcx>) -> Ty<'tcx>, G: FnOnce() -> ty::AutoRef<'tcx>, { - let tcx = self.get_ref().infcx.tcx; + let tcx = self.tcx(); match a.sty { ty::ty_rptr(_, ty::mt{ty, mutbl}) => match ty.sty { @@ -480,12 +482,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { b: Ty<'tcx>) -> CoerceResult<'tcx> { debug!("coerce_borrowed_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())); 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) @@ -493,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> { + /*! + * 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_fn_item(a={}, b={})", + a.repr(self.tcx()), b.repr(self.tcx())); - debug!("coerce_from_bare_fn(a={}, b={})", - a.repr(self.get_ref().infcx.tcx), b.repr(self.get_ref().infcx.tcx)); + 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); + } - if fn_ty_a.abi != abi::Rust || fn_ty_a.unsafety != ast::Unsafety::Normal { - return self.subtype(a, b); + 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) + } } - - 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)) }) } @@ -528,8 +544,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { mutbl_b: ast::Mutability) -> CoerceResult<'tcx> { debug!("coerce_unsafe_ptr(a={}, b={})", - a.repr(self.get_ref().infcx.tcx), - b.repr(self.get_ref().infcx.tcx)); + a.repr(self.tcx()), + b.repr(self.tcx())); let mt_a = match a.sty { ty::ty_rptr(_, mt) | ty::ty_ptr(mt) => mt, @@ -539,7 +555,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { }; // Check that the types which they point at are compatible. - let a_unsafe = ty::mk_ptr(self.get_ref().infcx.tcx, ty::mt{ mutbl: mutbl_b, ty: mt_a.ty }); + let a_unsafe = ty::mk_ptr(self.tcx(), ty::mt{ mutbl: mutbl_b, ty: mt_a.ty }); try!(self.subtype(a_unsafe, b)); if !can_coerce_mutbls(mt_a.mutbl, mutbl_b) { return Err(ty::terr_mutability); diff --git a/src/librustc/middle/infer/combine.rs b/src/librustc/middle/infer/combine.rs index 82ddbcee5a72e..fc240faac4490 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/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index ea19111ce3d67..6acbc98b4b27b 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -74,7 +74,7 @@ struct IntrinsicCheckingVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> IntrinsicCheckingVisitor<'a, 'tcx> { fn def_id_is_transmute(&self, def_id: DefId) -> bool { let intrinsic = match ty::lookup_item_type(self.tcx, def_id).ty.sty { - ty::ty_bare_fn(ref bfty) => bfty.abi == RustIntrinsic, + ty::ty_bare_fn(_, ref bfty) => bfty.abi == RustIntrinsic, _ => return false }; if def_id.krate == ast::LOCAL_CRATE { @@ -123,7 +123,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for IntrinsicCheckingVisitor<'a, 'tcx> { DefFn(did, _) if self.def_id_is_transmute(did) => { let typ = ty::node_id_to_type(self.tcx, expr.id); match typ.sty { - ty_bare_fn(ref bare_fn_ty) if bare_fn_ty.abi == RustIntrinsic => { + ty_bare_fn(_, ref bare_fn_ty) if bare_fn_ty.abi == RustIntrinsic => { if let ty::FnConverging(to) = bare_fn_ty.sig.0.output { let from = bare_fn_ty.sig.0.inputs[0]; self.check_transmute(expr.span, from, to, expr.id); diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index dce75579ca0a2..5aac988948f73 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/traits/select.rs b/src/librustc/middle/traits/select.rs index 8ba28b61006bd..77d7aac4d09f7 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -795,7 +795,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } // provide an impl, but only for suitable `fn` pointers - ty::ty_bare_fn(ty::BareFnTy { + ty::ty_bare_fn(_, ty::BareFnTy { unsafety: ast::Unsafety::Normal, abi: abi::Rust, sig: ty::Binder(ty::FnSig { @@ -984,7 +984,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::ty_int(_) | ty::ty_bool | ty::ty_float(_) | - ty::ty_bare_fn(_) | + ty::ty_bare_fn(..) | ty::ty_char => { // safe for everything Ok(If(Vec::new())) @@ -1543,7 +1543,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let self_ty = self.infcx.shallow_resolve(obligation.self_ty()); let sig = match self_ty.sty { - ty::ty_bare_fn(ty::BareFnTy { + ty::ty_bare_fn(_, ty::BareFnTy { unsafety: ast::Unsafety::Normal, abi: abi::Rust, ref sig diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 50a6fb9d0ca3f..aaa80f840fdae 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), // 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, BareFnTy<'tcx>), + ty_closure(Box>), ty_trait(Box>), ty_struct(DefId, Substs<'tcx>), + ty_unboxed_closure(DefId, Region, Substs<'tcx>), + ty_tup(Vec>), ty_param(ParamTy), // type parameter @@ -2178,7 +2185,7 @@ impl FlagComputation { self.add_tys(ts[]); } - &ty_bare_fn(ref f) => { + &ty_bare_fn(_, ref f) => { self.add_fn_sig(&f.sig); } @@ -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, + 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, @@ -2446,7 +2457,7 @@ pub fn maybe_walk_ty<'tcx>(ty: Ty<'tcx>, f: |Ty<'tcx>| -> bool) { } } ty_tup(ref ts) => { for tt in ts.iter() { maybe_walk_ty(*tt, |x| f(x)); } } - ty_bare_fn(ref ft) => { + ty_bare_fn(_, ref ft) => { for a in ft.sig.0.inputs.iter() { maybe_walk_ty(*a, |x| f(x)); } if let ty::FnConverging(output) = ft.sig.0.output { maybe_walk_ty(output, f); @@ -2929,7 +2940,7 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents { // Scalar and unique types are sendable, and durable ty_infer(ty::FreshIntTy(_)) | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) | - ty_bare_fn(_) | ty::ty_char => { + ty_bare_fn(..) | ty::ty_char => { TC::None } @@ -3264,7 +3275,7 @@ pub fn is_instantiable<'tcx>(cx: &ctxt<'tcx>, r_ty: Ty<'tcx>) -> bool { ty_uint(_) | ty_float(_) | ty_str | - ty_bare_fn(_) | + ty_bare_fn(..) | ty_closure(_) | ty_infer(_) | ty_err | @@ -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, @@ -3792,7 +3810,7 @@ pub fn node_id_item_substs<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) -> ItemSubsts pub fn fn_is_variadic(fty: Ty) -> bool { match fty.sty { - ty_bare_fn(ref f) => f.sig.0.variadic, + ty_bare_fn(_, ref f) => f.sig.0.variadic, ty_closure(ref f) => f.sig.0.variadic, ref s => { panic!("fn_is_variadic() called on non-fn type: {}", s) @@ -3802,7 +3820,7 @@ pub fn fn_is_variadic(fty: Ty) -> bool { pub fn ty_fn_sig<'tcx>(fty: Ty<'tcx>) -> &'tcx PolyFnSig<'tcx> { match fty.sty { - ty_bare_fn(ref f) => &f.sig, + ty_bare_fn(_, ref f) => &f.sig, ty_closure(ref f) => &f.sig, ref s => { panic!("ty_fn_sig() called on non-fn type: {}", s) @@ -3813,7 +3831,7 @@ pub fn ty_fn_sig<'tcx>(fty: Ty<'tcx>) -> &'tcx PolyFnSig<'tcx> { /// Returns the ABI of the given function. pub fn ty_fn_abi(fty: Ty) -> abi::Abi { match fty.sty { - ty_bare_fn(ref f) => f.abi, + ty_bare_fn(_, ref f) => f.abi, ty_closure(ref f) => f.abi, _ => panic!("ty_fn_abi() called on non-fn type"), } @@ -3840,7 +3858,7 @@ pub fn ty_closure_store(fty: Ty) -> TraitStore { pub fn ty_fn_ret<'tcx>(fty: Ty<'tcx>) -> FnOutput<'tcx> { match fty.sty { - ty_bare_fn(ref f) => f.sig.0.output, + ty_bare_fn(_, ref f) => f.sig.0.output, ty_closure(ref f) => f.sig.0.output, ref s => { panic!("ty_fn_ret() called on non-fn type: {}", s) @@ -3850,7 +3868,7 @@ pub fn ty_fn_ret<'tcx>(fty: Ty<'tcx>) -> FnOutput<'tcx> { pub fn is_fn_ty(fty: Ty) -> bool { match fty.sty { - ty_bare_fn(_) => true, + ty_bare_fn(..) => true, ty_closure(_) => true, _ => false } @@ -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())) @@ -4544,6 +4577,10 @@ pub fn note_and_explain_type_err(cx: &ctxt, err: &type_err) { "concrete lifetime that was found is ", conc_region, ""); } + terr_regions_overly_polymorphic(_, ty::ReInfer(ty::ReVar(_))) => { + // don't bother to print out the message below for + // inference variables, it's not very illuminating. + } terr_regions_overly_polymorphic(_, conc_region) => { note_and_explain_region(cx, "expected concrete lifetime is ", @@ -5884,8 +5921,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); @@ -6200,7 +6238,7 @@ pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec, ty_str | ty_vec(_, _) | ty_ptr(_) | - ty_bare_fn(_) | + ty_bare_fn(..) | ty_tup(_) | ty_param(_) | ty_infer(_) | @@ -6252,6 +6290,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 +6406,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 d69ae96d07eca..a35ea30b21791 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/util/ppaux.rs b/src/librustc/util/ppaux.rs index 85a06125e23ab..476d9949812b2 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -254,12 +254,14 @@ pub fn vec_map_to_string(ts: &[T], f: F) -> String where pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { fn bare_fn_to_string<'tcx>(cx: &ctxt<'tcx>, + opt_def_id: Option, unsafety: ast::Unsafety, abi: abi::Abi, ident: Option, sig: &ty::PolyFnSig<'tcx>) -> String { let mut s = String::new(); + match unsafety { ast::Unsafety::Normal => {} ast::Unsafety::Unsafe => { @@ -284,6 +286,16 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { push_sig_to_string(cx, &mut s, '(', ')', sig, ""); + match opt_def_id { + Some(def_id) => { + s.push_str(" {"); + let path_str = ty::item_path_str(cx, def_id); + s.push_str(path_str[]); + s.push_str("}"); + } + None => { } + } + s } @@ -408,8 +420,8 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { ty_closure(ref f) => { closure_to_string(cx, &**f) } - ty_bare_fn(ref f) => { - bare_fn_to_string(cx, f.unsafety, f.abi, None, &f.sig) + ty_bare_fn(opt_def_id, ref f) => { + bare_fn_to_string(cx, opt_def_id, f.unsafety, f.abi, None, &f.sig) } ty_infer(infer_ty) => infer_ty_to_string(cx, infer_ty), ty_err => "[type error]".to_string(), diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 090d6a7a3caef..526bbca8d70dd 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -253,7 +253,18 @@ impl<'a, 'tcx> Env<'a, 'tcx> { output_ty: Ty<'tcx>) -> Ty<'tcx> { - ty::mk_ctor_fn(self.infcx.tcx, input_tys, output_ty) + let input_args = input_tys.iter().map(|ty| *ty).collect(); + ty::mk_bare_fn(self.infcx.tcx, + None, + ty::BareFnTy { + unsafety: ast::Unsafety::Normal, + abi: abi::Rust, + sig: ty::Binder(ty::FnSig { + inputs: input_args, + output: ty::FnConverging(output_ty), + variadic: false + }) + }) } pub fn t_nil(&self) -> Ty<'tcx> { diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index ca1e0d7de7210..3be40aed57ac6 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -282,7 +282,7 @@ pub fn kind_for_unboxed_closure(ccx: &CrateContext, closure_id: ast::DefId) pub fn decl_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty<'tcx>, name: &str) -> ValueRef { let (inputs, output, abi, env) = match fn_ty.sty { - ty::ty_bare_fn(ref f) => { + ty::ty_bare_fn(_, ref f) => { (f.sig.0.inputs.clone(), f.sig.0.output, f.abi, None) } ty::ty_closure(ref f) => { @@ -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, @@ -955,7 +956,7 @@ pub fn trans_external_path<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, did: ast::DefId, t: Ty<'tcx>) -> ValueRef { let name = csearch::get_symbol(&ccx.sess().cstore, did); match t.sty { - ty::ty_bare_fn(ref fn_ty) => { + ty::ty_bare_fn(_, ref fn_ty) => { match ccx.sess().target.target.adjust_abi(fn_ty.abi) { Rust | RustCall => { get_extern_rust_fn(ccx, t, name.as_slice(), did) @@ -2014,7 +2015,7 @@ pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, let tcx = ccx.tcx(); let result_ty = match ctor_ty.sty { - ty::ty_bare_fn(ref bft) => bft.sig.0.output.unwrap(), + ty::ty_bare_fn(_, ref bft) => bft.sig.0.output.unwrap(), _ => ccx.sess().bug( format!("trans_enum_variant_constructor: \ unexpected ctor return type {}", @@ -2086,7 +2087,7 @@ fn trans_enum_variant_or_tuple_like_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx let ctor_ty = ctor_ty.subst(ccx.tcx(), param_substs); let result_ty = match ctor_ty.sty { - ty::ty_bare_fn(ref bft) => bft.sig.0.output, + ty::ty_bare_fn(_, ref bft) => bft.sig.0.output, _ => ccx.sess().bug( format!("trans_enum_variant_or_tuple_like_struct: \ unexpected ctor return type {}", @@ -2421,7 +2422,7 @@ fn register_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, node_type: Ty<'tcx>) -> ValueRef { match node_type.sty { - ty::ty_bare_fn(ref f) => { + ty::ty_bare_fn(_, ref f) => { assert!(f.abi == Rust || f.abi == RustCall); } _ => panic!("expected bare rust fn") @@ -2438,7 +2439,7 @@ pub fn get_fn_llvm_attributes<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty< let (fn_sig, abi, has_env) = match fn_ty.sty { ty::ty_closure(ref f) => (f.sig.clone(), f.abi, true), - ty::ty_bare_fn(ref f) => (f.sig.clone(), f.abi, false), + ty::ty_bare_fn(_, ref f) => (f.sig.clone(), f.abi, false), ty::ty_unboxed_closure(closure_did, _, ref substs) => { let unboxed_closures = ccx.tcx().unboxed_closures.borrow(); let ref function_type = (*unboxed_closures)[closure_did] @@ -2467,7 +2468,7 @@ pub fn get_fn_llvm_attributes<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty< _ => ccx.sess().bug("expected tuple'd inputs") } }, - ty::ty_bare_fn(_) if abi == RustCall => { + ty::ty_bare_fn(..) if abi == RustCall => { let mut inputs = vec![fn_sig.0.inputs[0]]; match fn_sig.0.inputs[1].sty { diff --git a/src/librustc_trans/trans/basic_block.rs b/src/librustc_trans/trans/basic_block.rs index 476f5e2d618fe..ab25343ff5fe0 100644 --- a/src/librustc_trans/trans/basic_block.rs +++ b/src/librustc_trans/trans/basic_block.rs @@ -37,7 +37,10 @@ impl BasicBlock { pub fn pred_iter(self) -> Preds { fn is_a_terminator_inst(user: &Value) -> bool { user.is_a_terminator_inst() } + let is_a_terminator_inst: fn(&Value) -> bool = is_a_terminator_inst; + fn get_parent(user: Value) -> BasicBlock { user.get_parent().unwrap() } + let get_parent: fn(Value) -> BasicBlock = get_parent; self.as_value().user_iter() .filter(is_a_terminator_inst) diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 1a753901f7ea4..b60c75d305ca8 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -21,7 +21,8 @@ pub use self::CallArgs::*; use arena::TypedArena; use back::{abi,link}; use session; -use llvm::{ValueRef, get_param}; +use llvm::{ValueRef}; +use llvm::get_param; use llvm; use metadata::csearch; use middle::def; @@ -158,7 +159,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) } } def::DefFn(did, _) if match expr_ty.sty { - ty::ty_bare_fn(ref f) => f.abi == synabi::RustIntrinsic, + ty::ty_bare_fn(_, ref f) => f.abi == synabi::RustIntrinsic, _ => false } => { let substs = node_id_substs(bcx, ExprId(ref_expr.id)); @@ -275,15 +276,16 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( // Construct the "tuply" version of `bare_fn_ty`. It takes two arguments: `self`, // which is the fn pointer, and `args`, which is the arguments tuple. - let (input_tys, output_ty) = + let (opt_def_id, input_tys, output_ty) = match bare_fn_ty.sty { - ty::ty_bare_fn(ty::BareFnTy { unsafety: ast::Unsafety::Normal, + ty::ty_bare_fn(opt_def_id, + ty::BareFnTy { unsafety: ast::Unsafety::Normal, abi: synabi::Rust, sig: ty::Binder(ty::FnSig { inputs: ref input_tys, output: output_ty, variadic: false })}) => { - (input_tys, output_ty) + (opt_def_id, input_tys, output_ty) } _ => { @@ -293,6 +295,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( }; let tuple_input_ty = ty::mk_tup(tcx, input_tys.to_vec()); let tuple_fn_ty = ty::mk_bare_fn(tcx, + opt_def_id, ty::BareFnTy { unsafety: ast::Unsafety::Normal, abi: synabi::RustCall, sig: ty::Binder(ty::FnSig { @@ -655,7 +658,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, let mut bcx = callee.bcx; let (abi, ret_ty) = match callee_ty.sty { - ty::ty_bare_fn(ref f) => (f.abi, f.sig.0.output), + ty::ty_bare_fn(_, ref f) => (f.abi, f.sig.0.output), ty::ty_closure(ref f) => (f.abi, f.sig.0.output), _ => panic!("expected bare rust fn or closure in trans_call_inner") }; diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs index d5d954f5a907b..bbf8cb1c07025 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 e4f0543b5e70f..eff735e4946bb 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -190,21 +190,24 @@ 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: {}", store).as_slice()) } + ty::AdjustReifyFnPointer(_def_id) => { + // FIXME(#19925) once fn item types are + // zero-sized, we'll need to do something here + } ty::AdjustDerefRef(ref adj) => { let mut ty = ety; // Save the last autoderef in case we can avoid it. diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index 51e3a83f81f5a..b03934af016b3 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -430,7 +430,7 @@ impl<'tcx> TypeMap<'tcx> { trait_data.principal.substs(), &mut unique_type_id); }, - ty::ty_bare_fn(ty::BareFnTy{ unsafety, abi, ref sig } ) => { + ty::ty_bare_fn(_, ty::BareFnTy{ unsafety, abi, ref sig } ) => { if unsafety == ast::Unsafety::Unsafe { unique_type_id.push_str("unsafe "); } @@ -2997,7 +2997,7 @@ fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } } } - ty::ty_bare_fn(ref barefnty) => { + ty::ty_bare_fn(_, ref barefnty) => { subroutine_type_metadata(cx, unique_type_id, &barefnty.sig, usage_site_span) } ty::ty_closure(ref closurety) => { @@ -3814,7 +3814,7 @@ fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, push_item_name(cx, trait_data.principal.def_id(), false, output); push_type_params(cx, trait_data.principal.substs(), output); }, - ty::ty_bare_fn(ty::BareFnTy{ unsafety, abi, ref sig } ) => { + ty::ty_bare_fn(_, ty::BareFnTy{ unsafety, abi, ref sig } ) => { if unsafety == ast::Unsafety::Unsafe { output.push_str("unsafe "); } diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index 81892e5fa8321..536ef3ffd98ee 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,12 @@ 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)); + } + AdjustReifyFnPointer(_def_id) => { + // FIXME(#19925) once fn item types are + // zero-sized, we'll need to do something here } AdjustDerefRef(ref adj) => { let (autoderefs, use_autoref) = match adj.autoref { @@ -466,6 +470,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 +482,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/foreign.rs b/src/librustc_trans/trans/foreign.rs index d072031993050..e50d645afd8d5 100644 --- a/src/librustc_trans/trans/foreign.rs +++ b/src/librustc_trans/trans/foreign.rs @@ -228,7 +228,7 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ccx.tn().val_to_string(llretptr)); let (fn_abi, fn_sig) = match callee_ty.sty { - ty::ty_bare_fn(ref fn_ty) => (fn_ty.abi, fn_ty.sig.clone()), + ty::ty_bare_fn(_, ref fn_ty) => (fn_ty.abi, fn_ty.sig.clone()), _ => ccx.sess().bug("trans_native_call called on non-function type") }; let llsig = foreign_signature(ccx, &fn_sig, passed_arg_tys.as_slice()); @@ -479,7 +479,7 @@ pub fn decl_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let tys = foreign_types_for_fn_ty(ccx, t); let llfn_ty = lltype_for_fn_from_foreign_types(ccx, &tys); let cconv = match t.sty { - ty::ty_bare_fn(ref fn_ty) => { + ty::ty_bare_fn(_, ref fn_ty) => { llvm_calling_convention(ccx, fn_ty.abi) } _ => panic!("expected bare fn in decl_rust_fn_with_foreign_abi") @@ -502,7 +502,7 @@ pub fn register_rust_fn_with_foreign_abi(ccx: &CrateContext, let llfn_ty = lltype_for_fn_from_foreign_types(ccx, &tys); let t = ty::node_id_to_type(ccx.tcx(), node_id); let cconv = match t.sty { - ty::ty_bare_fn(ref fn_ty) => { + ty::ty_bare_fn(_, ref fn_ty) => { llvm_calling_convention(ccx, fn_ty.abi) } _ => panic!("expected bare fn in register_rust_fn_with_foreign_abi") @@ -556,7 +556,7 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, // Compute the type that the function would have if it were just a // normal Rust function. This will be the type of the wrappee fn. match t.sty { - ty::ty_bare_fn(ref f) => { + ty::ty_bare_fn(_, ref f) => { assert!(f.abi != Rust && f.abi != RustIntrinsic); } _ => { @@ -849,7 +849,7 @@ fn foreign_types_for_id<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn foreign_types_for_fn_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> ForeignTypes<'tcx> { let fn_sig = match ty.sty { - ty::ty_bare_fn(ref fn_ty) => fn_ty.sig.clone(), + ty::ty_bare_fn(_, ref fn_ty) => fn_ty.sig.clone(), _ => ccx.sess().bug("foreign_types_for_fn_ty called on non-function type") }; let llsig = foreign_signature(ccx, &fn_sig, fn_sig.0.inputs.as_slice()); diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs index dea095ecaf594..905ce3c61dce5 100644 --- a/src/librustc_trans/trans/glue.rs +++ b/src/librustc_trans/trans/glue.rs @@ -226,7 +226,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let fty = ty::lookup_item_type(bcx.tcx(), dtor_did).ty.subst(bcx.tcx(), substs); let self_ty = match fty.sty { - ty::ty_bare_fn(ref f) => { + ty::ty_bare_fn(_, ref f) => { assert!(f.sig.0.inputs.len() == 1); f.sig.0.inputs[0] } @@ -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/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs index a6f7c849f4d95..f676608bbcc70 100644 --- a/src/librustc_trans/trans/intrinsic.rs +++ b/src/librustc_trans/trans/intrinsic.rs @@ -150,7 +150,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, let tcx = bcx.tcx(); let ret_ty = match callee_ty.sty { - ty::ty_bare_fn(ref f) => f.sig.0.output, + ty::ty_bare_fn(_, ref f) => f.sig.0.output, _ => panic!("expected bare_fn in trans_intrinsic_call") }; let foreign_item = tcx.map.expect_foreign_item(node); diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 15f6d7bc3f42d..85f819b915c86 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -477,7 +477,7 @@ pub fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, debug!("(translating trait callee) loading method"); // Replace the self type (&Self or Box) with an opaque pointer. let llcallee_ty = match callee_ty.sty { - ty::ty_bare_fn(ref f) if f.abi == Rust || f.abi == RustCall => { + ty::ty_bare_fn(_, ref f) if f.abi == Rust || f.abi == RustCall => { type_of_rust_fn(ccx, Some(Type::i8p(ccx)), f.sig.0.inputs.slice_from(1), @@ -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_trans/trans/type_of.rs b/src/librustc_trans/trans/type_of.rs index 2801e0ccead6d..ae0c0aa5598df 100644 --- a/src/librustc_trans/trans/type_of.rs +++ b/src/librustc_trans/trans/type_of.rs @@ -150,7 +150,9 @@ pub fn type_of_fn_from_ty<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, fty: Ty<'tcx>) f.sig.0.output, f.abi) } - ty::ty_bare_fn(ref f) => { + ty::ty_bare_fn(_, ref f) => { + // FIXME(#19925) once fn item types are + // zero-sized, we'll need to do something here if f.abi == abi::Rust || f.abi == abi::RustCall { type_of_rust_fn(cx, None, @@ -364,7 +366,7 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type { ty::ty_str => Type::i8(cx), - ty::ty_bare_fn(_) => { + ty::ty_bare_fn(..) => { type_of_fn_from_ty(cx, t).ptr_to() } ty::ty_closure(_) => { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 175763c874efa..cd711deabed5f 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 2c220f298262f..d3b518ec2e3ab 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(), @@ -466,7 +466,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { fn fixup_derefs_on_method_receiver_if_necessary(&self, method_callee: &MethodCallee) { let sig = match method_callee.ty.sty { - ty::ty_bare_fn(ref f) => f.sig.clone(), + ty::ty_bare_fn(_, ref f) => f.sig.clone(), ty::ty_closure(ref f) => f.sig.clone(), _ => return, }; diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 3b7eb22e56cc4..af5434e94fe95 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 cd9a09efe082b..560d937f4a441 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -399,7 +399,7 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let fty = fty.subst(ccx.tcx, ¶m_env.free_substs); match fty.sty { - ty::ty_bare_fn(ref fn_ty) => { + ty::ty_bare_fn(_, ref fn_ty) => { let inh = Inherited::new(ccx.tcx, param_env); let fcx = check_fn(ccx, fn_ty.unsafety, id, &fn_ty.sig, decl, id, body, &inh); @@ -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) => { @@ -2043,7 +2049,7 @@ fn try_overloaded_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, // Bail out if the callee is a bare function or a closure. We check those // manually. match structurally_resolved_type(fcx, callee.span, callee_type).sty { - ty::ty_bare_fn(_) | ty::ty_closure(_) => return false, + ty::ty_bare_fn(..) | ty::ty_closure(_) => return false, _ => {} } @@ -2493,7 +2499,7 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, ty::FnConverging(ty::mk_err()) } else { match method_fn_ty.sty { - ty::ty_bare_fn(ref fty) => { + ty::ty_bare_fn(_, ref fty) => { // HACK(eddyb) ignore self in the definition (see above). check_argument_types(fcx, sp, @@ -2921,7 +2927,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, }); let fn_sig = match fn_ty.sty { - ty::ty_bare_fn(ty::BareFnTy {ref sig, ..}) | + ty::ty_bare_fn(_, ty::BareFnTy {ref sig, ..}) | ty::ty_closure(box ty::ClosureTy {ref sig, ..}) => sig, _ => { fcx.type_error_message(call_expr.span, |actual| { @@ -3861,7 +3867,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } let lhs_ty = fcx.expr_ty(&**lhs); - check_expr_has_type(fcx, &**rhs, lhs_ty); + check_expr_coercable_to_type(fcx, &**rhs, lhs_ty); let rhs_ty = fcx.expr_ty(&**rhs); fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized); @@ -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/wf.rs b/src/librustc_typeck/check/wf.rs index 24d7bf5031e46..a2fb44fff796f 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -355,7 +355,7 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> { self.fold_substs(substs); } - ty::ty_bare_fn(ty::BareFnTy{sig: ref fn_sig, ..}) | + ty::ty_bare_fn(_, ty::BareFnTy{sig: ref fn_sig, ..}) | ty::ty_closure(box ty::ClosureTy{sig: ref fn_sig, ..}) => { self.binding_count += 1; diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 700d12116060c..b123d97d8970c 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 5d0bb6622c2e1..bba6af9584594 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 3f59b50337faf..af996da5543dd 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 49c5f13fa7397..368658cb1c51a 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 { @@ -256,7 +257,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt, let tcx = ccx.tcx; let start_t = ty::node_id_to_type(tcx, start_id); match start_t.sty { - ty::ty_bare_fn(_) => { + ty::ty_bare_fn(..) => { match tcx.map.find(start_id) { Some(ast_map::NodeItem(it)) => { match it.node { @@ -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 { diff --git a/src/librustc_typeck/variance.rs b/src/librustc_typeck/variance.rs index ef0d1bc3859fa..e241be3e55c9b 100644 --- a/src/librustc_typeck/variance.rs +++ b/src/librustc_typeck/variance.rs @@ -814,12 +814,13 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { } } - ty::ty_bare_fn(ty::BareFnTy { ref sig, .. }) | + ty::ty_bare_fn(_, ty::BareFnTy { ref sig, .. }) | ty::ty_closure(box ty::ClosureTy { ref sig, store: ty::UniqTraitStore, .. - }) => { + }) => + { self.add_constraints_from_sig(sig, variance); } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index d0988af1cb473..2bc93ade7774e 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -176,7 +176,7 @@ pub fn build_external_trait(cx: &DocContext, tcx: &ty::ctxt, fn build_external_function(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) -> clean::Function { let t = ty::lookup_item_type(tcx, did); let (decl, style) = match t.ty.sty { - ty::ty_bare_fn(ref f) => ((did, &f.sig).clean(cx), f.unsafety), + ty::ty_bare_fn(_, ref f) => ((did, &f.sig).clean(cx), f.unsafety), _ => panic!("bad function"), }; clean::Function { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ac688784f926c..6e7a750d8b3fb 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1360,7 +1360,7 @@ impl<'tcx> Clean for ty::Ty<'tcx> { mutability: mt.mutbl.clean(cx), type_: box mt.ty.clean(cx), }, - ty::ty_bare_fn(ref fty) => BareFunction(box BareFunctionDecl { + ty::ty_bare_fn(_, ref fty) => BareFunction(box BareFunctionDecl { unsafety: fty.unsafety, generics: Generics { lifetimes: Vec::new(), diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 8b2f644dfe33b..009079bd21453 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -65,17 +65,21 @@ const HOEDOWN_EXTENSIONS: libc::c_uint = type hoedown_document = libc::c_void; // this is opaque to us +type blockcodefn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer, + *const hoedown_buffer, *mut libc::c_void); + +type headerfn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer, + libc::c_int, *mut libc::c_void); + #[repr(C)] struct hoedown_renderer { opaque: *mut hoedown_html_renderer_state, - blockcode: Option, + blockcode: Option, blockquote: Option, blockhtml: Option, - header: Option, + header: Option, other: [libc::size_t, ..28], } @@ -281,8 +285,8 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result { toc_builder: if print_toc {Some(TocBuilder::new())} else {None} }; (*(*renderer).opaque).opaque = &mut opaque as *mut _ as *mut libc::c_void; - (*renderer).blockcode = Some(block); - (*renderer).header = Some(header); + (*renderer).blockcode = Some(block as blockcodefn); + (*renderer).header = Some(header as headerfn); let document = hoedown_document_new(renderer, HOEDOWN_EXTENSIONS, 16); hoedown_document_render(document, ob, s.as_ptr(), @@ -354,8 +358,8 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector) { unsafe { let ob = hoedown_buffer_new(DEF_OUNIT); let renderer = hoedown_html_renderer_new(0, 0); - (*renderer).blockcode = Some(block); - (*renderer).header = Some(header); + (*renderer).blockcode = Some(block as blockcodefn); + (*renderer).header = Some(header as headerfn); (*(*renderer).opaque).opaque = tests as *mut _ as *mut libc::c_void; let document = hoedown_document_new(renderer, HOEDOWN_EXTENSIONS, 16); diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 8149864afd405..dc9fd28934470 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -838,8 +838,9 @@ impl, V, S, H: Hasher> HashMap { /// } /// ``` #[unstable = "matches collection reform specification, waiting for dust to settle"] - pub fn keys(&self) -> Keys { + pub fn keys<'a>(&'a self) -> Keys<'a, K, V> { fn first((a, _): (A, B)) -> A { a } + let first: fn((&'a K,&'a V)) -> &'a K = first; // coerce to fn ptr Keys { inner: self.iter().map(first) } } @@ -862,8 +863,9 @@ impl, V, S, H: Hasher> HashMap { /// } /// ``` #[unstable = "matches collection reform specification, waiting for dust to settle"] - pub fn values(&self) -> Values { + pub fn values<'a>(&'a self) -> Values<'a, K, V> { fn second((_, b): (A, B)) -> B { b } + let second: fn((&'a K,&'a V)) -> &'a V = second; // coerce to fn ptr Values { inner: self.iter().map(second) } } @@ -938,6 +940,7 @@ impl, V, S, H: Hasher> HashMap { #[unstable = "matches collection reform specification, waiting for dust to settle"] pub fn into_iter(self) -> MoveEntries { fn last_two((_, b, c): (A, B, C)) -> (B, C) { (b, c) } + let last_two: fn((SafeHash, K, V)) -> (K, V) = last_two; MoveEntries { inner: self.table.into_iter().map(last_two) @@ -1007,6 +1010,7 @@ impl, V, S, H: Hasher> HashMap { #[unstable = "matches collection reform specification, waiting for dust to settle"] pub fn drain(&mut self) -> Drain { fn last_two((_, b, c): (A, B, C)) -> (B, C) { (b, c) } + let last_two: fn((SafeHash, K, V)) -> (K, V) = last_two; // coerce to fn pointer Drain { inner: self.table.drain().map(last_two), diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index f587669d3dacd..15ac3394d4176 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -277,6 +277,7 @@ impl, S, H: Hasher> HashSet { #[unstable = "matches collection reform specification, waiting for dust to settle"] pub fn into_iter(self) -> IntoIter { fn first((a, _): (A, B)) -> A { a } + let first: fn((T, ())) -> T = first; IntoIter { iter: self.map.into_iter().map(first) } } @@ -419,6 +420,8 @@ impl, S, H: Hasher> HashSet { #[unstable = "matches collection reform specification, waiting for dust to settle"] pub fn drain(&mut self) -> Drain { fn first((a, _): (A, B)) -> A { a } + let first: fn((T, ())) -> T = first; // coerce to fn pointer + Drain { iter: self.map.drain().map(first) } } diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs index 88907951673d1..0808b2a4f4258 100644 --- a/src/libstd/path/posix.rs +++ b/src/libstd/path/posix.rs @@ -390,6 +390,7 @@ impl Path { let v = if self.repr[0] == SEP_BYTE { self.repr[1..] } else { self.repr.as_slice() }; + let is_sep_byte: fn(&u8) -> bool = is_sep_byte; // coerce to fn ptr let mut ret = v.split(is_sep_byte); if v.is_empty() { // consume the empty "" component @@ -401,7 +402,8 @@ impl Path { /// Returns an iterator that yields each component of the path as Option<&str>. /// See components() for details. pub fn str_components<'a>(&'a self) -> StrComponents<'a> { - self.components().map(str::from_utf8) + let from_utf8: fn(&[u8]) -> Option<&str> = str::from_utf8; // coerce to fn ptr + self.components().map(from_utf8) } } diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs index c2c17103554ce..4b8fb7fad6a38 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -655,7 +655,8 @@ impl Path { None if repr.as_bytes()[0] == SEP_BYTE => repr.slice_from(1), None => repr }; - let ret = s.split_terminator(SEP).map(Some); + let some: fn(&'a str) -> Option<&'a str> = Some; // coerce to fn ptr + let ret = s.split_terminator(SEP).map(some); ret } @@ -666,6 +667,7 @@ impl Path { #![inline] x.unwrap().as_bytes() } + let convert: for<'b> fn(Option<&'b str>) -> &'b [u8] = convert; // coerce to fn ptr self.str_components().map(convert) } @@ -829,8 +831,12 @@ impl Path { let s = if self.has_nonsemantic_trailing_slash() { self.repr.slice_to(self.repr.len()-1) } else { self.repr.as_slice() }; - let idx = s.rfind(if !prefix_is_verbatim(self.prefix) { is_sep } - else { is_sep_verbatim }); + let sep_test: fn(char) -> bool = if !prefix_is_verbatim(self.prefix) { + is_sep + } else { + is_sep_verbatim + }; + let idx = s.rfind(sep_test); let prefixlen = self.prefix_len(); self.sepidx = idx.and_then(|x| if x < prefixlen { None } else { Some(x) }); } @@ -1048,7 +1054,11 @@ fn parse_prefix<'a>(mut path: &'a str) -> Option { // None result means the string didn't need normalizing fn normalize_helper<'a>(s: &'a str, prefix: Option) -> (bool, Option>) { - let f = if !prefix_is_verbatim(prefix) { is_sep } else { is_sep_verbatim }; + let f: fn(char) -> bool = if !prefix_is_verbatim(prefix) { + is_sep + } else { + is_sep_verbatim + }; let is_abs = s.len() > prefix_len(prefix) && f(s.char_at(prefix_len(prefix))); let s_ = s.slice_from(prefix_len(prefix)); let s_ = if is_abs { s_.slice_from(1) } else { s_ }; diff --git a/src/libstd/thread_local/mod.rs b/src/libstd/thread_local/mod.rs index 4c33d1c418d96..04718dcc6ae3b 100644 --- a/src/libstd/thread_local/mod.rs +++ b/src/libstd/thread_local/mod.rs @@ -189,11 +189,12 @@ macro_rules! __thread_local_inner { } }; - #[cfg(not(any(target_os = "macos", target_os = "linux")))] + #[cfg(all(stage0, not(any(target_os = "macos", target_os = "linux"))))] const INIT: ::std::thread_local::KeyInner<$t> = { unsafe extern fn __destroy(ptr: *mut u8) { ::std::thread_local::destroy_value::<$t>(ptr); } + ::std::thread_local::KeyInner { inner: ::std::cell::UnsafeCell { value: $init }, os: ::std::thread_local::OsStaticKey { @@ -203,6 +204,21 @@ macro_rules! __thread_local_inner { } }; + #[cfg(all(not(stage0), not(any(target_os = "macos", target_os = "linux"))))] + const INIT: ::std::thread_local::KeyInner<$t> = { + unsafe extern fn __destroy(ptr: *mut u8) { + ::std::thread_local::destroy_value::<$t>(ptr); + } + + ::std::thread_local::KeyInner { + inner: ::std::cell::UnsafeCell { value: $init }, + os: ::std::thread_local::OsStaticKey { + inner: ::std::thread_local::OS_INIT_INNER, + dtor: ::std::option::Option::Some(__destroy as unsafe extern fn(*mut u8)), + }, + } + }; + INIT }); } @@ -323,6 +339,12 @@ mod imp { // *should* be the case that this loop always terminates because we // provide the guarantee that a TLS key cannot be set after it is // flagged for destruction. + #[cfg(not(stage0))] + static DTORS: os::StaticKey = os::StaticKey { + inner: os::INIT_INNER, + dtor: Some(run_dtors as unsafe extern "C" fn(*mut u8)), + }; + #[cfg(stage0)] static DTORS: os::StaticKey = os::StaticKey { inner: os::INIT_INNER, dtor: Some(run_dtors), diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index aefbb2a1feab3..f76c350902d7d 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -50,14 +50,16 @@ pub trait ItemDecorator { push: |P|); } -impl ItemDecorator for fn(&mut ExtCtxt, Span, &ast::MetaItem, &ast::Item, |P|) { +impl ItemDecorator for F + where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, &ast::Item, |P|) +{ fn expand(&self, ecx: &mut ExtCtxt, sp: Span, meta_item: &ast::MetaItem, item: &ast::Item, push: |P|) { - self.clone()(ecx, sp, meta_item, item, push) + (*self)(ecx, sp, meta_item, item, push) } } @@ -70,14 +72,16 @@ pub trait ItemModifier { -> P; } -impl ItemModifier for fn(&mut ExtCtxt, Span, &ast::MetaItem, P) -> P { +impl ItemModifier for F + where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, P) -> P +{ fn expand(&self, ecx: &mut ExtCtxt, span: Span, meta_item: &ast::MetaItem, item: P) -> P { - self.clone()(ecx, span, meta_item, item) + (*self)(ecx, span, meta_item, item) } } @@ -93,13 +97,15 @@ pub trait TTMacroExpander { pub type MacroExpanderFn = for<'cx> fn(&'cx mut ExtCtxt, Span, &[ast::TokenTree]) -> Box; -impl TTMacroExpander for MacroExpanderFn { +impl TTMacroExpander for F + where F : for<'cx> Fn(&'cx mut ExtCtxt, Span, &[ast::TokenTree]) -> Box +{ fn expand<'cx>(&self, ecx: &'cx mut ExtCtxt, span: Span, token_tree: &[ast::TokenTree]) -> Box { - self.clone()(ecx, span, token_tree) + (*self)(ecx, span, token_tree) } } @@ -115,14 +121,18 @@ pub trait IdentMacroExpander { pub type IdentMacroExpanderFn = for<'cx> fn(&'cx mut ExtCtxt, Span, ast::Ident, Vec) -> Box; -impl IdentMacroExpander for IdentMacroExpanderFn { +impl IdentMacroExpander for F + where F : for<'cx> Fn(&'cx mut ExtCtxt, Span, ast::Ident, + Vec) -> Box +{ fn expand<'cx>(&self, cx: &'cx mut ExtCtxt, sp: Span, ident: ast::Ident, token_tree: Vec ) - -> Box { - self.clone()(cx, sp, ident, token_tree) + -> Box + { + (*self)(cx, sp, ident, token_tree) } } diff --git a/src/libunicode/u_str.rs b/src/libunicode/u_str.rs index 5e98109c432aa..88d87717ff3e8 100644 --- a/src/libunicode/u_str.rs +++ b/src/libunicode/u_str.rs @@ -143,7 +143,10 @@ impl UnicodeStrPrelude for str { #[inline] fn words(&self) -> Words { fn is_not_empty(s: &&str) -> bool { !s.is_empty() } + let is_not_empty: fn(&&str) -> bool = is_not_empty; // coerce to fn pointer + fn is_whitespace(c: char) -> bool { c.is_whitespace() } + let is_whitespace: fn(char) -> bool = is_whitespace; // coerce to fn pointer self.split(is_whitespace).filter(is_not_empty) } diff --git a/src/test/compile-fail/borrowck-autoref-3261.rs b/src/test/compile-fail/borrowck-autoref-3261.rs index 8c6e76e774619..1b4e5891f941d 100644 --- a/src/test/compile-fail/borrowck-autoref-3261.rs +++ b/src/test/compile-fail/borrowck-autoref-3261.rs @@ -20,7 +20,7 @@ impl X { } fn main() { - let mut x = X(Either::Right(main)); + let mut x = X(Either::Right(main as fn())); (&mut x).with( |opt| { //~ ERROR cannot borrow `x` as mutable more than once at a time match opt { diff --git a/src/test/compile-fail/cast-to-bare-fn.rs b/src/test/compile-fail/cast-to-bare-fn.rs index 10a829fd79455..1db813292b012 100644 --- a/src/test/compile-fail/cast-to-bare-fn.rs +++ b/src/test/compile-fail/cast-to-bare-fn.rs @@ -13,7 +13,7 @@ fn foo(_x: int) { } fn main() { let v: u64 = 5; let x = foo as extern "C" fn() -> int; - //~^ ERROR non-scalar cast + //~^ ERROR mismatched types let y = v as extern "Rust" fn(int) -> (int, int); //~^ ERROR non-scalar cast y(x()); diff --git a/src/test/compile-fail/coerce-bare-fn-to-closure-and-proc.rs b/src/test/compile-fail/coerce-bare-fn-to-closure-and-proc.rs index 27e339180a6cf..52f4c4749e224 100644 --- a/src/test/compile-fail/coerce-bare-fn-to-closure-and-proc.rs +++ b/src/test/compile-fail/coerce-bare-fn-to-closure-and-proc.rs @@ -8,12 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Test that coercions from fn item types are ok, but not fn pointer +// types to closures/procs are not allowed. + fn foo() {} -fn main() { +fn fn_item_type() { let f = foo; let f_closure: || = f; - //~^ ERROR: cannot coerce non-statically resolved bare fn to closure - //~^^ HELP: consider embedding the function in a closure } + +fn fn_pointer_type() { + let f = foo as fn(); + let f_closure: || = f; + //~^ ERROR: mismatched types +} + +fn main() { } diff --git a/src/test/compile-fail/fn-item-type.rs b/src/test/compile-fail/fn-item-type.rs new file mode 100644 index 0000000000000..dd4a24bfb2fdc --- /dev/null +++ b/src/test/compile-fail/fn-item-type.rs @@ -0,0 +1,25 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that the types of distinct fn items are not compatible by +// default. See also `run-pass/fn-item-type-*.rs`. + +fn foo(x: int) -> int { x * 2 } +fn bar(x: int) -> int { x * 4 } + +fn eq(x: T, y: T) { } + +fn main() { + let f = if true { foo } else { bar }; + //~^ ERROR expected fn item, found a different fn item + + eq(foo, bar); + //~^ ERROR expected fn item, found a different fn item +} diff --git a/src/test/compile-fail/issue-10764.rs b/src/test/compile-fail/issue-10764.rs index 0733744b65210..cd4ec495556c5 100644 --- a/src/test/compile-fail/issue-10764.rs +++ b/src/test/compile-fail/issue-10764.rs @@ -12,4 +12,4 @@ fn f(_: extern "Rust" fn()) {} extern fn bar() {} fn main() { f(bar) } -//~^ ERROR: expected `fn()`, found `extern "C" fn()` +//~^ ERROR mismatched types diff --git a/src/test/compile-fail/issue-9575.rs b/src/test/compile-fail/issue-9575.rs index aa3d9d9fef080..6e8f7ffb68da4 100644 --- a/src/test/compile-fail/issue-9575.rs +++ b/src/test/compile-fail/issue-9575.rs @@ -10,6 +10,6 @@ #[start] fn start(argc: int, argv: *const *const u8, crate_map: *const u8) -> int { - //~^ ERROR start function expects type: `fn(int, *const *const u8) -> int` + //~^ ERROR incorrect number of function parameters 0 } diff --git a/src/test/compile-fail/region-lifetime-bounds-on-fns-where-clause.rs b/src/test/compile-fail/region-lifetime-bounds-on-fns-where-clause.rs index 381144f2599c1..3e6a95b04f743 100644 --- a/src/test/compile-fail/region-lifetime-bounds-on-fns-where-clause.rs +++ b/src/test/compile-fail/region-lifetime-bounds-on-fns-where-clause.rs @@ -15,7 +15,7 @@ fn a<'a, 'b>(x: &mut &'a int, y: &mut &'b int) where 'b: 'a { fn b<'a, 'b>(x: &mut &'a int, y: &mut &'b int) { // Illegal now because there is no `'b:'a` declaration. - *x = *y; //~ ERROR mismatched types + *x = *y; //~ ERROR cannot infer } fn c<'a,'b>(x: &mut &'a int, y: &mut &'b int) { diff --git a/src/test/compile-fail/region-multiple-lifetime-bounds-on-fns-where-clause.rs b/src/test/compile-fail/region-multiple-lifetime-bounds-on-fns-where-clause.rs index a03911e1d0e18..2d635e9fc2718 100644 --- a/src/test/compile-fail/region-multiple-lifetime-bounds-on-fns-where-clause.rs +++ b/src/test/compile-fail/region-multiple-lifetime-bounds-on-fns-where-clause.rs @@ -16,8 +16,8 @@ fn a<'a, 'b, 'c>(x: &mut &'a int, y: &mut &'b int, z: &mut &'c int) where 'b: 'a fn b<'a, 'b, 'c>(x: &mut &'a int, y: &mut &'b int, z: &mut &'c int) { // Illegal now because there is no `'b:'a` declaration. - *x = *y; //~ ERROR mismatched types - *z = *y; //~ ERROR mismatched types + *x = *y; //~ ERROR cannot infer + *z = *y; //~ ERROR cannot infer } fn c<'a,'b, 'c>(x: &mut &'a int, y: &mut &'b int, z: &mut &'c int) { diff --git a/src/test/compile-fail/regions-lifetime-bounds-on-fns.rs b/src/test/compile-fail/regions-lifetime-bounds-on-fns.rs index 773d6e2c70365..4a42728da6f58 100644 --- a/src/test/compile-fail/regions-lifetime-bounds-on-fns.rs +++ b/src/test/compile-fail/regions-lifetime-bounds-on-fns.rs @@ -15,7 +15,7 @@ fn a<'a, 'b:'a>(x: &mut &'a int, y: &mut &'b int) { fn b<'a, 'b>(x: &mut &'a int, y: &mut &'b int) { // Illegal now because there is no `'b:'a` declaration. - *x = *y; //~ ERROR mismatched types + *x = *y; //~ ERROR cannot infer } fn c<'a,'b>(x: &mut &'a int, y: &mut &'b int) { diff --git a/src/test/compile-fail/regions-nested-fns.rs b/src/test/compile-fail/regions-nested-fns.rs index cf0b615bb01ab..f4654367970d1 100644 --- a/src/test/compile-fail/regions-nested-fns.rs +++ b/src/test/compile-fail/regions-nested-fns.rs @@ -12,10 +12,10 @@ fn ignore(t: T) {} fn nested<'x>(x: &'x int) { let y = 3; - let mut ay = &y; //~ ERROR cannot infer + let mut ay = &y; ignore::< for<'z>|&'z int|>(|z| { - ay = x; + ay = x; //~ ERROR cannot infer ay = &y; ay = z; }); diff --git a/src/test/compile-fail/static-reference-to-fn-1.rs b/src/test/compile-fail/static-reference-to-fn-1.rs index c0d430908a137..bce397c47932f 100644 --- a/src/test/compile-fail/static-reference-to-fn-1.rs +++ b/src/test/compile-fail/static-reference-to-fn-1.rs @@ -24,7 +24,7 @@ fn foo() -> Option { fn create() -> A<'static> { A { - func: &foo, //~ ERROR borrowed value does not live long enough + func: &foo, //~ ERROR mismatched types } } diff --git a/src/test/compile-fail/static-reference-to-fn-2.rs b/src/test/compile-fail/static-reference-to-fn-2.rs index 3a0f0a193cfe1..d7255c3ba0694 100644 --- a/src/test/compile-fail/static-reference-to-fn-2.rs +++ b/src/test/compile-fail/static-reference-to-fn-2.rs @@ -9,9 +9,11 @@ // except according to those terms. struct StateMachineIter<'a> { - statefn: &'a fn(&mut StateMachineIter<'a>) -> Option<&'static str> + statefn: &'a StateMachineFunc<'a> } +type StateMachineFunc<'a> = fn(&mut StateMachineIter<'a>) -> Option<&'static str>; + impl<'a> Iterator<&'static str> for StateMachineIter<'a> { fn next(&mut self) -> Option<&'static str> { return (*self.statefn)(self); @@ -19,19 +21,19 @@ impl<'a> Iterator<&'static str> for StateMachineIter<'a> { } fn state1(self_: &mut StateMachineIter) -> Option<&'static str> { - self_.statefn = &state2; + self_.statefn = &(state2 as StateMachineFunc); //~^ ERROR borrowed value does not live long enough return Some("state1"); } fn state2(self_: &mut StateMachineIter) -> Option<(&'static str)> { - self_.statefn = &state3; + self_.statefn = &(state3 as StateMachineFunc); //~^ ERROR borrowed value does not live long enough return Some("state2"); } fn state3(self_: &mut StateMachineIter) -> Option<(&'static str)> { - self_.statefn = &finished; + self_.statefn = &(finished as StateMachineFunc); //~^ ERROR borrowed value does not live long enough return Some("state3"); } @@ -42,7 +44,7 @@ fn finished(_: &mut StateMachineIter) -> Option<(&'static str)> { fn state_iter() -> StateMachineIter<'static> { StateMachineIter { - statefn: &state1 //~ ERROR borrowed value does not live long enough + statefn: &(state1 as StateMachineFunc) //~ ERROR borrowed value does not live long enough } } diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp index 974af1e6f3e10..e4389cd69dd62 100644 --- a/src/test/pretty/issue-4264.pp +++ b/src/test/pretty/issue-4264.pp @@ -50,20 +50,20 @@ ((::std::fmt::format as - fn(&core::fmt::Arguments<'_>) -> collections::string::String)((&((::std::fmt::Arguments::new - as - fn(&[&str], &[core::fmt::Argument<'_>]) -> core::fmt::Arguments<'_>)((__STATIC_FMTSTR - as - &'static [&'static str]), - (&([] - as - [core::fmt::Argument<'_>; 0]) - as - &[core::fmt::Argument<'_>; 0])) - as - core::fmt::Arguments<'_>) - as - &core::fmt::Arguments<'_>)) + fn(&core::fmt::Arguments<'_>) -> collections::string::String {std::fmt::format})((&((::std::fmt::Arguments::new + as + fn(&[&str], &[core::fmt::Argument<'_>]) -> core::fmt::Arguments<'_> {core::fmt::Arguments<'a>::new})((__STATIC_FMTSTR + as + &'static [&'static str]), + (&([] + as + [core::fmt::Argument<'_>; 0]) + as + &[core::fmt::Argument<'_>; 0])) + as + core::fmt::Arguments<'_>) + as + &core::fmt::Arguments<'_>)) as collections::string::String) } } as collections::string::String); @@ -78,7 +78,8 @@ pub fn use_id() { let _ = ((id::<[int; (3u as uint)]> as - fn([int; 3]) -> [int; 3])(([(1 as int), (2 as int), (3 as int)] - as [int; 3])) as [int; 3]); + fn([int; 3]) -> [int; 3] {id})(([(1 as int), (2 as int), + (3 as int)] as [int; 3])) as + [int; 3]); } fn main() { } diff --git a/src/test/run-pass/const-extern-function.rs b/src/test/run-pass/const-extern-function.rs index be7c47dafc017..069ca6ecf49dd 100644 --- a/src/test/run-pass/const-extern-function.rs +++ b/src/test/run-pass/const-extern-function.rs @@ -18,6 +18,6 @@ struct S { } pub fn main() { - assert!(foopy == f); + assert!(foopy as extern "C" fn() == f); assert!(f == s.f); } diff --git a/src/test/run-pass/extern-compare-with-return-type.rs b/src/test/run-pass/extern-compare-with-return-type.rs index 057394b2624fe..3febff18704de 100644 --- a/src/test/run-pass/extern-compare-with-return-type.rs +++ b/src/test/run-pass/extern-compare-with-return-type.rs @@ -18,15 +18,17 @@ extern fn uintret() -> uint { 22 } extern fn uintvoidret(_x: uint) {} extern fn uintuintuintuintret(x: uint, y: uint, z: uint) -> uint { x+y+z } +type uintuintuintuintret = extern fn(uint,uint,uint) -> uint; pub fn main() { - assert!(voidret1 == voidret1); - assert!(voidret1 != voidret2); + assert!(voidret1 as extern fn() == voidret1 as extern fn()); + assert!(voidret1 as extern fn() != voidret2 as extern fn()); - assert!(uintret == uintret); + assert!(uintret as extern fn() -> uint == uintret as extern fn() -> uint); - assert!(uintvoidret == uintvoidret); + assert!(uintvoidret as extern fn(uint) == uintvoidret as extern fn(uint)); - assert!(uintuintuintuintret == uintuintuintuintret); + assert!(uintuintuintuintret as uintuintuintuintret == + uintuintuintuintret as uintuintuintuintret); } diff --git a/src/test/run-pass/fn-item-type-cast.rs b/src/test/run-pass/fn-item-type-cast.rs new file mode 100644 index 0000000000000..bfd02f5e27b0c --- /dev/null +++ b/src/test/run-pass/fn-item-type-cast.rs @@ -0,0 +1,28 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test explicit coercions from a fn item type to a fn pointer type. + +fn foo(x: int) -> int { x * 2 } +fn bar(x: int) -> int { x * 4 } +type IntMap = fn(int) -> int; + +fn eq(x: T, y: T) { } + +static TEST: Option = Some(foo as IntMap); + +fn main() { + let f = foo as IntMap; + + let f = if true { foo as IntMap } else { bar as IntMap }; + assert_eq!(f(4), 8); + + eq(foo as IntMap, bar as IntMap); +} diff --git a/src/test/run-pass/fn-item-type-coerce.rs b/src/test/run-pass/fn-item-type-coerce.rs new file mode 100644 index 0000000000000..8427a0f444621 --- /dev/null +++ b/src/test/run-pass/fn-item-type-coerce.rs @@ -0,0 +1,23 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test implicit coercions from a fn item type to a fn pointer type. + +fn foo(x: int) -> int { x * 2 } +fn bar(x: int) -> int { x * 4 } +type IntMap = fn(int) -> int; + +fn eq(x: T, y: T) { } + +fn main() { + let f: IntMap = foo; + + eq::(foo, bar); +} diff --git a/src/test/run-pass/issue-10767.rs b/src/test/run-pass/issue-10767.rs index a30eb8120eae1..d28950241874d 100644 --- a/src/test/run-pass/issue-10767.rs +++ b/src/test/run-pass/issue-10767.rs @@ -12,5 +12,5 @@ pub fn main() { fn f() { }; - let _: Box = box f; + let _: Box = box() (f as fn()); } diff --git a/src/test/run-pass/issue-15444.rs b/src/test/run-pass/issue-15444.rs index f5618c2c7a3c4..0f4978d78dd86 100644 --- a/src/test/run-pass/issue-15444.rs +++ b/src/test/run-pass/issue-15444.rs @@ -25,5 +25,6 @@ fn thing(a: int, b: int) -> int { } fn main() { + let thing: fn(int, int) -> int = thing; // coerce to fn type bar(&thing); }