mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-04 04:39:16 +00:00
rollup merge of #19891: nikomatsakis/unique-fn-types-3
Conflicts: src/libcore/str.rs src/librustc_trans/trans/closure.rs src/librustc_typeck/collect.rs src/libstd/path/posix.rs src/libstd/path/windows.rs
This commit is contained in:
commit
de11710d80
@ -1230,6 +1230,7 @@ impl<K, V> BTreeMap<K, V> {
|
|||||||
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
||||||
pub fn keys<'a>(&'a self) -> Keys<'a, K, V> {
|
pub fn keys<'a>(&'a self) -> Keys<'a, K, V> {
|
||||||
fn first<A, B>((a, _): (A, B)) -> A { a }
|
fn first<A, B>((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) }
|
Keys { inner: self.iter().map(first) }
|
||||||
}
|
}
|
||||||
@ -1251,6 +1252,7 @@ impl<K, V> BTreeMap<K, V> {
|
|||||||
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
||||||
pub fn values<'a>(&'a self) -> Values<'a, K, V> {
|
pub fn values<'a>(&'a self) -> Values<'a, K, V> {
|
||||||
fn second<A, B>((_, b): (A, B)) -> B { b }
|
fn second<A, B>((_, 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) }
|
Values { inner: self.iter().map(second) }
|
||||||
}
|
}
|
||||||
|
@ -126,6 +126,7 @@ impl<T> BTreeSet<T> {
|
|||||||
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
||||||
pub fn into_iter(self) -> IntoIter<T> {
|
pub fn into_iter(self) -> IntoIter<T> {
|
||||||
fn first<A, B>((a, _): (A, B)) -> A { a }
|
fn first<A, B>((a, _): (A, B)) -> A { a }
|
||||||
|
let first: fn((T, ())) -> T = first; // coerce to fn pointer
|
||||||
|
|
||||||
IntoIter { iter: self.map.into_iter().map(first) }
|
IntoIter { iter: self.map.into_iter().map(first) }
|
||||||
}
|
}
|
||||||
|
@ -144,6 +144,7 @@ impl<V> VecMap<V> {
|
|||||||
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
||||||
pub fn keys<'r>(&'r self) -> Keys<'r, V> {
|
pub fn keys<'r>(&'r self) -> Keys<'r, V> {
|
||||||
fn first<A, B>((a, _): (A, B)) -> A { a }
|
fn first<A, B>((a, _): (A, B)) -> A { a }
|
||||||
|
let first: fn((uint, &'r V)) -> uint = first; // coerce to fn pointer
|
||||||
|
|
||||||
Keys { iter: self.iter().map(first) }
|
Keys { iter: self.iter().map(first) }
|
||||||
}
|
}
|
||||||
@ -153,6 +154,7 @@ impl<V> VecMap<V> {
|
|||||||
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
||||||
pub fn values<'r>(&'r self) -> Values<'r, V> {
|
pub fn values<'r>(&'r self) -> Values<'r, V> {
|
||||||
fn second<A, B>((_, b): (A, B)) -> B { b }
|
fn second<A, B>((_, b): (A, B)) -> B { b }
|
||||||
|
let second: fn((uint, &'r V)) -> &'r V = second; // coerce to fn pointer
|
||||||
|
|
||||||
Values { iter: self.iter().map(second) }
|
Values { iter: self.iter().map(second) }
|
||||||
}
|
}
|
||||||
@ -239,6 +241,7 @@ impl<V> VecMap<V> {
|
|||||||
fn filter<A>((i, v): (uint, Option<A>)) -> Option<(uint, A)> {
|
fn filter<A>((i, v): (uint, Option<A>)) -> Option<(uint, A)> {
|
||||||
v.map(|v| (i, v))
|
v.map(|v| (i, v))
|
||||||
}
|
}
|
||||||
|
let filter: fn((uint, Option<V>)) -> Option<(uint, V)> = filter; // coerce to fn ptr
|
||||||
|
|
||||||
let values = replace(&mut self.v, vec!());
|
let values = replace(&mut self.v, vec!());
|
||||||
IntoIter { iter: values.into_iter().enumerate().filter_map(filter) }
|
IntoIter { iter: values.into_iter().enumerate().filter_map(filter) }
|
||||||
|
@ -2612,6 +2612,9 @@ pub fn iterate<T, F>(seed: T, f: F) -> Iterate<T, F> where
|
|||||||
val.clone()
|
val.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// coerce to a fn pointer
|
||||||
|
let next: fn(&mut IterateState<T,F>) -> Option<T> = next;
|
||||||
|
|
||||||
Unfold::new((f, Some(seed), true), next)
|
Unfold::new((f, Some(seed), true), next)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1310,6 +1310,7 @@ impl StrExt for str {
|
|||||||
else { line }
|
else { line }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let f: fn(&str) -> &str = f; // coerce to fn pointer
|
||||||
LinesAny { inner: self.lines().map(f) }
|
LinesAny { inner: self.lines().map(f) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -700,7 +700,7 @@ pub fn get_enum_variants<'tcx>(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::Nod
|
|||||||
item, tcx, cdata);
|
item, tcx, cdata);
|
||||||
let name = item_name(&*intr, item);
|
let name = item_name(&*intr, item);
|
||||||
let (ctor_ty, arg_tys, arg_names) = match ctor_ty.sty {
|
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),
|
(Some(ctor_ty), f.sig.0.inputs.clone(), None),
|
||||||
_ => { // Nullary or struct enum variant.
|
_ => { // Nullary or struct enum variant.
|
||||||
let mut arg_names = Vec::new();
|
let mut arg_names = Vec::new();
|
||||||
|
@ -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)));
|
return ty::mk_closure(st.tcx, parse_closure_ty(st, |x,y| conv(x,y)));
|
||||||
}
|
}
|
||||||
'F' => {
|
'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);
|
let pos = parse_hex(st);
|
||||||
|
@ -123,8 +123,13 @@ pub fn enc_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, t: Ty<'t
|
|||||||
mywrite!(w, "f");
|
mywrite!(w, "f");
|
||||||
enc_closure_ty(w, cx, &**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, "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);
|
enc_bare_fn_ty(w, cx, f);
|
||||||
}
|
}
|
||||||
ty::ty_infer(_) => {
|
ty::ty_infer(_) => {
|
||||||
|
@ -1007,14 +1007,21 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
|
|||||||
|
|
||||||
self.emit_enum("AutoAdjustment", |this| {
|
self.emit_enum("AutoAdjustment", |this| {
|
||||||
match *adj {
|
match *adj {
|
||||||
ty::AdjustAddEnv(store) => {
|
ty::AdjustAddEnv(def_id, store) => {
|
||||||
this.emit_enum_variant("AutoAddEnv", 0, 1, |this| {
|
this.emit_enum_variant("AdjustAddEnv", 0, 2, |this| {
|
||||||
this.emit_enum_variant_arg(0, |this| store.encode(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) => {
|
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.emit_enum_variant_arg(0,
|
||||||
|this| Ok(this.emit_auto_deref_ref(ecx, auto_deref_ref)))
|
|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| {
|
this.read_enum_variant(&variants, |this, i| {
|
||||||
Ok(match i {
|
Ok(match i {
|
||||||
0 => {
|
0 => {
|
||||||
|
let def_id: ast::DefId =
|
||||||
|
this.read_def_id(dcx);
|
||||||
let store: ty::TraitStore =
|
let store: ty::TraitStore =
|
||||||
this.read_enum_variant_arg(0, |this| Decodable::decode(this)).unwrap();
|
this.read_enum_variant_arg(0, |this| Decodable::decode(this)).unwrap();
|
||||||
|
|
||||||
ty::AdjustAddEnv(store.tr(dcx))
|
ty::AdjustAddEnv(def_id, store.tr(dcx))
|
||||||
}
|
}
|
||||||
1 => {
|
1 => {
|
||||||
|
let def_id: ast::DefId =
|
||||||
|
this.read_def_id(dcx);
|
||||||
|
|
||||||
|
ty::AdjustReifyFnPointer(def_id)
|
||||||
|
}
|
||||||
|
2 => {
|
||||||
let auto_deref_ref: ty::AutoDerefRef =
|
let auto_deref_ref: ty::AutoDerefRef =
|
||||||
this.read_enum_variant_arg(0,
|
this.read_enum_variant_arg(0,
|
||||||
|this| Ok(this.read_auto_deref_ref(dcx))).unwrap();
|
|this| Ok(this.read_auto_deref_ref(dcx))).unwrap();
|
||||||
|
@ -127,7 +127,11 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) -> bool {
|
|||||||
ast::ExprCast(ref from, _) => {
|
ast::ExprCast(ref from, _) => {
|
||||||
let toty = ty::expr_ty(v.tcx, e);
|
let toty = ty::expr_ty(v.tcx, e);
|
||||||
let fromty = ty::expr_ty(v.tcx, &**from);
|
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,
|
span_err!(v.tcx.sess, e.span, E0012,
|
||||||
"can not cast to `{}` in a constant expression",
|
"can not cast to `{}` in a constant expression",
|
||||||
ppaux::ty_to_string(v.tcx, toty));
|
ppaux::ty_to_string(v.tcx, toty));
|
||||||
|
@ -32,7 +32,7 @@ enum UnsafeContext {
|
|||||||
|
|
||||||
fn type_is_unsafe_function(ty: Ty) -> bool {
|
fn type_is_unsafe_function(ty: Ty) -> bool {
|
||||||
match ty.sty {
|
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,
|
ty::ty_closure(ref f) => f.unsafety == ast::Unsafety::Unsafe,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
@ -824,10 +824,12 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
|||||||
None => { }
|
None => { }
|
||||||
Some(adjustment) => {
|
Some(adjustment) => {
|
||||||
match *adjustment {
|
match *adjustment {
|
||||||
ty::AdjustAddEnv(..) => {
|
ty::AdjustAddEnv(..) |
|
||||||
// Creating a closure consumes the input and stores it
|
ty::AdjustReifyFnPointer(..) => {
|
||||||
// into the resulting rvalue.
|
// Creating a closure/fn-pointer consumes the
|
||||||
debug!("walk_adjustment(AutoAddEnv)");
|
// input and stores it into the resulting
|
||||||
|
// rvalue.
|
||||||
|
debug!("walk_adjustment(AutoAddEnv|AdjustReifyFnPointer)");
|
||||||
let cmt_unadjusted =
|
let cmt_unadjusted =
|
||||||
return_if_err!(self.mc.cat_expr_unadjusted(expr));
|
return_if_err!(self.mc.cat_expr_unadjusted(expr));
|
||||||
self.delegate_consume(expr.id, expr.span, cmt_unadjusted);
|
self.delegate_consume(expr.id, expr.span, cmt_unadjusted);
|
||||||
|
@ -83,7 +83,7 @@ pub fn simplify_type(tcx: &ty::ctxt,
|
|||||||
ty::ty_closure(ref f) => {
|
ty::ty_closure(ref f) => {
|
||||||
Some(FunctionSimplifiedType(f.sig.0.inputs.len()))
|
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()))
|
Some(FunctionSimplifiedType(f.sig.0.inputs.len()))
|
||||||
}
|
}
|
||||||
ty::ty_param(_) => {
|
ty::ty_param(_) => {
|
||||||
|
@ -84,10 +84,14 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||||||
let Coerce(ref v) = *self; v
|
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> {
|
pub fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
|
||||||
debug!("Coerce.tys({} => {})",
|
debug!("Coerce.tys({} => {})",
|
||||||
a.repr(self.get_ref().infcx.tcx),
|
a.repr(self.tcx()),
|
||||||
b.repr(self.get_ref().infcx.tcx));
|
b.repr(self.tcx()));
|
||||||
|
|
||||||
// Consider coercing the subtype to a DST
|
// Consider coercing the subtype to a DST
|
||||||
let unsize = self.unpack_actual_value(a, |a| {
|
let unsize = self.unpack_actual_value(a, |a| {
|
||||||
@ -170,13 +174,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||||||
|
|
||||||
self.unpack_actual_value(a, |a| {
|
self.unpack_actual_value(a, |a| {
|
||||||
match a.sty {
|
match a.sty {
|
||||||
ty::ty_bare_fn(ref a_f) => {
|
ty::ty_bare_fn(Some(a_def_id), ref a_f) => {
|
||||||
// Bare functions are coercible to any closure type.
|
// Function items are coercible to any closure
|
||||||
//
|
// type; function pointers are not (that would
|
||||||
// FIXME(#3320) this should go away and be
|
// require double indirection).
|
||||||
// replaced with proper inference, got a patch
|
self.coerce_from_fn_item(a, a_def_id, a_f, b)
|
||||||
// underway - ndm
|
|
||||||
self.coerce_from_bare_fn(a, a_f, b)
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// Otherwise, just use subtyping rules.
|
// Otherwise, just use subtyping rules.
|
||||||
@ -206,8 +208,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||||||
mutbl_b: ast::Mutability)
|
mutbl_b: ast::Mutability)
|
||||||
-> CoerceResult<'tcx> {
|
-> CoerceResult<'tcx> {
|
||||||
debug!("coerce_borrowed_pointer(a={}, b={})",
|
debug!("coerce_borrowed_pointer(a={}, b={})",
|
||||||
a.repr(self.get_ref().infcx.tcx),
|
a.repr(self.tcx()),
|
||||||
b.repr(self.get_ref().infcx.tcx));
|
b.repr(self.tcx()));
|
||||||
|
|
||||||
// If we have a parameter of type `&M T_a` and the value
|
// If we have a parameter of type `&M T_a` and the value
|
||||||
// provided is `expr`, we will be adding an implicit borrow,
|
// 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,
|
r_borrow,
|
||||||
mt {ty: inner_ty, mutbl: mutbl_b});
|
mt {ty: inner_ty, mutbl: mutbl_b});
|
||||||
try!(sub.tys(a_borrowed, b));
|
try!(sub.tys(a_borrowed, b));
|
||||||
@ -247,8 +249,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||||||
b: Ty<'tcx>)
|
b: Ty<'tcx>)
|
||||||
-> CoerceResult<'tcx> {
|
-> CoerceResult<'tcx> {
|
||||||
debug!("coerce_unsized(a={}, b={})",
|
debug!("coerce_unsized(a={}, b={})",
|
||||||
a.repr(self.get_ref().infcx.tcx),
|
a.repr(self.tcx()),
|
||||||
b.repr(self.get_ref().infcx.tcx));
|
b.repr(self.tcx()));
|
||||||
|
|
||||||
// Note, we want to avoid unnecessary unsizing. We don't want to coerce to
|
// 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
|
// 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 coercion = Coercion(self.get_ref().trace.clone());
|
||||||
let r_borrow = self.get_ref().infcx.next_region_var(coercion);
|
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,
|
r_borrow,
|
||||||
ty::mt{ty: ty, mutbl: mt_b.mutbl});
|
ty::mt{ty: ty, mutbl: mt_b.mutbl});
|
||||||
try!(self.get_ref().infcx.try(|_| sub.tys(ty, b)));
|
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);
|
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});
|
ty::mt{ty: ty, mutbl: mt_b.mutbl});
|
||||||
try!(self.get_ref().infcx.try(|_| sub.tys(ty, b)));
|
try!(self.get_ref().infcx.try(|_| sub.tys(ty, b)));
|
||||||
debug!("Success, coerced with AutoDerefRef(1, \
|
debug!("Success, coerced with AutoDerefRef(1, \
|
||||||
@ -311,7 +313,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||||||
self.unpack_actual_value(t_a, |a| {
|
self.unpack_actual_value(t_a, |a| {
|
||||||
match self.unsize_ty(t_a, a, t_b) {
|
match self.unsize_ty(t_a, a, t_b) {
|
||||||
Some((ty, kind)) => {
|
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)));
|
try!(self.get_ref().infcx.try(|_| sub.tys(ty, b)));
|
||||||
debug!("Success, coerced with AutoDerefRef(1, \
|
debug!("Success, coerced with AutoDerefRef(1, \
|
||||||
AutoUnsizeUniq({}))", kind);
|
AutoUnsizeUniq({}))", kind);
|
||||||
@ -336,9 +338,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||||||
a: Ty<'tcx>,
|
a: Ty<'tcx>,
|
||||||
ty_b: Ty<'tcx>)
|
ty_b: Ty<'tcx>)
|
||||||
-> Option<(Ty<'tcx>, ty::UnsizeKind<'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|
|
self.unpack_actual_value(ty_b, |b|
|
||||||
match (&a.sty, &b.sty) {
|
match (&a.sty, &b.sty) {
|
||||||
@ -412,7 +414,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||||||
b: Ty<'tcx>,
|
b: Ty<'tcx>,
|
||||||
b_mutbl: ast::Mutability) -> CoerceResult<'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={})",
|
debug!("coerce_borrowed_object(a={}, b={}, b_mutbl={})",
|
||||||
a.repr(tcx),
|
a.repr(tcx),
|
||||||
@ -431,7 +433,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||||||
b: Ty<'tcx>,
|
b: Ty<'tcx>,
|
||||||
b_mutbl: ast::Mutability) -> CoerceResult<'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={})",
|
debug!("coerce_unsafe_object(a={}, b={}, b_mutbl={})",
|
||||||
a.repr(tcx),
|
a.repr(tcx),
|
||||||
@ -451,7 +453,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||||||
F: FnOnce(Ty<'tcx>) -> Ty<'tcx>,
|
F: FnOnce(Ty<'tcx>) -> Ty<'tcx>,
|
||||||
G: FnOnce() -> ty::AutoRef<'tcx>,
|
G: FnOnce() -> ty::AutoRef<'tcx>,
|
||||||
{
|
{
|
||||||
let tcx = self.get_ref().infcx.tcx;
|
let tcx = self.tcx();
|
||||||
|
|
||||||
match a.sty {
|
match a.sty {
|
||||||
ty::ty_rptr(_, ty::mt{ty, mutbl}) => match ty.sty {
|
ty::ty_rptr(_, ty::mt{ty, mutbl}) => match ty.sty {
|
||||||
@ -480,12 +482,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||||||
b: Ty<'tcx>)
|
b: Ty<'tcx>)
|
||||||
-> CoerceResult<'tcx> {
|
-> CoerceResult<'tcx> {
|
||||||
debug!("coerce_borrowed_fn(a={}, b={})",
|
debug!("coerce_borrowed_fn(a={}, b={})",
|
||||||
a.repr(self.get_ref().infcx.tcx),
|
a.repr(self.tcx()),
|
||||||
b.repr(self.get_ref().infcx.tcx));
|
b.repr(self.tcx()));
|
||||||
|
|
||||||
match a.sty {
|
match a.sty {
|
||||||
ty::ty_bare_fn(ref f) => {
|
ty::ty_bare_fn(Some(a_def_id), ref f) => {
|
||||||
self.coerce_from_bare_fn(a, f, b)
|
self.coerce_from_fn_item(a, a_def_id, f, b)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
self.subtype(a, 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
|
fn coerce_from_fn_item(&self,
|
||||||
/// `proc`.
|
a: Ty<'tcx>,
|
||||||
fn coerce_from_bare_fn(&self, a: Ty<'tcx>, fn_ty_a: &ty::BareFnTy<'tcx>, b: Ty<'tcx>)
|
fn_def_id_a: ast::DefId,
|
||||||
|
fn_ty_a: &ty::BareFnTy<'tcx>,
|
||||||
|
b: Ty<'tcx>)
|
||||||
-> CoerceResult<'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| {
|
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={})",
|
match b.sty {
|
||||||
a.repr(self.get_ref().infcx.tcx), b.repr(self.get_ref().infcx.tcx));
|
ty::ty_closure(ref f) => {
|
||||||
|
|
||||||
if fn_ty_a.abi != abi::Rust || fn_ty_a.unsafety != ast::Unsafety::Normal {
|
if fn_ty_a.abi != abi::Rust || fn_ty_a.unsafety != ast::Unsafety::Normal {
|
||||||
return self.subtype(a, b);
|
return self.subtype(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
let fn_ty_b = match b.sty {
|
let fn_ty_b = (*f).clone();
|
||||||
ty::ty_closure(ref f) => (*f).clone(),
|
let adj = ty::AdjustAddEnv(fn_def_id_a, fn_ty_b.store);
|
||||||
_ => return self.subtype(a, b)
|
let a_closure = ty::mk_closure(self.tcx(),
|
||||||
};
|
|
||||||
|
|
||||||
let adj = ty::AdjustAddEnv(fn_ty_b.store);
|
|
||||||
let a_closure = ty::mk_closure(self.get_ref().infcx.tcx,
|
|
||||||
ty::ClosureTy {
|
ty::ClosureTy {
|
||||||
sig: fn_ty_a.sig.clone(),
|
sig: fn_ty_a.sig.clone(),
|
||||||
.. *fn_ty_b
|
.. *fn_ty_b
|
||||||
});
|
});
|
||||||
try!(self.subtype(a_closure, b));
|
try!(self.subtype(a_closure, b));
|
||||||
Ok(Some(adj))
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -528,8 +544,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||||||
mutbl_b: ast::Mutability)
|
mutbl_b: ast::Mutability)
|
||||||
-> CoerceResult<'tcx> {
|
-> CoerceResult<'tcx> {
|
||||||
debug!("coerce_unsafe_ptr(a={}, b={})",
|
debug!("coerce_unsafe_ptr(a={}, b={})",
|
||||||
a.repr(self.get_ref().infcx.tcx),
|
a.repr(self.tcx()),
|
||||||
b.repr(self.get_ref().infcx.tcx));
|
b.repr(self.tcx()));
|
||||||
|
|
||||||
let mt_a = match a.sty {
|
let mt_a = match a.sty {
|
||||||
ty::ty_rptr(_, mt) | ty::ty_ptr(mt) => mt,
|
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.
|
// 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));
|
try!(self.subtype(a_unsafe, b));
|
||||||
if !can_coerce_mutbls(mt_a.mutbl, mutbl_b) {
|
if !can_coerce_mutbls(mt_a.mutbl, mutbl_b) {
|
||||||
return Err(ty::terr_mutability);
|
return Err(ty::terr_mutability);
|
||||||
|
@ -568,10 +568,11 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(&ty::ty_bare_fn(ref a_fty), &ty::ty_bare_fn(ref b_fty)) => {
|
(&ty::ty_bare_fn(a_opt_def_id, ref a_fty), &ty::ty_bare_fn(b_opt_def_id, ref b_fty))
|
||||||
this.bare_fn_tys(a_fty, b_fty).and_then(|fty| {
|
if a_opt_def_id == b_opt_def_id =>
|
||||||
Ok(ty::mk_bare_fn(tcx, fty))
|
{
|
||||||
})
|
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)) => {
|
(&ty::ty_closure(ref a_fty), &ty::ty_closure(ref b_fty)) => {
|
||||||
|
@ -74,7 +74,7 @@ struct IntrinsicCheckingVisitor<'a, 'tcx: 'a> {
|
|||||||
impl<'a, 'tcx> IntrinsicCheckingVisitor<'a, 'tcx> {
|
impl<'a, 'tcx> IntrinsicCheckingVisitor<'a, 'tcx> {
|
||||||
fn def_id_is_transmute(&self, def_id: DefId) -> bool {
|
fn def_id_is_transmute(&self, def_id: DefId) -> bool {
|
||||||
let intrinsic = match ty::lookup_item_type(self.tcx, def_id).ty.sty {
|
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
|
_ => return false
|
||||||
};
|
};
|
||||||
if def_id.krate == ast::LOCAL_CRATE {
|
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) => {
|
DefFn(did, _) if self.def_id_is_transmute(did) => {
|
||||||
let typ = ty::node_id_to_type(self.tcx, expr.id);
|
let typ = ty::node_id_to_type(self.tcx, expr.id);
|
||||||
match typ.sty {
|
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 {
|
if let ty::FnConverging(to) = bare_fn_ty.sig.0.output {
|
||||||
let from = bare_fn_ty.sig.0.inputs[0];
|
let from = bare_fn_ty.sig.0.inputs[0];
|
||||||
self.check_transmute(expr.span, from, to, expr.id);
|
self.check_transmute(expr.span, from, to, expr.id);
|
||||||
|
@ -441,8 +441,8 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
|||||||
|
|
||||||
Some(adjustment) => {
|
Some(adjustment) => {
|
||||||
match *adjustment {
|
match *adjustment {
|
||||||
ty::AdjustAddEnv(..) => {
|
ty::AdjustAddEnv(..) | ty::AdjustReifyFnPointer(..) => {
|
||||||
debug!("cat_expr(AdjustAddEnv): {}",
|
debug!("cat_expr(AdjustAddEnv|AdjustReifyFnPointer): {}",
|
||||||
expr.repr(self.tcx()));
|
expr.repr(self.tcx()));
|
||||||
// Convert a bare fn to a closure by adding NULL env.
|
// Convert a bare fn to a closure by adding NULL env.
|
||||||
// Result is an rvalue.
|
// Result is an rvalue.
|
||||||
|
@ -795,7 +795,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// provide an impl, but only for suitable `fn` pointers
|
// 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,
|
unsafety: ast::Unsafety::Normal,
|
||||||
abi: abi::Rust,
|
abi: abi::Rust,
|
||||||
sig: ty::Binder(ty::FnSig {
|
sig: ty::Binder(ty::FnSig {
|
||||||
@ -984,7 +984,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
ty::ty_int(_) |
|
ty::ty_int(_) |
|
||||||
ty::ty_bool |
|
ty::ty_bool |
|
||||||
ty::ty_float(_) |
|
ty::ty_float(_) |
|
||||||
ty::ty_bare_fn(_) |
|
ty::ty_bare_fn(..) |
|
||||||
ty::ty_char => {
|
ty::ty_char => {
|
||||||
// safe for everything
|
// safe for everything
|
||||||
Ok(If(Vec::new()))
|
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 self_ty = self.infcx.shallow_resolve(obligation.self_ty());
|
||||||
let sig = match self_ty.sty {
|
let sig = match self_ty.sty {
|
||||||
ty::ty_bare_fn(ty::BareFnTy {
|
ty::ty_bare_fn(_, ty::BareFnTy {
|
||||||
unsafety: ast::Unsafety::Normal,
|
unsafety: ast::Unsafety::Normal,
|
||||||
abi: abi::Rust,
|
abi: abi::Rust,
|
||||||
ref sig
|
ref sig
|
||||||
|
@ -293,7 +293,8 @@ pub enum Variance {
|
|||||||
|
|
||||||
#[deriving(Clone, Show)]
|
#[deriving(Clone, Show)]
|
||||||
pub enum AutoAdjustment<'tcx> {
|
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>)
|
AdjustDerefRef(AutoDerefRef<'tcx>)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1245,11 +1246,17 @@ pub enum sty<'tcx> {
|
|||||||
ty_vec(Ty<'tcx>, Option<uint>), // Second field is length.
|
ty_vec(Ty<'tcx>, Option<uint>), // Second field is length.
|
||||||
ty_ptr(mt<'tcx>),
|
ty_ptr(mt<'tcx>),
|
||||||
ty_rptr(Region, 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_closure(Box<ClosureTy<'tcx>>),
|
||||||
ty_trait(Box<TyTrait<'tcx>>),
|
ty_trait(Box<TyTrait<'tcx>>),
|
||||||
ty_struct(DefId, Substs<'tcx>),
|
ty_struct(DefId, Substs<'tcx>),
|
||||||
|
|
||||||
ty_unboxed_closure(DefId, Region, Substs<'tcx>),
|
ty_unboxed_closure(DefId, Region, Substs<'tcx>),
|
||||||
|
|
||||||
ty_tup(Vec<Ty<'tcx>>),
|
ty_tup(Vec<Ty<'tcx>>),
|
||||||
|
|
||||||
ty_param(ParamTy), // type parameter
|
ty_param(ParamTy), // type parameter
|
||||||
@ -2181,7 +2188,7 @@ impl FlagComputation {
|
|||||||
self.add_tys(ts[]);
|
self.add_tys(ts[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
&ty_bare_fn(ref f) => {
|
&ty_bare_fn(_, ref f) => {
|
||||||
self.add_fn_sig(&f.sig);
|
self.add_fn_sig(&f.sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2342,15 +2349,19 @@ pub fn mk_closure<'tcx>(cx: &ctxt<'tcx>, fty: ClosureTy<'tcx>) -> Ty<'tcx> {
|
|||||||
mk_t(cx, ty_closure(box fty))
|
mk_t(cx, ty_closure(box fty))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mk_bare_fn<'tcx>(cx: &ctxt<'tcx>, fty: BareFnTy<'tcx>) -> Ty<'tcx> {
|
pub fn mk_bare_fn<'tcx>(cx: &ctxt<'tcx>,
|
||||||
mk_t(cx, ty_bare_fn(fty))
|
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>,
|
pub fn mk_ctor_fn<'tcx>(cx: &ctxt<'tcx>,
|
||||||
|
def_id: ast::DefId,
|
||||||
input_tys: &[Ty<'tcx>],
|
input_tys: &[Ty<'tcx>],
|
||||||
output: Ty<'tcx>) -> Ty<'tcx> {
|
output: Ty<'tcx>) -> Ty<'tcx> {
|
||||||
let input_args = input_tys.iter().map(|ty| *ty).collect();
|
let input_args = input_tys.iter().map(|ty| *ty).collect();
|
||||||
mk_bare_fn(cx,
|
mk_bare_fn(cx,
|
||||||
|
Some(def_id),
|
||||||
BareFnTy {
|
BareFnTy {
|
||||||
unsafety: ast::Unsafety::Normal,
|
unsafety: ast::Unsafety::Normal,
|
||||||
abi: abi::Rust,
|
abi: abi::Rust,
|
||||||
@ -2449,7 +2460,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_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)); }
|
for a in ft.sig.0.inputs.iter() { maybe_walk_ty(*a, |x| f(x)); }
|
||||||
if let ty::FnConverging(output) = ft.sig.0.output {
|
if let ty::FnConverging(output) = ft.sig.0.output {
|
||||||
maybe_walk_ty(output, f);
|
maybe_walk_ty(output, f);
|
||||||
@ -2932,7 +2943,7 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
|
|||||||
// Scalar and unique types are sendable, and durable
|
// Scalar and unique types are sendable, and durable
|
||||||
ty_infer(ty::FreshIntTy(_)) |
|
ty_infer(ty::FreshIntTy(_)) |
|
||||||
ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
|
ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
|
||||||
ty_bare_fn(_) | ty::ty_char => {
|
ty_bare_fn(..) | ty::ty_char => {
|
||||||
TC::None
|
TC::None
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3267,7 +3278,7 @@ pub fn is_instantiable<'tcx>(cx: &ctxt<'tcx>, r_ty: Ty<'tcx>) -> bool {
|
|||||||
ty_uint(_) |
|
ty_uint(_) |
|
||||||
ty_float(_) |
|
ty_float(_) |
|
||||||
ty_str |
|
ty_str |
|
||||||
ty_bare_fn(_) |
|
ty_bare_fn(..) |
|
||||||
ty_closure(_) |
|
ty_closure(_) |
|
||||||
ty_infer(_) |
|
ty_infer(_) |
|
||||||
ty_err |
|
ty_err |
|
||||||
@ -3563,6 +3574,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 {
|
pub fn type_is_fp(ty: Ty) -> bool {
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty_infer(FloatVar(_)) | ty_float(_) => true,
|
ty_infer(FloatVar(_)) | ty_float(_) => true,
|
||||||
@ -3795,7 +3813,7 @@ pub fn node_id_item_substs<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) -> ItemSubsts
|
|||||||
|
|
||||||
pub fn fn_is_variadic(fty: Ty) -> bool {
|
pub fn fn_is_variadic(fty: Ty) -> bool {
|
||||||
match fty.sty {
|
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,
|
ty_closure(ref f) => f.sig.0.variadic,
|
||||||
ref s => {
|
ref s => {
|
||||||
panic!("fn_is_variadic() called on non-fn type: {}", s)
|
panic!("fn_is_variadic() called on non-fn type: {}", s)
|
||||||
@ -3805,7 +3823,7 @@ pub fn fn_is_variadic(fty: Ty) -> bool {
|
|||||||
|
|
||||||
pub fn ty_fn_sig<'tcx>(fty: Ty<'tcx>) -> &'tcx PolyFnSig<'tcx> {
|
pub fn ty_fn_sig<'tcx>(fty: Ty<'tcx>) -> &'tcx PolyFnSig<'tcx> {
|
||||||
match fty.sty {
|
match fty.sty {
|
||||||
ty_bare_fn(ref f) => &f.sig,
|
ty_bare_fn(_, ref f) => &f.sig,
|
||||||
ty_closure(ref f) => &f.sig,
|
ty_closure(ref f) => &f.sig,
|
||||||
ref s => {
|
ref s => {
|
||||||
panic!("ty_fn_sig() called on non-fn type: {}", s)
|
panic!("ty_fn_sig() called on non-fn type: {}", s)
|
||||||
@ -3816,7 +3834,7 @@ pub fn ty_fn_sig<'tcx>(fty: Ty<'tcx>) -> &'tcx PolyFnSig<'tcx> {
|
|||||||
/// Returns the ABI of the given function.
|
/// Returns the ABI of the given function.
|
||||||
pub fn ty_fn_abi(fty: Ty) -> abi::Abi {
|
pub fn ty_fn_abi(fty: Ty) -> abi::Abi {
|
||||||
match fty.sty {
|
match fty.sty {
|
||||||
ty_bare_fn(ref f) => f.abi,
|
ty_bare_fn(_, ref f) => f.abi,
|
||||||
ty_closure(ref f) => f.abi,
|
ty_closure(ref f) => f.abi,
|
||||||
_ => panic!("ty_fn_abi() called on non-fn type"),
|
_ => panic!("ty_fn_abi() called on non-fn type"),
|
||||||
}
|
}
|
||||||
@ -3843,7 +3861,7 @@ pub fn ty_closure_store(fty: Ty) -> TraitStore {
|
|||||||
|
|
||||||
pub fn ty_fn_ret<'tcx>(fty: Ty<'tcx>) -> FnOutput<'tcx> {
|
pub fn ty_fn_ret<'tcx>(fty: Ty<'tcx>) -> FnOutput<'tcx> {
|
||||||
match fty.sty {
|
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,
|
ty_closure(ref f) => f.sig.0.output,
|
||||||
ref s => {
|
ref s => {
|
||||||
panic!("ty_fn_ret() called on non-fn type: {}", s)
|
panic!("ty_fn_ret() called on non-fn type: {}", s)
|
||||||
@ -3853,7 +3871,7 @@ pub fn ty_fn_ret<'tcx>(fty: Ty<'tcx>) -> FnOutput<'tcx> {
|
|||||||
|
|
||||||
pub fn is_fn_ty(fty: Ty) -> bool {
|
pub fn is_fn_ty(fty: Ty) -> bool {
|
||||||
match fty.sty {
|
match fty.sty {
|
||||||
ty_bare_fn(_) => true,
|
ty_bare_fn(..) => true,
|
||||||
ty_closure(_) => true,
|
ty_closure(_) => true,
|
||||||
_ => false
|
_ => false
|
||||||
}
|
}
|
||||||
@ -3978,9 +3996,9 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>,
|
|||||||
return match adjustment {
|
return match adjustment {
|
||||||
Some(adjustment) => {
|
Some(adjustment) => {
|
||||||
match *adjustment {
|
match *adjustment {
|
||||||
AdjustAddEnv(store) => {
|
AdjustAddEnv(_, store) => {
|
||||||
match unadjusted_ty.sty {
|
match unadjusted_ty.sty {
|
||||||
ty::ty_bare_fn(ref b) => {
|
ty::ty_bare_fn(Some(_), ref b) => {
|
||||||
let bounds = ty::ExistentialBounds {
|
let bounds = ty::ExistentialBounds {
|
||||||
region_bound: ReStatic,
|
region_bound: ReStatic,
|
||||||
builtin_bounds: all_builtin_bounds(),
|
builtin_bounds: all_builtin_bounds(),
|
||||||
@ -3997,7 +4015,21 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>,
|
|||||||
}
|
}
|
||||||
ref b => {
|
ref b => {
|
||||||
cx.sess.bug(
|
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)[]);
|
b)[]);
|
||||||
}
|
}
|
||||||
@ -4356,7 +4388,8 @@ pub fn ty_sort_string<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> String {
|
|||||||
ty_vec(_, None) => "slice".to_string(),
|
ty_vec(_, None) => "slice".to_string(),
|
||||||
ty_ptr(_) => "*-ptr".to_string(),
|
ty_ptr(_) => "*-ptr".to_string(),
|
||||||
ty_rptr(_, _) => "&-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_closure(_) => "fn".to_string(),
|
||||||
ty_trait(ref inner) => {
|
ty_trait(ref inner) => {
|
||||||
format!("trait {}", item_path_str(cx, inner.principal.def_id()))
|
format!("trait {}", item_path_str(cx, inner.principal.def_id()))
|
||||||
@ -4547,6 +4580,10 @@ pub fn note_and_explain_type_err(cx: &ctxt, err: &type_err) {
|
|||||||
"concrete lifetime that was found is ",
|
"concrete lifetime that was found is ",
|
||||||
conc_region, "");
|
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) => {
|
terr_regions_overly_polymorphic(_, conc_region) => {
|
||||||
note_and_explain_region(cx,
|
note_and_explain_region(cx,
|
||||||
"expected concrete lifetime is ",
|
"expected concrete lifetime is ",
|
||||||
@ -5887,8 +5924,9 @@ pub fn hash_crate_independent<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh) -
|
|||||||
region(state, r);
|
region(state, r);
|
||||||
mt(state, m);
|
mt(state, m);
|
||||||
}
|
}
|
||||||
ty_bare_fn(ref b) => {
|
ty_bare_fn(opt_def_id, ref b) => {
|
||||||
byte!(14);
|
byte!(14);
|
||||||
|
hash!(opt_def_id);
|
||||||
hash!(b.unsafety);
|
hash!(b.unsafety);
|
||||||
hash!(b.abi);
|
hash!(b.abi);
|
||||||
fn_sig(state, &b.sig);
|
fn_sig(state, &b.sig);
|
||||||
@ -6203,7 +6241,7 @@ pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec<ty::Region>,
|
|||||||
ty_str |
|
ty_str |
|
||||||
ty_vec(_, _) |
|
ty_vec(_, _) |
|
||||||
ty_ptr(_) |
|
ty_ptr(_) |
|
||||||
ty_bare_fn(_) |
|
ty_bare_fn(..) |
|
||||||
ty_tup(_) |
|
ty_tup(_) |
|
||||||
ty_param(_) |
|
ty_param(_) |
|
||||||
ty_infer(_) |
|
ty_infer(_) |
|
||||||
@ -6255,6 +6293,7 @@ impl<'tcx> AutoAdjustment<'tcx> {
|
|||||||
pub fn is_identity(&self) -> bool {
|
pub fn is_identity(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
AdjustAddEnv(..) => false,
|
AdjustAddEnv(..) => false,
|
||||||
|
AdjustReifyFnPointer(..) => false,
|
||||||
AdjustDerefRef(ref r) => r.is_identity(),
|
AdjustDerefRef(ref r) => r.is_identity(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6370,8 +6409,11 @@ impl DebruijnIndex {
|
|||||||
impl<'tcx> Repr<'tcx> for AutoAdjustment<'tcx> {
|
impl<'tcx> Repr<'tcx> for AutoAdjustment<'tcx> {
|
||||||
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
|
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
|
||||||
match *self {
|
match *self {
|
||||||
AdjustAddEnv(ref trait_store) => {
|
AdjustAddEnv(def_id, ref trait_store) => {
|
||||||
format!("AdjustAddEnv({})", trait_store)
|
format!("AdjustAddEnv({},{})", def_id.repr(tcx), trait_store)
|
||||||
|
}
|
||||||
|
AdjustReifyFnPointer(def_id) => {
|
||||||
|
format!("AdjustAddEnv({})", def_id.repr(tcx))
|
||||||
}
|
}
|
||||||
AdjustDerefRef(ref data) => {
|
AdjustDerefRef(ref data) => {
|
||||||
data.repr(tcx)
|
data.repr(tcx)
|
||||||
|
@ -538,8 +538,8 @@ pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
|
|||||||
ty::ty_tup(ref ts) => {
|
ty::ty_tup(ref ts) => {
|
||||||
ty::ty_tup(ts.fold_with(this))
|
ty::ty_tup(ts.fold_with(this))
|
||||||
}
|
}
|
||||||
ty::ty_bare_fn(ref f) => {
|
ty::ty_bare_fn(opt_def_id, ref f) => {
|
||||||
ty::ty_bare_fn(f.fold_with(this))
|
ty::ty_bare_fn(opt_def_id, f.fold_with(this))
|
||||||
}
|
}
|
||||||
ty::ty_closure(ref f) => {
|
ty::ty_closure(ref f) => {
|
||||||
ty::ty_closure(box f.fold_with(this))
|
ty::ty_closure(box f.fold_with(this))
|
||||||
|
@ -254,12 +254,14 @@ pub fn vec_map_to_string<T, F>(ts: &[T], f: F) -> String where
|
|||||||
|
|
||||||
pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String {
|
pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String {
|
||||||
fn bare_fn_to_string<'tcx>(cx: &ctxt<'tcx>,
|
fn bare_fn_to_string<'tcx>(cx: &ctxt<'tcx>,
|
||||||
|
opt_def_id: Option<ast::DefId>,
|
||||||
unsafety: ast::Unsafety,
|
unsafety: ast::Unsafety,
|
||||||
abi: abi::Abi,
|
abi: abi::Abi,
|
||||||
ident: Option<ast::Ident>,
|
ident: Option<ast::Ident>,
|
||||||
sig: &ty::PolyFnSig<'tcx>)
|
sig: &ty::PolyFnSig<'tcx>)
|
||||||
-> String {
|
-> String {
|
||||||
let mut s = String::new();
|
let mut s = String::new();
|
||||||
|
|
||||||
match unsafety {
|
match unsafety {
|
||||||
ast::Unsafety::Normal => {}
|
ast::Unsafety::Normal => {}
|
||||||
ast::Unsafety::Unsafe => {
|
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, "");
|
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
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -408,8 +420,8 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String {
|
|||||||
ty_closure(ref f) => {
|
ty_closure(ref f) => {
|
||||||
closure_to_string(cx, &**f)
|
closure_to_string(cx, &**f)
|
||||||
}
|
}
|
||||||
ty_bare_fn(ref f) => {
|
ty_bare_fn(opt_def_id, ref f) => {
|
||||||
bare_fn_to_string(cx, f.unsafety, f.abi, None, &f.sig)
|
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_infer(infer_ty) => infer_ty_to_string(cx, infer_ty),
|
||||||
ty_err => "[type error]".to_string(),
|
ty_err => "[type error]".to_string(),
|
||||||
|
@ -253,7 +253,18 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
|
|||||||
output_ty: Ty<'tcx>)
|
output_ty: Ty<'tcx>)
|
||||||
-> 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> {
|
pub fn t_nil(&self) -> Ty<'tcx> {
|
||||||
|
@ -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>,
|
pub fn decl_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||||
fn_ty: Ty<'tcx>, name: &str) -> ValueRef {
|
fn_ty: Ty<'tcx>, name: &str) -> ValueRef {
|
||||||
let (inputs, output, abi, env) = match fn_ty.sty {
|
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)
|
(f.sig.0.inputs.clone(), f.sig.0.output, f.abi, None)
|
||||||
}
|
}
|
||||||
ty::ty_closure(ref f) => {
|
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 class_ty = ty::lookup_item_type(tcx, parent_id).ty.subst(tcx, substs);
|
||||||
let llty = type_of_dtor(ccx, class_ty);
|
let llty = type_of_dtor(ccx, class_ty);
|
||||||
let dtor_ty = ty::mk_ctor_fn(ccx.tcx(),
|
let dtor_ty = ty::mk_ctor_fn(ccx.tcx(),
|
||||||
|
did,
|
||||||
&[glue::get_drop_glue_type(ccx, t)],
|
&[glue::get_drop_glue_type(ccx, t)],
|
||||||
ty::mk_nil(ccx.tcx()));
|
ty::mk_nil(ccx.tcx()));
|
||||||
get_extern_fn(ccx,
|
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 {
|
did: ast::DefId, t: Ty<'tcx>) -> ValueRef {
|
||||||
let name = csearch::get_symbol(&ccx.sess().cstore, did);
|
let name = csearch::get_symbol(&ccx.sess().cstore, did);
|
||||||
match t.sty {
|
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) {
|
match ccx.sess().target.target.adjust_abi(fn_ty.abi) {
|
||||||
Rust | RustCall => {
|
Rust | RustCall => {
|
||||||
get_extern_rust_fn(ccx, t, name[], did)
|
get_extern_rust_fn(ccx, t, name[], did)
|
||||||
@ -2014,7 +2015,7 @@ pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
|||||||
let tcx = ccx.tcx();
|
let tcx = ccx.tcx();
|
||||||
|
|
||||||
let result_ty = match ctor_ty.sty {
|
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(
|
_ => ccx.sess().bug(
|
||||||
format!("trans_enum_variant_constructor: \
|
format!("trans_enum_variant_constructor: \
|
||||||
unexpected ctor return type {}",
|
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 ctor_ty = ctor_ty.subst(ccx.tcx(), param_substs);
|
||||||
|
|
||||||
let result_ty = match ctor_ty.sty {
|
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(
|
_ => ccx.sess().bug(
|
||||||
format!("trans_enum_variant_or_tuple_like_struct: \
|
format!("trans_enum_variant_or_tuple_like_struct: \
|
||||||
unexpected ctor return type {}",
|
unexpected ctor return type {}",
|
||||||
@ -2421,7 +2422,7 @@ fn register_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||||||
node_type: Ty<'tcx>)
|
node_type: Ty<'tcx>)
|
||||||
-> ValueRef {
|
-> ValueRef {
|
||||||
match node_type.sty {
|
match node_type.sty {
|
||||||
ty::ty_bare_fn(ref f) => {
|
ty::ty_bare_fn(_, ref f) => {
|
||||||
assert!(f.abi == Rust || f.abi == RustCall);
|
assert!(f.abi == Rust || f.abi == RustCall);
|
||||||
}
|
}
|
||||||
_ => panic!("expected bare rust fn")
|
_ => 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 {
|
let (fn_sig, abi, has_env) = match fn_ty.sty {
|
||||||
ty::ty_closure(ref f) => (f.sig.clone(), f.abi, true),
|
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) => {
|
ty::ty_unboxed_closure(closure_did, _, ref substs) => {
|
||||||
let unboxed_closures = ccx.tcx().unboxed_closures.borrow();
|
let unboxed_closures = ccx.tcx().unboxed_closures.borrow();
|
||||||
let ref function_type = (*unboxed_closures)[closure_did]
|
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")
|
_ => 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]];
|
let mut inputs = vec![fn_sig.0.inputs[0]];
|
||||||
|
|
||||||
match fn_sig.0.inputs[1].sty {
|
match fn_sig.0.inputs[1].sty {
|
||||||
|
@ -37,7 +37,10 @@ impl BasicBlock {
|
|||||||
|
|
||||||
pub fn pred_iter(self) -> Preds {
|
pub fn pred_iter(self) -> Preds {
|
||||||
fn is_a_terminator_inst(user: &Value) -> bool { user.is_a_terminator_inst() }
|
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() }
|
fn get_parent(user: Value) -> BasicBlock { user.get_parent().unwrap() }
|
||||||
|
let get_parent: fn(Value) -> BasicBlock = get_parent;
|
||||||
|
|
||||||
self.as_value().user_iter()
|
self.as_value().user_iter()
|
||||||
.filter(is_a_terminator_inst)
|
.filter(is_a_terminator_inst)
|
||||||
|
@ -21,7 +21,8 @@ pub use self::CallArgs::*;
|
|||||||
use arena::TypedArena;
|
use arena::TypedArena;
|
||||||
use back::{abi,link};
|
use back::{abi,link};
|
||||||
use session;
|
use session;
|
||||||
use llvm::{ValueRef, get_param};
|
use llvm::{ValueRef};
|
||||||
|
use llvm::get_param;
|
||||||
use llvm;
|
use llvm;
|
||||||
use metadata::csearch;
|
use metadata::csearch;
|
||||||
use middle::def;
|
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 {
|
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
|
_ => false
|
||||||
} => {
|
} => {
|
||||||
let substs = node_id_substs(bcx, ExprId(ref_expr.id));
|
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`,
|
// 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.
|
// 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 {
|
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,
|
abi: synabi::Rust,
|
||||||
sig: ty::Binder(ty::FnSig { inputs: ref input_tys,
|
sig: ty::Binder(ty::FnSig { inputs: ref input_tys,
|
||||||
output: output_ty,
|
output: output_ty,
|
||||||
variadic: false })}) =>
|
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_input_ty = ty::mk_tup(tcx, input_tys.to_vec());
|
||||||
let tuple_fn_ty = ty::mk_bare_fn(tcx,
|
let tuple_fn_ty = ty::mk_bare_fn(tcx,
|
||||||
|
opt_def_id,
|
||||||
ty::BareFnTy { unsafety: ast::Unsafety::Normal,
|
ty::BareFnTy { unsafety: ast::Unsafety::Normal,
|
||||||
abi: synabi::RustCall,
|
abi: synabi::RustCall,
|
||||||
sig: ty::Binder(ty::FnSig {
|
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 mut bcx = callee.bcx;
|
||||||
|
|
||||||
let (abi, ret_ty) = match callee_ty.sty {
|
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),
|
ty::ty_closure(ref f) => (f.abi, f.sig.0.output),
|
||||||
_ => panic!("expected bare rust fn or closure in trans_call_inner")
|
_ => panic!("expected bare rust fn or closure in trans_call_inner")
|
||||||
};
|
};
|
||||||
|
@ -13,7 +13,6 @@ pub use self::ClosureKind::*;
|
|||||||
use back::abi;
|
use back::abi;
|
||||||
use back::link::mangle_internal_name_by_path_and_seq;
|
use back::link::mangle_internal_name_by_path_and_seq;
|
||||||
use llvm::ValueRef;
|
use llvm::ValueRef;
|
||||||
use middle::def;
|
|
||||||
use middle::mem_categorization::Typer;
|
use middle::mem_categorization::Typer;
|
||||||
use trans::adt;
|
use trans::adt;
|
||||||
use trans::base::*;
|
use trans::base::*;
|
||||||
@ -603,7 +602,7 @@ pub fn trans_unboxed_closure<'blk, 'tcx>(
|
|||||||
|
|
||||||
pub fn get_wrapper_for_bare_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
pub fn get_wrapper_for_bare_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||||
closure_ty: Ty<'tcx>,
|
closure_ty: Ty<'tcx>,
|
||||||
def: def::Def,
|
def_id: ast::DefId,
|
||||||
fn_ptr: ValueRef,
|
fn_ptr: ValueRef,
|
||||||
is_local: bool) -> ValueRef {
|
is_local: bool) -> ValueRef {
|
||||||
|
|
||||||
@ -697,11 +696,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>,
|
pub fn make_closure_from_bare_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||||
closure_ty: Ty<'tcx>,
|
closure_ty: Ty<'tcx>,
|
||||||
def: def::Def,
|
def_id: ast::DefId,
|
||||||
fn_ptr: ValueRef)
|
fn_ptr: ValueRef)
|
||||||
-> DatumBlock<'blk, 'tcx, Expr> {
|
-> DatumBlock<'blk, 'tcx, Expr> {
|
||||||
let scratch = rvalue_scratch_datum(bcx, closure_ty, "__adjust");
|
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())));
|
fill_fn_pair(bcx, scratch.val, wrapper, C_null(Type::i8p(bcx.ccx())));
|
||||||
|
|
||||||
DatumBlock::new(bcx, scratch.to_expr_datum())
|
DatumBlock::new(bcx, scratch.to_expr_datum())
|
||||||
|
@ -190,21 +190,24 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, e: &ast::Expr)
|
|||||||
None => { }
|
None => { }
|
||||||
Some(adj) => {
|
Some(adj) => {
|
||||||
match adj {
|
match adj {
|
||||||
ty::AdjustAddEnv(ty::RegionTraitStore(ty::ReStatic, _)) => {
|
ty::AdjustAddEnv(def_id, ty::RegionTraitStore(ty::ReStatic, _)) => {
|
||||||
let def = ty::resolve_expr(cx.tcx(), e);
|
|
||||||
let wrapper = closure::get_wrapper_for_bare_fn(cx,
|
let wrapper = closure::get_wrapper_for_bare_fn(cx,
|
||||||
ety_adjusted,
|
ety_adjusted,
|
||||||
def,
|
def_id,
|
||||||
llconst,
|
llconst,
|
||||||
true);
|
true);
|
||||||
llconst = C_struct(cx, &[wrapper, C_null(Type::i8p(cx))], false)
|
llconst = C_struct(cx, &[wrapper, C_null(Type::i8p(cx))], false)
|
||||||
}
|
}
|
||||||
ty::AdjustAddEnv(store) => {
|
ty::AdjustAddEnv(_, store) => {
|
||||||
cx.sess()
|
cx.sess()
|
||||||
.span_bug(e.span,
|
.span_bug(e.span,
|
||||||
format!("unexpected static function: {}",
|
format!("unexpected static function: {}",
|
||||||
store)[])
|
store)[])
|
||||||
}
|
}
|
||||||
|
ty::AdjustReifyFnPointer(_def_id) => {
|
||||||
|
// FIXME(#19925) once fn item types are
|
||||||
|
// zero-sized, we'll need to do something here
|
||||||
|
}
|
||||||
ty::AdjustDerefRef(ref adj) => {
|
ty::AdjustDerefRef(ref adj) => {
|
||||||
let mut ty = ety;
|
let mut ty = ety;
|
||||||
// Save the last autoderef in case we can avoid it.
|
// Save the last autoderef in case we can avoid it.
|
||||||
|
@ -430,7 +430,7 @@ impl<'tcx> TypeMap<'tcx> {
|
|||||||
trait_data.principal.substs(),
|
trait_data.principal.substs(),
|
||||||
&mut unique_type_id);
|
&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 {
|
if unsafety == ast::Unsafety::Unsafe {
|
||||||
unique_type_id.push_str("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)
|
subroutine_type_metadata(cx, unique_type_id, &barefnty.sig, usage_site_span)
|
||||||
}
|
}
|
||||||
ty::ty_closure(ref closurety) => {
|
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_item_name(cx, trait_data.principal.def_id(), false, output);
|
||||||
push_type_params(cx, trait_data.principal.substs(), 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 {
|
if unsafety == ast::Unsafety::Unsafe {
|
||||||
output.push_str("unsafe ");
|
output.push_str("unsafe ");
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ use trans::inline;
|
|||||||
use trans::tvec;
|
use trans::tvec;
|
||||||
use trans::type_of;
|
use trans::type_of;
|
||||||
use middle::ty::{struct_fields, tup_fields};
|
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::{AutoPtr};
|
||||||
use middle::ty::{mod, Ty};
|
use middle::ty::{mod, Ty};
|
||||||
use middle::ty::MethodCall;
|
use middle::ty::MethodCall;
|
||||||
@ -177,8 +177,12 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||||||
datum.to_string(bcx.ccx()),
|
datum.to_string(bcx.ccx()),
|
||||||
adjustment.repr(bcx.tcx()));
|
adjustment.repr(bcx.tcx()));
|
||||||
match adjustment {
|
match adjustment {
|
||||||
AdjustAddEnv(..) => {
|
AdjustAddEnv(def_id, _) => {
|
||||||
datum = unpack_datum!(bcx, add_env(bcx, expr, datum));
|
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) => {
|
AdjustDerefRef(ref adj) => {
|
||||||
let (autoderefs, use_autoref) = match adj.autoref {
|
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>,
|
fn add_env<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||||
|
def_id: ast::DefId,
|
||||||
expr: &ast::Expr,
|
expr: &ast::Expr,
|
||||||
datum: Datum<'tcx, Expr>)
|
datum: Datum<'tcx, Expr>)
|
||||||
-> DatumBlock<'blk, '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 closure_ty = expr_ty_adjusted(bcx, expr);
|
||||||
let fn_ptr = datum.to_llscalarish(bcx);
|
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_id, fn_ptr)
|
||||||
closure::make_closure_from_bare_fn(bcx, closure_ty, def, fn_ptr)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,7 +228,7 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||||||
ccx.tn().val_to_string(llretptr));
|
ccx.tn().val_to_string(llretptr));
|
||||||
|
|
||||||
let (fn_abi, fn_sig) = match callee_ty.sty {
|
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")
|
_ => ccx.sess().bug("trans_native_call called on non-function type")
|
||||||
};
|
};
|
||||||
let llsig = foreign_signature(ccx, &fn_sig, passed_arg_tys[]);
|
let llsig = foreign_signature(ccx, &fn_sig, passed_arg_tys[]);
|
||||||
@ -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 tys = foreign_types_for_fn_ty(ccx, t);
|
||||||
let llfn_ty = lltype_for_fn_from_foreign_types(ccx, &tys);
|
let llfn_ty = lltype_for_fn_from_foreign_types(ccx, &tys);
|
||||||
let cconv = match t.sty {
|
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)
|
llvm_calling_convention(ccx, fn_ty.abi)
|
||||||
}
|
}
|
||||||
_ => panic!("expected bare fn in decl_rust_fn_with_foreign_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 llfn_ty = lltype_for_fn_from_foreign_types(ccx, &tys);
|
||||||
let t = ty::node_id_to_type(ccx.tcx(), node_id);
|
let t = ty::node_id_to_type(ccx.tcx(), node_id);
|
||||||
let cconv = match t.sty {
|
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)
|
llvm_calling_convention(ccx, fn_ty.abi)
|
||||||
}
|
}
|
||||||
_ => panic!("expected bare fn in register_rust_fn_with_foreign_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
|
// 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.
|
// normal Rust function. This will be the type of the wrappee fn.
|
||||||
match t.sty {
|
match t.sty {
|
||||||
ty::ty_bare_fn(ref f) => {
|
ty::ty_bare_fn(_, ref f) => {
|
||||||
assert!(f.abi != Rust && f.abi != RustIntrinsic);
|
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>,
|
fn foreign_types_for_fn_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||||
ty: Ty<'tcx>) -> ForeignTypes<'tcx> {
|
ty: Ty<'tcx>) -> ForeignTypes<'tcx> {
|
||||||
let fn_sig = match ty.sty {
|
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")
|
_ => 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());
|
let llsig = foreign_signature(ccx, &fn_sig, fn_sig.0.inputs.as_slice());
|
||||||
|
@ -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 fty = ty::lookup_item_type(bcx.tcx(), dtor_did).ty.subst(bcx.tcx(), substs);
|
||||||
let self_ty = match fty.sty {
|
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);
|
assert!(f.sig.0.inputs.len() == 1);
|
||||||
f.sig.0.inputs[0]
|
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(),
|
let dtor_ty = ty::mk_ctor_fn(bcx.tcx(),
|
||||||
|
class_did,
|
||||||
&[get_drop_glue_type(bcx.ccx(), t)],
|
&[get_drop_glue_type(bcx.ccx(), t)],
|
||||||
ty::mk_nil(bcx.tcx()));
|
ty::mk_nil(bcx.tcx()));
|
||||||
let (_, variant_cx) = invoke(variant_cx, dtor_addr, args[], dtor_ty, None, false);
|
let (_, variant_cx) = invoke(variant_cx, dtor_addr, args[], dtor_ty, None, false);
|
||||||
|
@ -150,7 +150,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
|||||||
let tcx = bcx.tcx();
|
let tcx = bcx.tcx();
|
||||||
|
|
||||||
let ret_ty = match callee_ty.sty {
|
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")
|
_ => panic!("expected bare_fn in trans_intrinsic_call")
|
||||||
};
|
};
|
||||||
let foreign_item = tcx.map.expect_foreign_item(node);
|
let foreign_item = tcx.map.expect_foreign_item(node);
|
||||||
|
@ -477,7 +477,7 @@ pub fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||||||
debug!("(translating trait callee) loading method");
|
debug!("(translating trait callee) loading method");
|
||||||
// Replace the self type (&Self or Box<Self>) with an opaque pointer.
|
// Replace the self type (&Self or Box<Self>) with an opaque pointer.
|
||||||
let llcallee_ty = match callee_ty.sty {
|
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,
|
type_of_rust_fn(ccx,
|
||||||
Some(Type::i8p(ccx)),
|
Some(Type::i8p(ccx)),
|
||||||
f.sig.0.inputs.slice_from(1),
|
f.sig.0.inputs.slice_from(1),
|
||||||
@ -639,7 +639,8 @@ fn emit_vtable_methods<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||||||
m.repr(tcx),
|
m.repr(tcx),
|
||||||
substs.repr(tcx));
|
substs.repr(tcx));
|
||||||
if m.generics.has_type_params(subst::FnSpace) ||
|
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 \
|
debug!("(making impl vtable) method has self or type \
|
||||||
params: {}",
|
params: {}",
|
||||||
token::get_name(name));
|
token::get_name(name));
|
||||||
|
@ -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.sig.0.output,
|
||||||
f.abi)
|
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 {
|
if f.abi == abi::Rust || f.abi == abi::RustCall {
|
||||||
type_of_rust_fn(cx,
|
type_of_rust_fn(cx,
|
||||||
None,
|
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_str => Type::i8(cx),
|
||||||
|
|
||||||
ty::ty_bare_fn(_) => {
|
ty::ty_bare_fn(..) => {
|
||||||
type_of_fn_from_ty(cx, t).ptr_to()
|
type_of_fn_from_ty(cx, t).ptr_to()
|
||||||
}
|
}
|
||||||
ty::ty_closure(_) => {
|
ty::ty_closure(_) => {
|
||||||
|
@ -954,7 +954,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
|||||||
tcx.sess.span_err(ast_ty.span,
|
tcx.sess.span_err(ast_ty.span,
|
||||||
"variadic function must have C calling convention");
|
"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) => {
|
ast::TyClosure(ref f) => {
|
||||||
// Use corresponding trait store to figure out default bounds
|
// Use corresponding trait store to figure out default bounds
|
||||||
|
@ -113,7 +113,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
|
|||||||
self.add_obligations(&pick, &method_bounds_substs, &method_bounds);
|
self.add_obligations(&pick, &method_bounds_substs, &method_bounds);
|
||||||
|
|
||||||
// Create the final `MethodCallee`.
|
// 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),
|
sig: ty::Binder(method_sig),
|
||||||
unsafety: pick.method_ty.fty.unsafety,
|
unsafety: pick.method_ty.fty.unsafety,
|
||||||
abi: pick.method_ty.fty.abi.clone(),
|
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,
|
fn fixup_derefs_on_method_receiver_if_necessary(&self,
|
||||||
method_callee: &MethodCallee) {
|
method_callee: &MethodCallee) {
|
||||||
let sig = match method_callee.ty.sty {
|
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(),
|
ty::ty_closure(ref f) => f.sig.clone(),
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
|
@ -199,7 +199,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
|
|||||||
infer::FnCall,
|
infer::FnCall,
|
||||||
&fn_sig).0;
|
&fn_sig).0;
|
||||||
let transformed_self_ty = fn_sig.inputs[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),
|
sig: ty::Binder(fn_sig),
|
||||||
unsafety: bare_fn_ty.unsafety,
|
unsafety: bare_fn_ty.unsafety,
|
||||||
abi: bare_fn_ty.abi.clone(),
|
abi: bare_fn_ty.abi.clone(),
|
||||||
|
@ -399,7 +399,7 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
|||||||
let fty = fty.subst(ccx.tcx, ¶m_env.free_substs);
|
let fty = fty.subst(ccx.tcx, ¶m_env.free_substs);
|
||||||
|
|
||||||
match fty.sty {
|
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 inh = Inherited::new(ccx.tcx, param_env);
|
||||||
let fcx = check_fn(ccx, fn_ty.unsafety, id, &fn_ty.sig,
|
let fcx = check_fn(ccx, fn_ty.unsafety, id, &fn_ty.sig,
|
||||||
decl, id, body, &inh);
|
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.
|
// 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 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);
|
let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
|
||||||
|
|
||||||
// Check the impl method type IM is a subtype of the trait method
|
// 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);
|
}, 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_scalar = ty::type_is_scalar(t_1);
|
||||||
let t_1_is_char = ty::type_is_char(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);
|
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
|
// 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;
|
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) {
|
if t_1_is_float || ty::type_is_unsafe_ptr(t_1) {
|
||||||
fcx.type_error_message(span, |actual| {
|
fcx.type_error_message(span, |actual| {
|
||||||
format!("illegal cast; cast through an \
|
format!("illegal cast; cast through an \
|
||||||
@ -1634,7 +1638,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
span: Span,
|
span: Span,
|
||||||
adj: &ty::AutoAdjustment<'tcx>) {
|
adj: &ty::AutoAdjustment<'tcx>) {
|
||||||
match *adj {
|
match *adj {
|
||||||
ty::AdjustAddEnv(..) => { }
|
ty::AdjustAddEnv(..) |
|
||||||
|
ty::AdjustReifyFnPointer(..) => {
|
||||||
|
}
|
||||||
ty::AdjustDerefRef(ref d_r) => {
|
ty::AdjustDerefRef(ref d_r) => {
|
||||||
match d_r.autoref {
|
match d_r.autoref {
|
||||||
Some(ref a_r) => {
|
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
|
// Bail out if the callee is a bare function or a closure. We check those
|
||||||
// manually.
|
// manually.
|
||||||
match structurally_resolved_type(fcx, callee.span, callee_type).sty {
|
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())
|
ty::FnConverging(ty::mk_err())
|
||||||
} else {
|
} else {
|
||||||
match method_fn_ty.sty {
|
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).
|
// HACK(eddyb) ignore self in the definition (see above).
|
||||||
check_argument_types(fcx,
|
check_argument_types(fcx,
|
||||||
sp,
|
sp,
|
||||||
@ -2921,7 +2927,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
|||||||
});
|
});
|
||||||
|
|
||||||
let fn_sig = match fn_ty.sty {
|
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,
|
ty::ty_closure(box ty::ClosureTy {ref sig, ..}) => sig,
|
||||||
_ => {
|
_ => {
|
||||||
fcx.type_error_message(call_expr.span, |actual| {
|
fcx.type_error_message(call_expr.span, |actual| {
|
||||||
@ -3875,7 +3881,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
|||||||
}
|
}
|
||||||
|
|
||||||
let lhs_ty = fcx.expr_ty(&**lhs);
|
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);
|
let rhs_ty = fcx.expr_ty(&**rhs);
|
||||||
|
|
||||||
fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
|
fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
|
||||||
@ -5641,7 +5647,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
|
|||||||
};
|
};
|
||||||
(n_tps, inputs, ty::FnConverging(output))
|
(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,
|
unsafety: ast::Unsafety::Unsafe,
|
||||||
abi: abi::RustIntrinsic,
|
abi: abi::RustIntrinsic,
|
||||||
sig: ty::Binder(FnSig {
|
sig: ty::Binder(FnSig {
|
||||||
|
@ -355,7 +355,7 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> {
|
|||||||
|
|
||||||
self.fold_substs(substs);
|
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, ..}) => {
|
ty::ty_closure(box ty::ClosureTy{sig: ref fn_sig, ..}) => {
|
||||||
self.binding_count += 1;
|
self.binding_count += 1;
|
||||||
|
|
||||||
|
@ -15,7 +15,6 @@ use self::ResolveReason::*;
|
|||||||
|
|
||||||
use astconv::AstConv;
|
use astconv::AstConv;
|
||||||
use check::FnCtxt;
|
use check::FnCtxt;
|
||||||
use middle::def;
|
|
||||||
use middle::pat_util;
|
use middle::pat_util;
|
||||||
use middle::ty::{mod, Ty, MethodCall, MethodCallee};
|
use middle::ty::{mod, Ty, MethodCall, MethodCallee};
|
||||||
use middle::ty_fold::{TypeFolder,TypeFoldable};
|
use middle::ty_fold::{TypeFolder,TypeFoldable};
|
||||||
@ -267,25 +266,12 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
|||||||
Some(adjustment) => {
|
Some(adjustment) => {
|
||||||
let adj_object = ty::adjust_is_object(&adjustment);
|
let adj_object = ty::adjust_is_object(&adjustment);
|
||||||
let resolved_adjustment = match adjustment {
|
let resolved_adjustment = match adjustment {
|
||||||
ty::AdjustAddEnv(store) => {
|
ty::AdjustAddEnv(def_id, store) => {
|
||||||
// FIXME(eddyb) #2190 Allow only statically resolved
|
ty::AdjustAddEnv(def_id, self.resolve(&store, reason))
|
||||||
// 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(self.resolve(&store, reason))
|
ty::AdjustReifyFnPointer(def_id) => {
|
||||||
|
ty::AdjustReifyFnPointer(def_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::AdjustDerefRef(adj) => {
|
ty::AdjustDerefRef(adj) => {
|
||||||
|
@ -235,7 +235,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
|
|||||||
// impl, plus its own.
|
// impl, plus its own.
|
||||||
let new_polytype = ty::Polytype {
|
let new_polytype = ty::Polytype {
|
||||||
generics: new_method_ty.generics.clone(),
|
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));
|
debug!("new_polytype={}", new_polytype.repr(tcx));
|
||||||
|
|
||||||
|
@ -211,6 +211,8 @@ pub fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
|||||||
|
|
||||||
// Create a set of parameter types shared among all the variants.
|
// Create a set of parameter types shared among all the variants.
|
||||||
for variant in variants.iter() {
|
for variant in variants.iter() {
|
||||||
|
let variant_def_id = local_def(variant.node.id);
|
||||||
|
|
||||||
// Nullary enum constructors get turned into constants; n-ary enum
|
// Nullary enum constructors get turned into constants; n-ary enum
|
||||||
// constructors get turned into functions.
|
// constructors get turned into functions.
|
||||||
let result_ty = match variant.node.kind {
|
let result_ty = match variant.node.kind {
|
||||||
@ -246,7 +248,7 @@ pub fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
|||||||
ty: result_ty
|
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);
|
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,
|
m.def_id,
|
||||||
Polytype {
|
Polytype {
|
||||||
generics: m.generics.clone(),
|
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>,
|
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");
|
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,
|
let mty = Rc::new(ty_of_method(ccx,
|
||||||
convert_method_context,
|
convert_method_context,
|
||||||
container,
|
container,
|
||||||
@ -526,13 +529,13 @@ fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>,
|
|||||||
untransformed_rcvr_ty,
|
untransformed_rcvr_ty,
|
||||||
rcvr_ty_generics,
|
rcvr_ty_generics,
|
||||||
rcvr_visibility));
|
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 {}",
|
debug!("method {} (id {}) has type {}",
|
||||||
m.pe_ident().repr(tcx),
|
m.pe_ident().repr(tcx),
|
||||||
m.id,
|
m.id,
|
||||||
fty.repr(tcx));
|
fty.repr(tcx));
|
||||||
tcx.tcache.borrow_mut().insert(
|
tcx.tcache.borrow_mut().insert(
|
||||||
local_def(m.id),
|
m_def_id,
|
||||||
Polytype {
|
Polytype {
|
||||||
generics: mty.generics.clone(),
|
generics: mty.generics.clone(),
|
||||||
ty: fty
|
ty: fty
|
||||||
@ -1461,7 +1464,7 @@ pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item)
|
|||||||
};
|
};
|
||||||
let pty = Polytype {
|
let pty = Polytype {
|
||||||
generics: ty_generics,
|
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 {}",
|
debug!("type of {} (id {}) is {}",
|
||||||
token::get_ident(it.ident),
|
token::get_ident(it.ident),
|
||||||
@ -2138,6 +2141,7 @@ pub fn ty_of_foreign_fn_decl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
|||||||
|
|
||||||
let t_fn = ty::mk_bare_fn(
|
let t_fn = ty::mk_bare_fn(
|
||||||
ccx.tcx,
|
ccx.tcx,
|
||||||
|
None,
|
||||||
ty::BareFnTy {
|
ty::BareFnTy {
|
||||||
abi: abi,
|
abi: abi,
|
||||||
unsafety: ast::Unsafety::Unsafe,
|
unsafety: ast::Unsafety::Unsafe,
|
||||||
|
@ -102,6 +102,7 @@ use util::ppaux;
|
|||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
use syntax::print::pprust::*;
|
use syntax::print::pprust::*;
|
||||||
use syntax::{ast, ast_map, abi};
|
use syntax::{ast, ast_map, abi};
|
||||||
|
use syntax::ast_util::local_def;
|
||||||
|
|
||||||
#[cfg(stage0)]
|
#[cfg(stage0)]
|
||||||
mod diagnostics;
|
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,
|
unsafety: ast::Unsafety::Normal,
|
||||||
abi: abi::Rust,
|
abi: abi::Rust,
|
||||||
sig: ty::Binder(ty::FnSig {
|
sig: ty::Binder(ty::FnSig {
|
||||||
@ -256,7 +257,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
|
|||||||
let tcx = ccx.tcx;
|
let tcx = ccx.tcx;
|
||||||
let start_t = ty::node_id_to_type(tcx, start_id);
|
let start_t = ty::node_id_to_type(tcx, start_id);
|
||||||
match start_t.sty {
|
match start_t.sty {
|
||||||
ty::ty_bare_fn(_) => {
|
ty::ty_bare_fn(..) => {
|
||||||
match tcx.map.find(start_id) {
|
match tcx.map.find(start_id) {
|
||||||
Some(ast_map::NodeItem(it)) => {
|
Some(ast_map::NodeItem(it)) => {
|
||||||
match it.node {
|
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,
|
unsafety: ast::Unsafety::Normal,
|
||||||
abi: abi::Rust,
|
abi: abi::Rust,
|
||||||
sig: ty::Binder(ty::FnSig {
|
sig: ty::Binder(ty::FnSig {
|
||||||
|
@ -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 {
|
ty::ty_closure(box ty::ClosureTy {
|
||||||
ref sig,
|
ref sig,
|
||||||
store: ty::UniqTraitStore,
|
store: ty::UniqTraitStore,
|
||||||
..
|
..
|
||||||
}) => {
|
}) =>
|
||||||
|
{
|
||||||
self.add_constraints_from_sig(sig, variance);
|
self.add_constraints_from_sig(sig, variance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
fn build_external_function(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) -> clean::Function {
|
||||||
let t = ty::lookup_item_type(tcx, did);
|
let t = ty::lookup_item_type(tcx, did);
|
||||||
let (decl, style) = match t.ty.sty {
|
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"),
|
_ => panic!("bad function"),
|
||||||
};
|
};
|
||||||
clean::Function {
|
clean::Function {
|
||||||
|
@ -1360,7 +1360,7 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
|
|||||||
mutability: mt.mutbl.clean(cx),
|
mutability: mt.mutbl.clean(cx),
|
||||||
type_: box mt.ty.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,
|
unsafety: fty.unsafety,
|
||||||
generics: Generics {
|
generics: Generics {
|
||||||
lifetimes: Vec::new(),
|
lifetimes: Vec::new(),
|
||||||
|
@ -65,17 +65,21 @@ const HOEDOWN_EXTENSIONS: libc::c_uint =
|
|||||||
|
|
||||||
type hoedown_document = libc::c_void; // this is opaque to us
|
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)]
|
#[repr(C)]
|
||||||
struct hoedown_renderer {
|
struct hoedown_renderer {
|
||||||
opaque: *mut hoedown_html_renderer_state,
|
opaque: *mut hoedown_html_renderer_state,
|
||||||
blockcode: Option<extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
|
blockcode: Option<blockcodefn>,
|
||||||
*const hoedown_buffer, *mut libc::c_void)>,
|
|
||||||
blockquote: Option<extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
|
blockquote: Option<extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
|
||||||
*mut libc::c_void)>,
|
*mut libc::c_void)>,
|
||||||
blockhtml: Option<extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
|
blockhtml: Option<extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
|
||||||
*mut libc::c_void)>,
|
*mut libc::c_void)>,
|
||||||
header: Option<extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
|
header: Option<headerfn>,
|
||||||
libc::c_int, *mut libc::c_void)>,
|
|
||||||
other: [libc::size_t, ..28],
|
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}
|
toc_builder: if print_toc {Some(TocBuilder::new())} else {None}
|
||||||
};
|
};
|
||||||
(*(*renderer).opaque).opaque = &mut opaque as *mut _ as *mut libc::c_void;
|
(*(*renderer).opaque).opaque = &mut opaque as *mut _ as *mut libc::c_void;
|
||||||
(*renderer).blockcode = Some(block);
|
(*renderer).blockcode = Some(block as blockcodefn);
|
||||||
(*renderer).header = Some(header);
|
(*renderer).header = Some(header as headerfn);
|
||||||
|
|
||||||
let document = hoedown_document_new(renderer, HOEDOWN_EXTENSIONS, 16);
|
let document = hoedown_document_new(renderer, HOEDOWN_EXTENSIONS, 16);
|
||||||
hoedown_document_render(document, ob, s.as_ptr(),
|
hoedown_document_render(document, ob, s.as_ptr(),
|
||||||
@ -354,8 +358,8 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector) {
|
|||||||
unsafe {
|
unsafe {
|
||||||
let ob = hoedown_buffer_new(DEF_OUNIT);
|
let ob = hoedown_buffer_new(DEF_OUNIT);
|
||||||
let renderer = hoedown_html_renderer_new(0, 0);
|
let renderer = hoedown_html_renderer_new(0, 0);
|
||||||
(*renderer).blockcode = Some(block);
|
(*renderer).blockcode = Some(block as blockcodefn);
|
||||||
(*renderer).header = Some(header);
|
(*renderer).header = Some(header as headerfn);
|
||||||
(*(*renderer).opaque).opaque = tests as *mut _ as *mut libc::c_void;
|
(*(*renderer).opaque).opaque = tests as *mut _ as *mut libc::c_void;
|
||||||
|
|
||||||
let document = hoedown_document_new(renderer, HOEDOWN_EXTENSIONS, 16);
|
let document = hoedown_document_new(renderer, HOEDOWN_EXTENSIONS, 16);
|
||||||
|
@ -838,8 +838,9 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
||||||
pub fn keys(&self) -> Keys<K, V> {
|
pub fn keys<'a>(&'a self) -> Keys<'a, K, V> {
|
||||||
fn first<A, B>((a, _): (A, B)) -> A { a }
|
fn first<A, B>((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) }
|
Keys { inner: self.iter().map(first) }
|
||||||
}
|
}
|
||||||
@ -862,8 +863,9 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
||||||
pub fn values(&self) -> Values<K, V> {
|
pub fn values<'a>(&'a self) -> Values<'a, K, V> {
|
||||||
fn second<A, B>((_, b): (A, B)) -> B { b }
|
fn second<A, B>((_, 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) }
|
Values { inner: self.iter().map(second) }
|
||||||
}
|
}
|
||||||
@ -938,6 +940,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
|
|||||||
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
||||||
pub fn into_iter(self) -> IntoIter<K, V> {
|
pub fn into_iter(self) -> IntoIter<K, V> {
|
||||||
fn last_two<A, B, C>((_, b, c): (A, B, C)) -> (B, C) { (b, c) }
|
fn last_two<A, B, C>((_, b, c): (A, B, C)) -> (B, C) { (b, c) }
|
||||||
|
let last_two: fn((SafeHash, K, V)) -> (K, V) = last_two;
|
||||||
|
|
||||||
IntoIter {
|
IntoIter {
|
||||||
inner: self.table.into_iter().map(last_two)
|
inner: self.table.into_iter().map(last_two)
|
||||||
@ -1007,6 +1010,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
|
|||||||
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
||||||
pub fn drain(&mut self) -> Drain<K, V> {
|
pub fn drain(&mut self) -> Drain<K, V> {
|
||||||
fn last_two<A, B, C>((_, b, c): (A, B, C)) -> (B, C) { (b, c) }
|
fn last_two<A, B, C>((_, 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 {
|
Drain {
|
||||||
inner: self.table.drain().map(last_two),
|
inner: self.table.drain().map(last_two),
|
||||||
|
@ -276,6 +276,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
|
|||||||
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
||||||
pub fn into_iter(self) -> IntoIter<T> {
|
pub fn into_iter(self) -> IntoIter<T> {
|
||||||
fn first<A, B>((a, _): (A, B)) -> A { a }
|
fn first<A, B>((a, _): (A, B)) -> A { a }
|
||||||
|
let first: fn((T, ())) -> T = first;
|
||||||
|
|
||||||
IntoIter { iter: self.map.into_iter().map(first) }
|
IntoIter { iter: self.map.into_iter().map(first) }
|
||||||
}
|
}
|
||||||
@ -418,6 +419,8 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
|
|||||||
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
||||||
pub fn drain(&mut self) -> Drain<T> {
|
pub fn drain(&mut self) -> Drain<T> {
|
||||||
fn first<A, B>((a, _): (A, B)) -> A { a }
|
fn first<A, B>((a, _): (A, B)) -> A { a }
|
||||||
|
let first: fn((T, ())) -> T = first; // coerce to fn pointer
|
||||||
|
|
||||||
Drain { iter: self.map.drain().map(first) }
|
Drain { iter: self.map.drain().map(first) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -390,6 +390,7 @@ impl Path {
|
|||||||
let v = if self.repr[0] == SEP_BYTE {
|
let v = if self.repr[0] == SEP_BYTE {
|
||||||
self.repr[1..]
|
self.repr[1..]
|
||||||
} else { self.repr.as_slice() };
|
} 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);
|
let mut ret = v.split(is_sep_byte);
|
||||||
if v.is_empty() {
|
if v.is_empty() {
|
||||||
// consume the empty "" component
|
// consume the empty "" component
|
||||||
@ -404,7 +405,8 @@ impl Path {
|
|||||||
fn from_utf8(s: &[u8]) -> Option<&str> {
|
fn from_utf8(s: &[u8]) -> Option<&str> {
|
||||||
str::from_utf8(s).ok()
|
str::from_utf8(s).ok()
|
||||||
}
|
}
|
||||||
self.components().map(from_utf8)
|
let f: fn(&[u8]) -> Option<&str> = from_utf8; // coerce to fn ptr
|
||||||
|
self.components().map(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -651,7 +651,8 @@ impl Path {
|
|||||||
None if repr.as_bytes()[0] == SEP_BYTE => repr[1..],
|
None if repr.as_bytes()[0] == SEP_BYTE => repr[1..],
|
||||||
None => repr
|
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
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -662,6 +663,7 @@ impl Path {
|
|||||||
#![inline]
|
#![inline]
|
||||||
x.unwrap().as_bytes()
|
x.unwrap().as_bytes()
|
||||||
}
|
}
|
||||||
|
let convert: for<'b> fn(Option<&'b str>) -> &'b [u8] = convert; // coerce to fn ptr
|
||||||
self.str_components().map(convert)
|
self.str_components().map(convert)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1044,7 +1046,11 @@ fn parse_prefix<'a>(mut path: &'a str) -> Option<PathPrefix> {
|
|||||||
|
|
||||||
// None result means the string didn't need normalizing
|
// None result means the string didn't need normalizing
|
||||||
fn normalize_helper<'a>(s: &'a str, prefix: Option<PathPrefix>) -> (bool, Option<Vec<&'a str>>) {
|
fn normalize_helper<'a>(s: &'a str, prefix: Option<PathPrefix>) -> (bool, Option<Vec<&'a str>>) {
|
||||||
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 is_abs = s.len() > prefix_len(prefix) && f(s.char_at(prefix_len(prefix)));
|
||||||
let s_ = s[prefix_len(prefix)..];
|
let s_ = s[prefix_len(prefix)..];
|
||||||
let s_ = if is_abs { s_[1..] } else { s_ };
|
let s_ = if is_abs { s_[1..] } else { s_ };
|
||||||
|
@ -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> = {
|
const INIT: ::std::thread_local::KeyInner<$t> = {
|
||||||
unsafe extern fn __destroy(ptr: *mut u8) {
|
unsafe extern fn __destroy(ptr: *mut u8) {
|
||||||
::std::thread_local::destroy_value::<$t>(ptr);
|
::std::thread_local::destroy_value::<$t>(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
::std::thread_local::KeyInner {
|
::std::thread_local::KeyInner {
|
||||||
inner: ::std::cell::UnsafeCell { value: $init },
|
inner: ::std::cell::UnsafeCell { value: $init },
|
||||||
os: ::std::thread_local::OsStaticKey {
|
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
|
INIT
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -323,6 +339,12 @@ mod imp {
|
|||||||
// *should* be the case that this loop always terminates because we
|
// *should* be the case that this loop always terminates because we
|
||||||
// provide the guarantee that a TLS key cannot be set after it is
|
// provide the guarantee that a TLS key cannot be set after it is
|
||||||
// flagged for destruction.
|
// 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 {
|
static DTORS: os::StaticKey = os::StaticKey {
|
||||||
inner: os::INIT_INNER,
|
inner: os::INIT_INNER,
|
||||||
dtor: Some(run_dtors),
|
dtor: Some(run_dtors),
|
||||||
|
@ -50,14 +50,16 @@ pub trait ItemDecorator {
|
|||||||
push: |P<ast::Item>|);
|
push: |P<ast::Item>|);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ItemDecorator for fn(&mut ExtCtxt, Span, &ast::MetaItem, &ast::Item, |P<ast::Item>|) {
|
impl<F> ItemDecorator for F
|
||||||
|
where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, &ast::Item, |P<ast::Item>|)
|
||||||
|
{
|
||||||
fn expand(&self,
|
fn expand(&self,
|
||||||
ecx: &mut ExtCtxt,
|
ecx: &mut ExtCtxt,
|
||||||
sp: Span,
|
sp: Span,
|
||||||
meta_item: &ast::MetaItem,
|
meta_item: &ast::MetaItem,
|
||||||
item: &ast::Item,
|
item: &ast::Item,
|
||||||
push: |P<ast::Item>|) {
|
push: |P<ast::Item>|) {
|
||||||
self.clone()(ecx, sp, meta_item, item, push)
|
(*self)(ecx, sp, meta_item, item, push)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,14 +72,16 @@ pub trait ItemModifier {
|
|||||||
-> P<ast::Item>;
|
-> P<ast::Item>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ItemModifier for fn(&mut ExtCtxt, Span, &ast::MetaItem, P<ast::Item>) -> P<ast::Item> {
|
impl<F> ItemModifier for F
|
||||||
|
where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, P<ast::Item>) -> P<ast::Item>
|
||||||
|
{
|
||||||
fn expand(&self,
|
fn expand(&self,
|
||||||
ecx: &mut ExtCtxt,
|
ecx: &mut ExtCtxt,
|
||||||
span: Span,
|
span: Span,
|
||||||
meta_item: &ast::MetaItem,
|
meta_item: &ast::MetaItem,
|
||||||
item: P<ast::Item>)
|
item: P<ast::Item>)
|
||||||
-> P<ast::Item> {
|
-> P<ast::Item> {
|
||||||
self.clone()(ecx, span, meta_item, item)
|
(*self)(ecx, span, meta_item, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,13 +97,15 @@ pub trait TTMacroExpander {
|
|||||||
pub type MacroExpanderFn =
|
pub type MacroExpanderFn =
|
||||||
for<'cx> fn(&'cx mut ExtCtxt, Span, &[ast::TokenTree]) -> Box<MacResult+'cx>;
|
for<'cx> fn(&'cx mut ExtCtxt, Span, &[ast::TokenTree]) -> Box<MacResult+'cx>;
|
||||||
|
|
||||||
impl TTMacroExpander for MacroExpanderFn {
|
impl<F> TTMacroExpander for F
|
||||||
|
where F : for<'cx> Fn(&'cx mut ExtCtxt, Span, &[ast::TokenTree]) -> Box<MacResult+'cx>
|
||||||
|
{
|
||||||
fn expand<'cx>(&self,
|
fn expand<'cx>(&self,
|
||||||
ecx: &'cx mut ExtCtxt,
|
ecx: &'cx mut ExtCtxt,
|
||||||
span: Span,
|
span: Span,
|
||||||
token_tree: &[ast::TokenTree])
|
token_tree: &[ast::TokenTree])
|
||||||
-> Box<MacResult+'cx> {
|
-> Box<MacResult+'cx> {
|
||||||
self.clone()(ecx, span, token_tree)
|
(*self)(ecx, span, token_tree)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,14 +121,18 @@ pub trait IdentMacroExpander {
|
|||||||
pub type IdentMacroExpanderFn =
|
pub type IdentMacroExpanderFn =
|
||||||
for<'cx> fn(&'cx mut ExtCtxt, Span, ast::Ident, Vec<ast::TokenTree>) -> Box<MacResult+'cx>;
|
for<'cx> fn(&'cx mut ExtCtxt, Span, ast::Ident, Vec<ast::TokenTree>) -> Box<MacResult+'cx>;
|
||||||
|
|
||||||
impl IdentMacroExpander for IdentMacroExpanderFn {
|
impl<F> IdentMacroExpander for F
|
||||||
|
where F : for<'cx> Fn(&'cx mut ExtCtxt, Span, ast::Ident,
|
||||||
|
Vec<ast::TokenTree>) -> Box<MacResult+'cx>
|
||||||
|
{
|
||||||
fn expand<'cx>(&self,
|
fn expand<'cx>(&self,
|
||||||
cx: &'cx mut ExtCtxt,
|
cx: &'cx mut ExtCtxt,
|
||||||
sp: Span,
|
sp: Span,
|
||||||
ident: ast::Ident,
|
ident: ast::Ident,
|
||||||
token_tree: Vec<ast::TokenTree> )
|
token_tree: Vec<ast::TokenTree> )
|
||||||
-> Box<MacResult+'cx> {
|
-> Box<MacResult+'cx>
|
||||||
self.clone()(cx, sp, ident, token_tree)
|
{
|
||||||
|
(*self)(cx, sp, ident, token_tree)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +64,10 @@ impl UnicodeStr for str {
|
|||||||
#[inline]
|
#[inline]
|
||||||
fn words(&self) -> Words {
|
fn words(&self) -> Words {
|
||||||
fn is_not_empty(s: &&str) -> bool { !s.is_empty() }
|
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() }
|
fn is_whitespace(c: char) -> bool { c.is_whitespace() }
|
||||||
|
let is_whitespace: fn(char) -> bool = is_whitespace; // coerce to fn pointer
|
||||||
|
|
||||||
Words { inner: self.split(is_whitespace).filter(is_not_empty) }
|
Words { inner: self.split(is_whitespace).filter(is_not_empty) }
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ impl X {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut x = X(Either::Right(main));
|
let mut x = X(Either::Right(main as fn()));
|
||||||
(&mut x).with(
|
(&mut x).with(
|
||||||
|opt| { //~ ERROR cannot borrow `x` as mutable more than once at a time
|
|opt| { //~ ERROR cannot borrow `x` as mutable more than once at a time
|
||||||
match opt {
|
match opt {
|
||||||
|
@ -13,7 +13,7 @@ fn foo(_x: int) { }
|
|||||||
fn main() {
|
fn main() {
|
||||||
let v: u64 = 5;
|
let v: u64 = 5;
|
||||||
let x = foo as extern "C" fn() -> int;
|
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);
|
let y = v as extern "Rust" fn(int) -> (int, int);
|
||||||
//~^ ERROR non-scalar cast
|
//~^ ERROR non-scalar cast
|
||||||
y(x());
|
y(x());
|
||||||
|
@ -8,12 +8,21 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// 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 foo() {}
|
||||||
|
|
||||||
fn main() {
|
fn fn_item_type() {
|
||||||
let f = foo;
|
let f = foo;
|
||||||
|
|
||||||
let f_closure: || = f;
|
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() { }
|
||||||
|
25
src/test/compile-fail/fn-item-type.rs
Normal file
25
src/test/compile-fail/fn-item-type.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T>(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
|
||||||
|
}
|
@ -12,4 +12,4 @@ fn f(_: extern "Rust" fn()) {}
|
|||||||
extern fn bar() {}
|
extern fn bar() {}
|
||||||
|
|
||||||
fn main() { f(bar) }
|
fn main() { f(bar) }
|
||||||
//~^ ERROR: expected `fn()`, found `extern "C" fn()`
|
//~^ ERROR mismatched types
|
||||||
|
@ -10,6 +10,6 @@
|
|||||||
|
|
||||||
#[start]
|
#[start]
|
||||||
fn start(argc: int, argv: *const *const u8, crate_map: *const u8) -> int {
|
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
|
0
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
fn b<'a, 'b>(x: &mut &'a int, y: &mut &'b int) {
|
||||||
// Illegal now because there is no `'b:'a` declaration.
|
// 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) {
|
fn c<'a,'b>(x: &mut &'a int, y: &mut &'b int) {
|
||||||
|
@ -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) {
|
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.
|
// Illegal now because there is no `'b:'a` declaration.
|
||||||
*x = *y; //~ ERROR mismatched types
|
*x = *y; //~ ERROR cannot infer
|
||||||
*z = *y; //~ ERROR mismatched types
|
*z = *y; //~ ERROR cannot infer
|
||||||
}
|
}
|
||||||
|
|
||||||
fn c<'a,'b, 'c>(x: &mut &'a int, y: &mut &'b int, z: &mut &'c int) {
|
fn c<'a,'b, 'c>(x: &mut &'a int, y: &mut &'b int, z: &mut &'c int) {
|
||||||
|
@ -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) {
|
fn b<'a, 'b>(x: &mut &'a int, y: &mut &'b int) {
|
||||||
// Illegal now because there is no `'b:'a` declaration.
|
// 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) {
|
fn c<'a,'b>(x: &mut &'a int, y: &mut &'b int) {
|
||||||
|
@ -12,10 +12,10 @@ fn ignore<T>(t: T) {}
|
|||||||
|
|
||||||
fn nested<'x>(x: &'x int) {
|
fn nested<'x>(x: &'x int) {
|
||||||
let y = 3;
|
let y = 3;
|
||||||
let mut ay = &y; //~ ERROR cannot infer
|
let mut ay = &y;
|
||||||
|
|
||||||
ignore::< for<'z>|&'z int|>(|z| {
|
ignore::< for<'z>|&'z int|>(|z| {
|
||||||
ay = x;
|
ay = x; //~ ERROR cannot infer
|
||||||
ay = &y;
|
ay = &y;
|
||||||
ay = z;
|
ay = z;
|
||||||
});
|
});
|
||||||
|
@ -24,7 +24,7 @@ fn foo() -> Option<int> {
|
|||||||
|
|
||||||
fn create() -> A<'static> {
|
fn create() -> A<'static> {
|
||||||
A {
|
A {
|
||||||
func: &foo, //~ ERROR borrowed value does not live long enough
|
func: &foo, //~ ERROR mismatched types
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,9 +9,11 @@
|
|||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
struct StateMachineIter<'a> {
|
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> {
|
impl<'a> Iterator<&'static str> for StateMachineIter<'a> {
|
||||||
fn next(&mut self) -> Option<&'static str> {
|
fn next(&mut self) -> Option<&'static str> {
|
||||||
return (*self.statefn)(self);
|
return (*self.statefn)(self);
|
||||||
@ -19,19 +21,19 @@ impl<'a> Iterator<&'static str> for StateMachineIter<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn state1(self_: &mut StateMachineIter) -> Option<&'static str> {
|
fn state1(self_: &mut StateMachineIter) -> Option<&'static str> {
|
||||||
self_.statefn = &state2;
|
self_.statefn = &(state2 as StateMachineFunc);
|
||||||
//~^ ERROR borrowed value does not live long enough
|
//~^ ERROR borrowed value does not live long enough
|
||||||
return Some("state1");
|
return Some("state1");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn state2(self_: &mut StateMachineIter) -> Option<(&'static str)> {
|
fn state2(self_: &mut StateMachineIter) -> Option<(&'static str)> {
|
||||||
self_.statefn = &state3;
|
self_.statefn = &(state3 as StateMachineFunc);
|
||||||
//~^ ERROR borrowed value does not live long enough
|
//~^ ERROR borrowed value does not live long enough
|
||||||
return Some("state2");
|
return Some("state2");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn state3(self_: &mut StateMachineIter) -> Option<(&'static str)> {
|
fn state3(self_: &mut StateMachineIter) -> Option<(&'static str)> {
|
||||||
self_.statefn = &finished;
|
self_.statefn = &(finished as StateMachineFunc);
|
||||||
//~^ ERROR borrowed value does not live long enough
|
//~^ ERROR borrowed value does not live long enough
|
||||||
return Some("state3");
|
return Some("state3");
|
||||||
}
|
}
|
||||||
@ -42,7 +44,7 @@ fn finished(_: &mut StateMachineIter) -> Option<(&'static str)> {
|
|||||||
|
|
||||||
fn state_iter() -> StateMachineIter<'static> {
|
fn state_iter() -> StateMachineIter<'static> {
|
||||||
StateMachineIter {
|
StateMachineIter {
|
||||||
statefn: &state1 //~ ERROR borrowed value does not live long enough
|
statefn: &(state1 as StateMachineFunc) //~ ERROR borrowed value does not live long enough
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,9 +50,9 @@ pub fn bar() {
|
|||||||
|
|
||||||
|
|
||||||
((::std::fmt::format as
|
((::std::fmt::format as
|
||||||
fn(&core::fmt::Arguments<'_>) -> collections::string::String)((&((::std::fmt::Arguments::new
|
fn(&core::fmt::Arguments<'_>) -> collections::string::String {std::fmt::format})((&((::std::fmt::Arguments::new
|
||||||
as
|
as
|
||||||
fn(&[&str], &[core::fmt::Argument<'_>]) -> core::fmt::Arguments<'_>)((__STATIC_FMTSTR
|
fn(&[&str], &[core::fmt::Argument<'_>]) -> core::fmt::Arguments<'_> {core::fmt::Arguments<'a>::new})((__STATIC_FMTSTR
|
||||||
as
|
as
|
||||||
&'static [&'static str]),
|
&'static [&'static str]),
|
||||||
(&([]
|
(&([]
|
||||||
@ -78,7 +78,8 @@ pub fn id<T>(x: T) -> T { (x as T) }
|
|||||||
pub fn use_id() {
|
pub fn use_id() {
|
||||||
let _ =
|
let _ =
|
||||||
((id::<[int; (3u as uint)]> as
|
((id::<[int; (3u as uint)]> as
|
||||||
fn([int; 3]) -> [int; 3])(([(1 as int), (2 as int), (3 as int)]
|
fn([int; 3]) -> [int; 3] {id})(([(1 as int), (2 as int),
|
||||||
as [int; 3])) as [int; 3]);
|
(3 as int)] as [int; 3])) as
|
||||||
|
[int; 3]);
|
||||||
}
|
}
|
||||||
fn main() { }
|
fn main() { }
|
||||||
|
@ -18,6 +18,6 @@ struct S {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
assert!(foopy == f);
|
assert!(foopy as extern "C" fn() == f);
|
||||||
assert!(f == s.f);
|
assert!(f == s.f);
|
||||||
}
|
}
|
||||||
|
@ -18,15 +18,17 @@ extern fn uintret() -> uint { 22 }
|
|||||||
extern fn uintvoidret(_x: uint) {}
|
extern fn uintvoidret(_x: uint) {}
|
||||||
|
|
||||||
extern fn uintuintuintuintret(x: uint, y: uint, z: uint) -> uint { x+y+z }
|
extern fn uintuintuintuintret(x: uint, y: uint, z: uint) -> uint { x+y+z }
|
||||||
|
type uintuintuintuintret = extern fn(uint,uint,uint) -> uint;
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
assert!(voidret1 == voidret1);
|
assert!(voidret1 as extern fn() == voidret1 as extern fn());
|
||||||
assert!(voidret1 != voidret2);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
28
src/test/run-pass/fn-item-type-cast.rs
Normal file
28
src/test/run-pass/fn-item-type-cast.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T>(x: T, y: T) { }
|
||||||
|
|
||||||
|
static TEST: Option<IntMap> = 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);
|
||||||
|
}
|
23
src/test/run-pass/fn-item-type-coerce.rs
Normal file
23
src/test/run-pass/fn-item-type-coerce.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<T>(x: T, y: T) { }
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let f: IntMap = foo;
|
||||||
|
|
||||||
|
eq::<IntMap>(foo, bar);
|
||||||
|
}
|
@ -12,5 +12,5 @@
|
|||||||
pub fn main() {
|
pub fn main() {
|
||||||
fn f() {
|
fn f() {
|
||||||
};
|
};
|
||||||
let _: Box<fn()> = box f;
|
let _: Box<fn()> = box() (f as fn());
|
||||||
}
|
}
|
||||||
|
@ -25,5 +25,6 @@ fn thing(a: int, b: int) -> int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
let thing: fn(int, int) -> int = thing; // coerce to fn type
|
||||||
bar(&thing);
|
bar(&thing);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user