fn visit_ty(&mut self, t: &ast::Ty, _: ()) {
match t.node {
- ast::TyClosure(closure) if closure.onceness == ast::Once &&
- closure.sigil != ast::OwnedSigil => {
+ ast::TyClosure(closure, _) if closure.onceness == ast::Once => {
self.gate_feature("once_fns", t.span,
"once functions are \
experimental and likely to be removed");
parse_substs(&mut st, conv)
}
-fn parse_sigil(st: &mut PState) -> ast::Sigil {
- match next(st) {
- '@' => ast::ManagedSigil,
- '~' => ast::OwnedSigil,
- '&' => ast::BorrowedSigil,
- c => st.tcx.sess.bug(format!("parse_sigil(): bad input '{}'", c))
- }
-}
-
fn parse_vstore<M>(st: &mut PState, conv: conv_did,
parse_mut: |&mut PState| -> M) -> ty::Vstore<M> {
assert_eq!(next(st), '/');
}
fn parse_closure_ty(st: &mut PState, conv: conv_did) -> ty::ClosureTy {
- let sigil = parse_sigil(st);
let fn_style = parse_fn_style(next(st));
let onceness = parse_onceness(next(st));
- let region = parse_region(st, |x,y| conv(x,y));
+ let store = parse_trait_store(st, |x,y| conv(x,y));
let bounds = parse_bounds(st, |x,y| conv(x,y));
let sig = parse_sig(st, |x,y| conv(x,y));
ty::ClosureTy {
fn_style: fn_style,
- sigil: sigil,
onceness: onceness,
- region: region,
+ store: store,
bounds: bounds.builtin_bounds,
sig: sig
}
}
}
-fn enc_sigil(w: &mut MemWriter, sigil: Sigil) {
- match sigil {
- ManagedSigil => mywrite!(w, "@"),
- OwnedSigil => mywrite!(w, "~"),
- BorrowedSigil => mywrite!(w, "&"),
- }
-}
-
fn enc_fn_style(w: &mut MemWriter, p: FnStyle) {
match p {
NormalFn => mywrite!(w, "n"),
}
fn enc_closure_ty(w: &mut MemWriter, cx: &ctxt, ft: &ty::ClosureTy) {
- enc_sigil(w, ft.sigil);
enc_fn_style(w, ft.fn_style);
enc_onceness(w, ft.onceness);
- enc_region(w, cx, ft.region);
+ enc_trait_store(w, cx, ft.store);
let bounds = ty::ParamBounds {builtin_bounds: ft.bounds,
trait_bounds: Vec::new()};
enc_bounds(w, cx, &bounds);
fn emit_auto_adjustment(&mut self, ecx: &e::EncodeContext, adj: &ty::AutoAdjustment) {
self.emit_enum("AutoAdjustment", |this| {
match *adj {
- ty::AutoAddEnv(region, sigil) => {
- this.emit_enum_variant("AutoAddEnv", 0, 2, |this| {
- this.emit_enum_variant_arg(0, |this| region.encode(this));
- this.emit_enum_variant_arg(1, |this| sigil.encode(this))
+ ty::AutoAddEnv(store) => {
+ this.emit_enum_variant("AutoAddEnv", 0, 1, |this| {
+ this.emit_enum_variant_arg(0, |this| store.encode(this))
})
}
this.read_enum_variant(variants, |this, i| {
Ok(match i {
0 => {
- let region: ty::Region =
+ let store: ty::TraitStore =
this.read_enum_variant_arg(0, |this| Decodable::decode(this)).unwrap();
- let sigil: ast::Sigil =
- this.read_enum_variant_arg(1, |this| Decodable::decode(this)).unwrap();
- ty:: AutoAddEnv(region.tr(xcx), sigil)
+ ty:: AutoAddEnv(store.tr(xcx))
}
1 => {
let auto_deref_ref: ty::AutoDerefRef =
fn move_suggestion(tcx: &ty::ctxt, ty: ty::t, default_msg: &'static str)
-> &'static str {
match ty::get(ty).sty {
- ty::ty_closure(ref cty) if cty.sigil == ast::BorrowedSigil =>
+ ty::ty_closure(~ty::ClosureTy { store: ty::RegionTraitStore(..), .. }) =>
"a non-copyable stack closure (capture it in a new closure, \
e.g. `|x| f(x)`, to override)",
_ if ty::type_moves_by_default(tcx, ty) =>
let fty = ty::node_id_to_type(cx.tcx, id);
match ty::get(fty).sty {
ty::ty_closure(~ty::ClosureTy {
- sigil: OwnedSigil,
- bounds: bounds,
- ..
- }) => {
- b(|cx, fv| check_for_uniq(cx, fv, bounds))
- }
- ty::ty_closure(~ty::ClosureTy {
- sigil: ManagedSigil,
- ..
- }) => {
- // can't happen
- fail!("internal error: saw closure with managed sigil (@fn)");
- }
+ store: ty::UniqTraitStore, bounds, ..
+ }) => b(|cx, fv| check_for_uniq(cx, fv, bounds)),
+
ty::ty_closure(~ty::ClosureTy {
- sigil: BorrowedSigil,
- bounds: bounds,
- region: region,
- ..
- }) => {
- b(|cx, fv| check_for_block(cx, fv, bounds, region))
- }
+ store: ty::RegionTraitStore(region, _), bounds, ..
+ }) => b(|cx, fv| check_for_block(cx, fv, bounds, region)),
+
ty::ty_bare_fn(_) => {
b(check_for_bare)
}
}
ty::ty_uniq(_) | ty::ty_str(ty::VstoreUniq) |
ty::ty_vec(_, ty::VstoreUniq) |
- ty::ty_trait(~ty::TyTrait { store: ty::UniqTraitStore, .. }) => {
- n_uniq += 1;
- }
- ty::ty_closure(ref c) if c.sigil == ast::OwnedSigil => {
+ ty::ty_trait(~ty::TyTrait { store: ty::UniqTraitStore, .. }) |
+ ty::ty_closure(~ty::ClosureTy { store: ty::UniqTraitStore, .. }) => {
n_uniq += 1;
}
ty::ty_trait(~ty::TyTrait { store: ty::UniqTraitStore, .. }) |
ty::ty_vec(_, ty::VstoreUniq) |
ty::ty_str(ty::VstoreUniq) |
- ty::ty_closure(~ty::ClosureTy {sigil: ast::OwnedSigil, ..}) => {
+ ty::ty_closure(~ty::ClosureTy {store: ty::UniqTraitStore, ..}) => {
Some(deref_ptr(OwnedPtr))
}
}
ty::ty_str(ty::VstoreSlice(r, ())) |
- ty::ty_closure(~ty::ClosureTy {sigil: ast::BorrowedSigil,
- region: r, ..}) => {
+ ty::ty_closure(~ty::ClosureTy {store: ty::RegionTraitStore(r, _), ..}) => {
Some(deref_ptr(BorrowedPtr(ty::ImmBorrow, r)))
}
// Decide whether to use implicit reference or by copy/move
// capture for the upvar. This, combined with the onceness,
// determines whether the closure can move out of it.
- let var_is_refd = match (closure_ty.sigil, closure_ty.onceness) {
+ let var_is_refd = match (closure_ty.store, closure_ty.onceness) {
// Many-shot stack closures can never move out.
- (ast::BorrowedSigil, ast::Many) => true,
+ (ty::RegionTraitStore(..), ast::Many) => true,
// 1-shot stack closures can move out.
- (ast::BorrowedSigil, ast::Once) => false,
+ (ty::RegionTraitStore(..), ast::Once) => false,
// Heap closures always capture by copy/move, and can
// move out if they are once.
- (ast::OwnedSigil, _) |
- (ast::ManagedSigil, _) => false,
+ (ty::UniqTraitStore, _) => false,
};
if var_is_refd {
let _indenter = indenter();
let fn_ty = ty::node_id_to_type(self.tcx, fn_expr_id);
- let sigil = ty::ty_closure_sigil(fn_ty);
let freevars = freevars::get_freevars(self.tcx, fn_expr_id);
- let v = if sigil == BorrowedSigil {
- // || captures everything by ref
- freevars.iter()
- .map(|fvar| CaptureVar {def: fvar.def, span: fvar.span, mode: CapRef})
- .collect()
- } else {
- // @fn() and ~fn() capture by copy or by move depending on type
- freevars.iter()
- .map(|fvar| {
- let fvar_def_id = ast_util::def_id_of_def(fvar.def).node;
- let fvar_ty = ty::node_id_to_type(self.tcx, fvar_def_id);
- debug!("fvar_def_id={:?} fvar_ty={}",
- fvar_def_id, ppaux::ty_to_str(self.tcx, fvar_ty));
- let mode = if ty::type_moves_by_default(self.tcx, fvar_ty) {
- CapMove
- } else {
- CapCopy
- };
- CaptureVar {def: fvar.def, span: fvar.span, mode:mode}
-
+ Rc::new(match ty::ty_closure_store(fn_ty) {
+ ty::RegionTraitStore(..) => {
+ // || captures everything by ref
+ freevars.iter()
+ .map(|fvar| CaptureVar {def: fvar.def, span: fvar.span, mode: CapRef})
+ .collect()
+ }
+ ty::UniqTraitStore => {
+ // proc captures by copy or by move depending on type
+ freevars.iter()
+ .map(|fvar| {
+ let fvar_def_id = ast_util::def_id_of_def(fvar.def).node;
+ let fvar_ty = ty::node_id_to_type(self.tcx, fvar_def_id);
+ debug!("fvar_def_id={:?} fvar_ty={}",
+ fvar_def_id, ppaux::ty_to_str(self.tcx, fvar_ty));
+ let mode = if ty::type_moves_by_default(self.tcx, fvar_ty) {
+ CapMove
+ } else {
+ CapCopy
+ };
+ CaptureVar {def: fvar.def, span: fvar.span, mode:mode}
}).collect()
- };
- Rc::new(v)
+ }
+ })
}
}
});
}
- TyClosure(c) => {
+ TyClosure(c, _) | TyProc(c) => {
c.bounds.as_ref().map(|bounds| {
for bound in bounds.iter() {
self.resolve_type_parameter_bound(ty.id, bound);
fn visit_ty(&mut self, ty: &ast::Ty, scope: Scope<'a>) {
match ty.node {
- ast::TyClosure(c) => push_fn_scope(self, ty, scope, &c.lifetimes),
+ ast::TyClosure(c, _) | ast::TyProc(c) => {
+ push_fn_scope(self, ty, scope, &c.lifetimes);
+ }
ast::TyBareFn(c) => push_fn_scope(self, ty, scope, &c.lifetimes),
_ => visit::walk_ty(self, ty, scope),
}
// noalias because the actual object pointer is nested.
ty::ty_uniq(..) | // ty::ty_trait(_, _, ty::UniqTraitStore, _, _) |
ty::ty_vec(_, ty::VstoreUniq) | ty::ty_str(ty::VstoreUniq) |
- ty::ty_closure(~ty::ClosureTy {sigil: ast::OwnedSigil, ..}) => {
+ ty::ty_closure(~ty::ClosureTy {store: ty::UniqTraitStore, ..}) => {
unsafe {
llvm::LLVMAddAttribute(llarg, lib::llvm::NoAliasAttribute as c_uint);
}
}
fn allocate_cbox<'a>(bcx: &'a Block<'a>,
- sigil: ast::Sigil,
+ store: ty::TraitStore,
cdata_ty: ty::t)
-> Result<'a> {
let _icx = push_ctxt("closure::allocate_cbox");
let tcx = bcx.tcx();
// Allocate and initialize the box:
- match sigil {
- ast::ManagedSigil => {
- tcx.sess.bug("trying to trans allocation of @fn")
- }
- ast::OwnedSigil => {
+ match store {
+ ty::UniqTraitStore => {
let ty = type_of(bcx.ccx(), cdata_ty);
let size = llsize_of(bcx.ccx(), ty);
// we treat proc as @ here, which isn't ideal
malloc_raw_dyn_managed(bcx, cdata_ty, ClosureExchangeMallocFnLangItem, size)
}
- ast::BorrowedSigil => {
+ ty::RegionTraitStore(..) => {
let cbox_ty = tuplify_box_ty(tcx, cdata_ty);
let llbox = alloc_ty(bcx, cbox_ty, "__closure");
rslt(bcx, llbox)
pub fn store_environment<'a>(
bcx: &'a Block<'a>,
bound_values: Vec<EnvValue> ,
- sigil: ast::Sigil)
+ store: ty::TraitStore)
-> ClosureResult<'a> {
let _icx = push_ctxt("closure::store_environment");
let ccx = bcx.ccx();
}
// allocate closure in the heap
- let Result {bcx: bcx, val: llbox} = allocate_cbox(bcx, sigil, cdata_ty);
+ let Result {bcx: bcx, val: llbox} = allocate_cbox(bcx, store, cdata_ty);
let llbox = PointerCast(bcx, llbox, llboxptr_ty);
debug!("tuplify_box_ty = {}", ty_to_str(tcx, cbox_ty));
// collects the upvars and packages them up for store_environment.
fn build_closure<'a>(bcx0: &'a Block<'a>,
cap_vars: &[moves::CaptureVar],
- sigil: ast::Sigil)
+ store: ty::TraitStore)
-> ClosureResult<'a> {
let _icx = push_ctxt("closure::build_closure");
let datum = expr::trans_local_var(bcx, cap_var.def);
match cap_var.mode {
moves::CapRef => {
- assert_eq!(sigil, ast::BorrowedSigil);
+ let is_region_closure = match store {
+ ty::RegionTraitStore(..) => true,
+ ty::UniqTraitStore => false
+ };
+ assert!(is_region_closure);
env_vals.push(EnvValue {action: EnvRef,
datum: datum});
}
}
}
- return store_environment(bcx, env_vals, sigil);
+ store_environment(bcx, env_vals, store)
}
// Given an enclosing block context, a new function context, a closure type,
// with the upvars and type descriptors.
fn load_environment<'a>(bcx: &'a Block<'a>, cdata_ty: ty::t,
cap_vars: &[moves::CaptureVar],
- sigil: ast::Sigil) -> &'a Block<'a> {
+ store: ty::TraitStore) -> &'a Block<'a> {
let _icx = push_ctxt("closure::load_environment");
// Don't bother to create the block if there's nothing to load
let mut i = 0u;
for cap_var in cap_vars.iter() {
let mut upvarptr = GEPi(bcx, llcdata, [0u, i]);
- match sigil {
- ast::BorrowedSigil => { upvarptr = Load(bcx, upvarptr); }
- ast::ManagedSigil | ast::OwnedSigil => {}
+ match store {
+ ty::RegionTraitStore(..) => { upvarptr = Load(bcx, upvarptr); }
+ ty::UniqTraitStore => {}
}
let def_id = ast_util::def_id_of_def(cap_var.def);
cdata_ty,
env_pointer_alloca,
i,
- sigil,
+ store,
cap_var.span);
}
pub fn trans_expr_fn<'a>(
bcx: &'a Block<'a>,
- sigil: ast::Sigil,
+ store: ty::TraitStore,
decl: &ast::FnDecl,
body: &ast::Block,
id: ast::NodeId,
*
* Translates the body of a closure expression.
*
- * - `sigil`
+ * - `store`
* - `decl`
* - `body`
* - `id`: The id of the closure expression.
let cap_vars = ccx.maps.capture_map.borrow().get_copy(&id);
let ClosureResult {llbox, cdata_ty, bcx} =
- build_closure(bcx, cap_vars.as_slice(), sigil);
+ build_closure(bcx, cap_vars.as_slice(), store);
trans_closure(ccx, decl, body, llfn,
bcx.fcx.param_substs, id,
[], ty::ty_fn_ret(fty),
- |bcx| load_environment(bcx, cdata_ty, cap_vars.as_slice(), sigil));
+ |bcx| load_environment(bcx, cdata_ty, cap_vars.as_slice(), store));
fill_fn_pair(bcx, dest_addr, llfn, llbox);
bcx
None => { }
Some(adj) => {
match *adj {
- ty::AutoAddEnv(ty::ReStatic, ast::BorrowedSigil) => {
+ ty::AutoAddEnv(ty::RegionTraitStore(ty::ReStatic, _)) => {
let def = ty::resolve_expr(cx.tcx(), e);
let wrapper = closure::get_wrapper_for_bare_fn(cx,
ety_adjusted,
is_local);
llconst = C_struct(cx, [wrapper, C_null(Type::i8p(cx))], false)
}
- ty::AutoAddEnv(ref r, ref s) => {
+ ty::AutoAddEnv(store) => {
cx.sess()
.span_bug(e.span,
- format!("unexpected static function: region \
- {:?} sigil {:?}",
- *r,
- *s))
+ format!("unexpected static function: {:?}",
+ store))
}
ty::AutoObject(..) => {
cx.sess()
env_data_type: ty::t,
env_pointer: ValueRef,
env_index: uint,
- closure_sigil: ast::Sigil,
+ closure_store: ty::TraitStore,
span: Span) {
if fn_should_be_ignored(bcx.fcx) {
return;
llvm::LLVMDIBuilderCreateOpDeref(Type::i64(cx).to_ref())]
};
- let address_op_count = match closure_sigil {
- ast::BorrowedSigil => {
+ let address_op_count = match closure_store {
+ ty::RegionTraitStore(..) => {
address_operations.len()
}
- ast::ManagedSigil | ast::OwnedSigil => {
+ ty::UniqTraitStore => {
address_operations.len() - 1
}
};
ast::ExprFnBlock(decl, body) |
ast::ExprProc(decl, body) => {
let expr_ty = expr_ty(bcx, expr);
- let sigil = ty::ty_closure_sigil(expr_ty);
+ let store = ty::ty_closure_store(expr_ty);
debug!("translating block function {} with type {}",
expr_to_str(expr), expr_ty.repr(tcx));
- closure::trans_expr_fn(bcx, sigil, decl, body, expr.id, dest)
+ closure::trans_expr_fn(bcx, store, decl, body, expr.id, dest)
}
ast::ExprCall(f, ref args) => {
callee::trans_call(bcx, expr, f, callee::ArgExprs(args.as_slice()), dest)
bcx
})
}
- ty::ty_closure(ref f) if f.sigil == ast::OwnedSigil => {
+ ty::ty_closure(ref f) if f.store == ty::UniqTraitStore => {
let box_cell_v = GEPi(bcx, v0, [0u, abi::fn_field_box]);
let env = Load(bcx, box_cell_v);
let env_ptr_ty = Type::at_box(bcx.ccx(), Type::i8(bcx.ccx())).ptr_to();
// FIXME (#4809): visitor should break out bare fns from other fns
ty::ty_closure(ref fty) => {
let pureval = ast_fn_style_constant(fty.fn_style);
- let sigilval = ast_sigil_constant(fty.sigil);
+ let sigilval = match fty.store {
+ ty::UniqTraitStore => 2u,
+ ty::RegionTraitStore(..) => 4u,
+ };
let retval = if ty::type_is_bot(fty.sig.output) {0u} else {1u};
let extra = vec!(self.c_uint(pureval),
self.c_uint(sigilval),
return final;
}
-pub fn ast_sigil_constant(sigil: ast::Sigil) -> uint {
- match sigil {
- ast::OwnedSigil => 2u,
- ast::ManagedSigil => 3u,
- ast::BorrowedSigil => 4u,
- }
-}
-
pub fn ast_fn_style_constant(fn_style: ast::FnStyle) -> uint {
match fn_style {
ast::UnsafeFn => 1u,
}
pub enum AutoAdjustment {
- AutoAddEnv(ty::Region, ast::Sigil),
+ AutoAddEnv(ty::TraitStore),
AutoDerefRef(AutoDerefRef),
AutoObject(ty::TraitStore,
ty::BuiltinBounds,
#[deriving(Clone, Eq, TotalEq, Hash)]
pub struct ClosureTy {
pub fn_style: ast::FnStyle,
- pub sigil: ast::Sigil,
pub onceness: ast::Onceness,
- pub region: Region,
+ pub store: TraitStore,
pub bounds: BuiltinBounds,
pub sig: FnSig,
}
terr_onceness_mismatch(expected_found<Onceness>),
terr_abi_mismatch(expected_found<abi::Abi>),
terr_mutability,
- terr_sigil_mismatch(expected_found<ast::Sigil>),
+ terr_sigil_mismatch(expected_found<TraitStore>),
terr_box_mutability,
terr_ptr_mutability,
terr_ref_mutability,
&ty_param(_) => flags |= has_params as uint,
&ty_infer(_) => flags |= needs_infer as uint,
&ty_self(_) => flags |= has_self as uint,
- &ty_enum(_, ref substs) | &ty_struct(_, ref substs) |
- &ty_trait(~ty::TyTrait { ref substs, .. }) => {
+ &ty_enum(_, ref substs) | &ty_struct(_, ref substs) => {
+ flags |= sflags(substs);
+ }
+ &ty_trait(~ty::TyTrait { ref substs, store, .. }) => {
flags |= sflags(substs);
- match st {
- ty_trait(~ty::TyTrait { store: RegionTraitStore(r, _), .. }) => {
+ match store {
+ RegionTraitStore(r, _) => {
flags |= rflags(r);
}
_ => {}
flags &= !(has_ty_bot as uint);
}
&ty_closure(ref f) => {
- flags |= rflags(f.region);
+ match f.store {
+ RegionTraitStore(r, _) => {
+ flags |= rflags(r);
+ }
+ _ => {}
+ }
for a in f.sig.inputs.iter() { flags |= get(*a).flags; }
flags |= get(f.sig.output).flags;
// T -> _|_ is *not* _|_ !
fn closure_contents(cx: &ctxt, cty: &ClosureTy) -> TypeContents {
// Closure contents are just like trait contents, but with potentially
// even more stuff.
- let st = match cty.sigil {
- ast::BorrowedSigil =>
- object_contents(cx, RegionTraitStore(cty.region, MutMutable), cty.bounds),
- ast::OwnedSigil => object_contents(cx, UniqTraitStore, cty.bounds),
- ast::ManagedSigil => unreachable!()
- };
-
- // FIXME(#3569): This borrowed_contents call should be taken care of in
- // object_contents, after ~Traits and @Traits can have region bounds too.
- // This one here is redundant for &fns but important for ~fns and @fns.
- let rt = borrowed_contents(cty.region, ast::MutImmutable);
+ let st = object_contents(cx, cty.store, cty.bounds);
// This also prohibits "@once fn" from being copied, which allows it to
// be called. Neither way really makes much sense.
ast::Many => TC::None,
};
- st | rt | ot
+ st | ot
}
fn object_contents(cx: &ctxt,
}
}
-pub fn ty_closure_sigil(fty: t) -> Sigil {
+pub fn ty_closure_store(fty: t) -> TraitStore {
match get(fty).sty {
- ty_closure(ref f) => f.sigil,
+ ty_closure(ref f) => f.store,
ref s => {
- fail!("ty_closure_sigil() called on non-closure type: {:?}", s)
+ fail!("ty_closure_store() called on non-closure type: {:?}", s)
}
}
}
return match adjustment {
Some(adjustment) => {
match *adjustment {
- AutoAddEnv(r, s) => {
+ AutoAddEnv(store) => {
match ty::get(unadjusted_ty).sty {
ty::ty_bare_fn(ref b) => {
ty::mk_closure(
cx,
ty::ClosureTy {fn_style: b.fn_style,
- sigil: s,
onceness: ast::Many,
- region: r,
+ store: store,
bounds: ty::AllBuiltinBounds(),
sig: b.sig.clone()})
}
match get(ty).sty {
ty_closure(ref fty) => {
ty::mk_closure(cx, ClosureTy {
- sigil: BorrowedSigil,
- region: r,
+ store: RegionTraitStore(r, ast::MutMutable),
..(**fty).clone()
})
}
}
}
-// Determine what the style to check a nested function under
-pub fn determine_inherited_style(parent: (ast::FnStyle, ast::NodeId),
- child: (ast::FnStyle, ast::NodeId),
- child_sigil: ast::Sigil)
- -> (ast::FnStyle, ast::NodeId) {
- // If the closure is a stack closure and hasn't had some non-standard
- // style inferred for it, then check it under its parent's style.
- // Otherwise, use its own
- match child_sigil {
- ast::BorrowedSigil if child.val0() == ast::NormalFn => parent,
- _ => child
- }
-}
-
// Iterate over a type parameter's bounded traits and any supertraits
// of those traits, ignoring kinds.
// Here, the supertraits are the transitive closure of the supertrait
ty_closure(ref c) => {
byte!(15);
hash!(c.fn_style);
- hash!(c.sigil);
hash!(c.onceness);
hash!(c.bounds);
- region(&mut state, c.region);
+ match c.store {
+ UniqTraitStore => byte!(0),
+ RegionTraitStore(r, m) => {
+ byte!(1)
+ region(&mut state, r);
+ assert_eq!(m, ast::MutMutable);
+ }
+ }
}
ty_trait(~ty::TyTrait { def_id: d, store, bounds, .. }) => {
byte!(17);
fty: &ty::ClosureTy)
-> ty::ClosureTy {
ty::ClosureTy {
- region: self.fold_region(fty.region),
+ store: self.fold_trait_store(fty.store),
sig: self.fold_sig(&fty.sig),
fn_style: fty.fn_style,
- sigil: fty.sigil,
onceness: fty.onceness,
bounds: fty.bounds,
}
r
}
-fn opt_ast_region_to_region<AC:AstConv,RS:RegionScope>(
+pub fn opt_ast_region_to_region<AC:AstConv,RS:RegionScope>(
this: &AC,
rscope: &RS,
default_span: Span,
ty::mk_bare_fn(tcx, ty_of_bare_fn(this, ast_ty.id, bf.fn_style,
bf.abi, bf.decl))
}
- ast::TyClosure(ref f) => {
- if f.sigil == ast::ManagedSigil {
- tcx.sess.span_err(ast_ty.span,
- "managed closures are not supported");
- }
+ ast::TyClosure(ref f, ref region) => {
+
+ // resolve the function bound region in the original region
+ // scope `rscope`, not the scope of the function parameters
+ let bound_region = opt_ast_region_to_region(this, rscope,
+ ast_ty.span, region);
+
+ let store = ty::RegionTraitStore(bound_region, ast::MutMutable);
+
+ // Use corresponding trait store to figure out default bounds
+ // if none were specified.
+ let bounds = conv_builtin_bounds(this.tcx(), &f.bounds, store);
- let bounds = conv_builtin_bounds(this.tcx(), &f.bounds, match f.sigil {
- // Use corresponding trait store to figure out default bounds
- // if none were specified.
- ast::BorrowedSigil => {
- // dummy region
- ty::RegionTraitStore(ty::ReEmpty, ast::MutMutable)
- }
- ast::OwnedSigil => ty::UniqTraitStore,
- ast::ManagedSigil => return ty::mk_err()
- });
let fn_decl = ty_of_closure(this,
- rscope,
ast_ty.id,
- f.sigil,
f.fn_style,
f.onceness,
bounds,
- &f.region,
+ store,
f.decl,
- None,
- ast_ty.span);
+ None);
+ ty::mk_closure(tcx, fn_decl)
+ }
+ ast::TyProc(ref f) => {
+ // Use corresponding trait store to figure out default bounds
+ // if none were specified.
+ let bounds = conv_builtin_bounds(this.tcx(), &f.bounds, ty::UniqTraitStore);
+
+ let fn_decl = ty_of_closure(this,
+ ast_ty.id,
+ f.fn_style,
+ f.onceness,
+ bounds,
+ ty::UniqTraitStore,
+ f.decl,
+ None);
ty::mk_closure(tcx, fn_decl)
}
ast::TyPath(ref path, ref bounds, id) => {
};
}
-pub fn ty_of_closure<AC:AstConv,RS:RegionScope>(
+pub fn ty_of_closure<AC:AstConv>(
this: &AC,
- rscope: &RS,
id: ast::NodeId,
- sigil: ast::Sigil,
fn_style: ast::FnStyle,
onceness: ast::Onceness,
bounds: ty::BuiltinBounds,
- opt_lifetime: &Option<ast::Lifetime>,
+ store: ty::TraitStore,
decl: &ast::FnDecl,
- expected_sig: Option<ty::FnSig>,
- span: Span)
+ expected_sig: Option<ty::FnSig>)
-> ty::ClosureTy
{
debug!("ty_of_fn_decl");
- // resolve the function bound region in the original region
- // scope `rscope`, not the scope of the function parameters
- let bound_region = match opt_lifetime {
- &Some(ref lifetime) => {
- ast_region_to_region(this.tcx(), lifetime)
- }
- &None => {
- match sigil {
- ast::OwnedSigil | ast::ManagedSigil => {
- // @fn(), ~fn() default to static as the bound
- // on their upvars:
- ty::ReStatic
- }
- ast::BorrowedSigil => {
- // || defaults as normal for an omitted lifetime:
- opt_ast_region_to_region(this, rscope, span, opt_lifetime)
- }
- }
- }
- };
-
// new region names that appear inside of the fn decl are bound to
// that function type
let rb = rscope::BindingRscope::new(id);
ty::ClosureTy {
fn_style: fn_style,
- sigil: sigil,
onceness: onceness,
- region: bound_region,
+ store: store,
bounds: bounds,
sig: ty::FnSig {binder_id: id,
inputs: input_tys,
fn check_expr_fn(fcx: &FnCtxt,
expr: &ast::Expr,
- ast_sigil_opt: Option<ast::Sigil>,
+ store: ty::TraitStore,
decl: &ast::FnDecl,
body: ast::P<ast::Block>,
fn_kind: FnKind,
// Find the expected input/output types (if any). Substitute
// fresh bound regions for any bound regions we find in the
// expected types so as to avoid capture.
- //
- // Also try to pick up inferred style and sigil, defaulting
- // to impure and block. Note that we only will use those for
- // block syntax lambdas; that is, lambdas without explicit
- // sigils.
let expected_sty = unpack_expected(fcx,
expected,
|x| Some((*x).clone()));
let error_happened = false;
let (expected_sig,
- expected_style,
- expected_sigil,
expected_onceness,
expected_bounds) = {
match expected_sty {
replace_late_bound_regions_in_fn_sig(
tcx, &cenv.sig,
|_| fcx.inh.infcx.fresh_bound_region(expr.id));
- (Some(sig), cenv.fn_style, cenv.sigil,
- cenv.onceness, cenv.bounds)
+ (Some(sig), cenv.onceness, cenv.bounds)
}
_ => {
// Not an error! Means we're inferring the closure type
- let mut sigil = ast::BorrowedSigil;
- let mut onceness = ast::Many;
let mut bounds = ty::EmptyBuiltinBounds();
- match expr.node {
+ let onceness = match expr.node {
ast::ExprProc(..) => {
- sigil = ast::OwnedSigil;
- onceness = ast::Once;
bounds.add(ty::BoundSend);
+ ast::Once
}
- _ => ()
- }
- (None, ast::NormalFn, sigil,
- onceness, bounds)
+ _ => ast::Many
+ };
+ (None, onceness, bounds)
}
}
};
- // If the proto is specified, use that, otherwise select a
- // proto based on inference.
- let (sigil, fn_style) = match ast_sigil_opt {
- Some(p) => (p, ast::NormalFn),
- None => (expected_sigil, expected_style)
- };
-
// construct the function type
let fn_ty = astconv::ty_of_closure(fcx,
- fcx.infcx(),
expr.id,
- sigil,
- fn_style,
+ ast::NormalFn,
expected_onceness,
expected_bounds,
- &None,
+ store,
decl,
- expected_sig,
- expr.span);
+ expected_sig);
let fty_sig;
let fty = if error_happened {
};
ty::mk_err()
} else {
- let fn_ty_copy = fn_ty.clone();
fty_sig = fn_ty.sig.clone();
- ty::mk_closure(tcx, fn_ty_copy)
+ ty::mk_closure(tcx, fn_ty.clone())
};
debug!("check_expr_fn_with_unifier fty={}",
fcx.write_ty(expr.id, fty);
- let (inherited_style, id) =
- ty::determine_inherited_style((fcx.ps.borrow().fn_style,
- fcx.ps.borrow().def),
- (fn_style, expr.id),
- sigil);
+ // If the closure is a stack closure and hasn't had some non-standard
+ // style inferred for it, then check it under its parent's style.
+ // Otherwise, use its own
+ let (inherited_style, id) = match store {
+ ty::RegionTraitStore(..) => (fcx.ps.borrow().fn_style,
+ fcx.ps.borrow().def),
+ ty::UniqTraitStore => (ast::NormalFn, expr.id)
+ };
check_fn(fcx.ccx, inherited_style, &fty_sig,
decl, id, body, fn_kind, fcx.inh);
_match::check_match(fcx, expr, discrim, arms.as_slice());
}
ast::ExprFnBlock(decl, body) => {
+ let region = astconv::opt_ast_region_to_region(fcx,
+ fcx.infcx(),
+ expr.span,
+ &None);
check_expr_fn(fcx,
expr,
- Some(ast::BorrowedSigil),
+ ty::RegionTraitStore(region, ast::MutMutable),
decl,
body,
Vanilla,
ast::ExprProc(decl, body) => {
check_expr_fn(fcx,
expr,
- Some(ast::OwnedSigil),
+ ty::UniqTraitStore,
decl,
body,
Vanilla,
use middle::pat_util;
use util::ppaux::{ty_to_str, region_to_str, Repr};
-use syntax::ast::{ManagedSigil, OwnedSigil, BorrowedSigil};
use syntax::ast::{DefArg, DefBinding, DefLocal, DefUpvar};
use syntax::ast;
use syntax::ast_util;
tcx.region_maps.var_region(node_id)
}
DefUpvar(_, subdef, closure_id, body_id) => {
- match ty::ty_closure_sigil(fcx.node_ty(closure_id)) {
- BorrowedSigil => region_of_def(fcx, *subdef),
- ManagedSigil | OwnedSigil => ReScope(body_id)
+ match ty::ty_closure_store(fcx.node_ty(closure_id)) {
+ ty::RegionTraitStore(..) => region_of_def(fcx, *subdef),
+ ty::UniqTraitStore => ReScope(body_id)
}
}
_ => {
let function_type = rcx.resolve_node_type(expr.id);
match ty::get(function_type).sty {
ty::ty_closure(~ty::ClosureTy {
- sigil: ast::BorrowedSigil, region: region, ..}) => {
+ store: ty::RegionTraitStore(region, _), ..}) => {
let freevars = freevars::get_freevars(tcx, expr.id);
if freevars.is_empty() {
// No free variables means that the environment
rcx.set_repeating_scope(repeating_scope);
match ty::get(function_type).sty {
- ty::ty_closure(~ty::ClosureTy {sigil: ast::BorrowedSigil, ..}) => {
+ ty::ty_closure(~ty::ClosureTy {store: ty::RegionTraitStore(..), ..}) => {
let freevars = freevars::get_freevars(tcx, expr.id);
propagate_upupvar_borrow_kind(rcx, expr, freevars);
}
match ty::get(callee_ty).sty {
ty::ty_bare_fn(..) => { }
ty::ty_closure(ref closure_ty) => {
+ let region = match closure_ty.store {
+ ty::RegionTraitStore(r, _) => r,
+ ty::UniqTraitStore => ty::ReStatic
+ };
rcx.fcx.mk_subr(true, infer::InvokeClosure(callee_expr.span),
- call_region, closure_ty.region);
+ call_region, region);
}
_ => {
// this should not happen, but it does if the program is
Some(adjustment) => {
match *adjustment {
- ty::AutoAddEnv(r, s) => {
+ ty::AutoAddEnv(store) => {
+ let r = match store {
+ ty::RegionTraitStore(r, _) => r,
+ ty::UniqTraitStore => ty::ReStatic
+ };
match resolve_region(fcx.infcx(),
r,
resolve_all | force_all) {
"cannot coerce non-statically resolved bare fn")
}
- let resolved_adj = @ty::AutoAddEnv(r1, s);
+ let resolved_adj = @ty::AutoAddEnv(match store {
+ ty::RegionTraitStore(..) => {
+ ty::RegionTraitStore(r1, ast::MutMutable)
+ }
+ ty::UniqTraitStore => ty::UniqTraitStore
+ });
debug!("Adjustments for node {}: {:?}",
id, resolved_adj);
tcx.adjustments.borrow_mut().insert(id, resolved_adj);
});
}
- ty::ty_closure(~ty::ClosureTy {sigil: ast::BorrowedSigil, ..}) => {
+ ty::ty_closure(~ty::ClosureTy {store: ty::RegionTraitStore(..), ..}) => {
return self.unpack_actual_value(a, |sty_a| {
self.coerce_borrowed_fn(a, sty_a, b)
});
b.inf_str(self.get_ref().infcx));
let fn_ty = match *sty_a {
- ty::ty_closure(ref f) if f.sigil == ast::ManagedSigil ||
- f.sigil == ast::OwnedSigil => {
+ ty::ty_closure(ref f) if f.store == ty::UniqTraitStore => {
(*f).clone()
}
ty::ty_bare_fn(ref f) => {
let a_borrowed = ty::mk_closure(
self.get_ref().infcx.tcx,
ty::ClosureTy {
- sigil: ast::BorrowedSigil,
- region: r_borrow,
+ store: ty::RegionTraitStore(r_borrow, ast::MutMutable),
.. *fn_ty
});
_ => return self.subtype(a, b)
};
- let adj = @ty::AutoAddEnv(fn_ty_b.region, fn_ty_b.sigil);
+ let adj = @ty::AutoAddEnv(fn_ty_b.store);
let a_closure = ty::mk_closure(self.get_ref().infcx.tcx,
ty::ClosureTy {
sig: fn_ty_a.sig.clone(),
fn closure_tys(&self, a: &ty::ClosureTy,
b: &ty::ClosureTy) -> cres<ty::ClosureTy> {
- let p = if_ok!(self.sigils(a.sigil, b.sigil));
- let r = if_ok!(self.contraregions(a.region, b.region));
+ let store = match (a.store, b.store) {
+ (ty::RegionTraitStore(a_r, a_m),
+ ty::RegionTraitStore(b_r, b_m)) if a_m == b_m => {
+ let r = if_ok!(self.contraregions(a_r, b_r));
+ ty::RegionTraitStore(r, a_m)
+ }
+
+ _ if a.store == b.store => {
+ a.store
+ }
+
+ _ => {
+ return Err(ty::terr_sigil_mismatch(expected_found(self, a.store, b.store)))
+ }
+ };
let fn_style = if_ok!(self.fn_styles(a.fn_style, b.fn_style));
let onceness = if_ok!(self.oncenesses(a.onceness, b.onceness));
let bounds = if_ok!(self.bounds(a.bounds, b.bounds));
let sig = if_ok!(self.fn_sigs(&a.sig, &b.sig));
- Ok(ty::ClosureTy {fn_style: fn_style,
- sigil: p,
- onceness: onceness,
- region: r,
- bounds: bounds,
- sig: sig})
+ Ok(ty::ClosureTy {
+ fn_style: fn_style,
+ onceness: onceness,
+ store: store,
+ bounds: bounds,
+ sig: sig
+ })
}
fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig>;
self.contratys(a, b).and_then(|t| Ok(t))
}
- fn sigils(&self, p1: ast::Sigil, p2: ast::Sigil) -> cres<ast::Sigil> {
- if p1 == p2 {
- Ok(p1)
- } else {
- Err(ty::terr_sigil_mismatch(expected_found(self, p1, p2)))
- }
- }
-
fn fn_styles(&self, a: FnStyle, b: FnStyle) -> cres<FnStyle>;
fn abi(&self, a: abi::Abi, b: abi::Abi) -> cres<abi::Abi> {
self.add_constraint(index, variance);
}
- ty::ty_bare_fn(ty::BareFnTy { sig: ref sig, .. }) => {
+ ty::ty_bare_fn(ty::BareFnTy { ref sig, .. }) |
+ ty::ty_closure(~ty::ClosureTy { ref sig, store: ty::UniqTraitStore, .. }) => {
self.add_constraints_from_sig(sig, variance);
}
- ty::ty_closure(~ty::ClosureTy { sig: ref sig, region, .. }) => {
+ ty::ty_closure(~ty::ClosureTy { ref sig,
+ store: ty::RegionTraitStore(region, _), .. }) => {
let contra = self.contravariant(variance);
self.add_constraints_from_region(region, contra);
self.add_constraints_from_sig(sig, variance);
}
fn closure_to_str(cx: &ctxt, cty: &ty::ClosureTy) -> ~str {
- let is_proc =
- (cty.sigil, cty.onceness) == (ast::OwnedSigil, ast::Once);
- let is_borrowed_closure = cty.sigil == ast::BorrowedSigil;
+ let mut s = StrBuf::new();
- let mut s = if is_proc || is_borrowed_closure {
- StrBuf::new()
- } else {
- StrBuf::from_owned_str(cty.sigil.to_str())
- };
-
- match (cty.sigil, cty.region) {
- (ast::ManagedSigil, ty::ReStatic) |
- (ast::OwnedSigil, ty::ReStatic) => {}
-
- (_, region) => {
+ match cty.store {
+ ty::UniqTraitStore => {}
+ ty::RegionTraitStore(region, _) => {
s.push_str(region_to_str(cx, "", true, region));
}
}
}
};
- if is_proc {
- s.push_str("proc");
- } else {
- match cty.onceness {
- ast::Many => {}
- ast::Once => {
- s.push_str(cty.onceness.to_str());
- s.push_char(' ');
+ match cty.store {
+ ty::UniqTraitStore => {
+ assert_eq!(cty.onceness, ast::Once);
+ s.push_str("proc");
+ push_sig_to_str(cx, &mut s, '(', ')', &cty.sig);
+ }
+ ty::RegionTraitStore(..) => {
+ match cty.onceness {
+ ast::Many => {}
+ ast::Once => s.push_str("once ")
}
- };
-
- if !is_borrowed_closure {
- s.push_str("fn");
+ push_sig_to_str(cx, &mut s, '|', '|', &cty.sig);
}
}
- if !is_borrowed_closure {
- // Print bounds before `fn` if this is not a borrowed closure.
- if !cty.bounds.is_empty() {
- s.push_str(":");
- s.push_str(cty.bounds.repr(cx));
- }
-
- push_sig_to_str(cx, &mut s, '(', ')', &cty.sig);
- } else {
- // Print bounds after the signature if this is a borrowed closure.
- push_sig_to_str(cx, &mut s, '|', '|', &cty.sig);
-
- if is_borrowed_closure {
- if !cty.bounds.is_empty() {
- s.push_str(":");
- s.push_str(cty.bounds.repr(cx));
- }
- }
+ if !cty.bounds.is_empty() {
+ s.push_str(":");
+ s.push_str(cty.bounds.repr(cx));
}
s.into_owned()