mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-31 06:22:00 +00:00
more sound treatment of fn& regions; change all & to be distinct
This commit is contained in:
parent
8ee79c79aa
commit
652b312122
@ -29,7 +29,7 @@ pure fn get<T: copy>(opt: option<T>) -> T {
|
||||
}
|
||||
}
|
||||
|
||||
pure fn get_ref<T>(opt: &option<T>) -> &T {
|
||||
pure fn get_ref<T>(opt: &r/option<T>) -> &r/T {
|
||||
/*!
|
||||
* Gets an immutable reference to the value inside an option.
|
||||
*
|
||||
|
@ -361,7 +361,7 @@ impl<T: const send> &rw_arc<T> {
|
||||
}
|
||||
|
||||
/// To be called inside of the write_downgrade block.
|
||||
fn downgrade(+token: rw_write_mode<T>) -> rw_read_mode<T> {
|
||||
fn downgrade(+token: rw_write_mode/&a<T>) -> rw_read_mode/&a<T> {
|
||||
// The rwlock should assert that the token belongs to us for us.
|
||||
let state = unsafe { get_shared_immutable_state(&self.x) };
|
||||
let rw_write_mode((data, t, _poison)) = token;
|
||||
|
@ -538,7 +538,7 @@ impl &rwlock {
|
||||
}
|
||||
|
||||
/// To be called inside of the write_downgrade block.
|
||||
fn downgrade(+token: rwlock_write_mode) -> rwlock_read_mode {
|
||||
fn downgrade(+token: rwlock_write_mode/&a) -> rwlock_read_mode/&a {
|
||||
if !ptr::ref_eq(self, token.lock) {
|
||||
fail ~"Can't downgrade() with a different rwlock's write_mode!";
|
||||
}
|
||||
|
@ -84,9 +84,10 @@ enum def {
|
||||
def_ty_param(def_id, uint),
|
||||
def_binding(node_id, binding_mode),
|
||||
def_use(def_id),
|
||||
def_upvar(node_id /* local id of closed over var */,
|
||||
def_upvar(node_id /* id of closed over var */,
|
||||
@def /* closed over def */,
|
||||
node_id /* expr node that creates the closure */),
|
||||
node_id /* expr node that creates the closure */,
|
||||
node_id /* id for the block/body of the closure expr */),
|
||||
def_class(def_id, bool /* has constructor */),
|
||||
def_typaram_binder(node_id), /* class, impl or trait that has ty params */
|
||||
def_region(node_id),
|
||||
|
@ -60,7 +60,7 @@ pure fn def_id_of_def(d: def) -> def_id {
|
||||
id
|
||||
}
|
||||
def_arg(id, _) | def_local(id, _) | def_self(id) |
|
||||
def_upvar(id, _, _) | def_binding(id, _) | def_region(id)
|
||||
def_upvar(id, _, _, _) | def_binding(id, _) | def_region(id)
|
||||
| def_typaram_binder(id) | def_label(id) => {
|
||||
local_def(id)
|
||||
}
|
||||
@ -381,9 +381,9 @@ impl inlined_item: inlined_item_utils {
|
||||
referring to a def_self */
|
||||
fn is_self(d: ast::def) -> bool {
|
||||
match d {
|
||||
def_self(_) => true,
|
||||
def_upvar(_, d, _) => is_self(*d),
|
||||
_ => false
|
||||
def_self(_) => true,
|
||||
def_upvar(_, d, _, _) => is_self(*d),
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -207,9 +207,6 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
|
||||
|
||||
if upto == cu_typeck { return {crate: crate, tcx: some(ty_cx)}; }
|
||||
|
||||
time(time_passes, ~"block-use checking", ||
|
||||
middle::block_use::check_crate(ty_cx, crate));
|
||||
|
||||
time(time_passes, ~"loop checking", ||
|
||||
middle::check_loop::check_crate(ty_cx, crate));
|
||||
|
||||
|
@ -128,7 +128,11 @@ fn parse_substs(st: @pstate, conv: conv_did) -> ty::substs {
|
||||
fn parse_bound_region(st: @pstate) -> ty::bound_region {
|
||||
match check next(st) {
|
||||
's' => ty::br_self,
|
||||
'a' => ty::br_anon,
|
||||
'a' => {
|
||||
let id = parse_int(st) as uint;
|
||||
assert next(st) == '|';
|
||||
ty::br_anon(id)
|
||||
}
|
||||
'[' => ty::br_named(@parse_str(st, ']')),
|
||||
'c' => {
|
||||
let id = parse_int(st);
|
||||
|
@ -154,7 +154,11 @@ fn enc_region(w: io::Writer, cx: @ctxt, r: ty::region) {
|
||||
fn enc_bound_region(w: io::Writer, br: ty::bound_region) {
|
||||
match br {
|
||||
ty::br_self => w.write_char('s'),
|
||||
ty::br_anon => w.write_char('a'),
|
||||
ty::br_anon(idx) => {
|
||||
w.write_char('a');
|
||||
w.write_uint(idx);
|
||||
w.write_char('|');
|
||||
}
|
||||
ty::br_named(s) => {
|
||||
w.write_char('[');
|
||||
w.write_str(*s);
|
||||
|
@ -363,8 +363,11 @@ impl ast::def: tr {
|
||||
ast::def_ty_param(did, v) => ast::def_ty_param(did.tr(xcx), v),
|
||||
ast::def_binding(nid, bm) => ast::def_binding(xcx.tr_id(nid), bm),
|
||||
ast::def_use(did) => ast::def_use(did.tr(xcx)),
|
||||
ast::def_upvar(nid1, def, nid2) => {
|
||||
ast::def_upvar(xcx.tr_id(nid1), @(*def).tr(xcx), xcx.tr_id(nid2))
|
||||
ast::def_upvar(nid1, def, nid2, nid3) => {
|
||||
ast::def_upvar(xcx.tr_id(nid1),
|
||||
@(*def).tr(xcx),
|
||||
xcx.tr_id(nid2),
|
||||
xcx.tr_id(nid3))
|
||||
}
|
||||
ast::def_class(did, has_constructor) => {
|
||||
ast::def_class(did.tr(xcx), has_constructor)
|
||||
|
@ -1,47 +0,0 @@
|
||||
import syntax::visit;
|
||||
import syntax::ast::*;
|
||||
import driver::session::session;
|
||||
|
||||
type ctx = {tcx: ty::ctxt, mut allow_block: bool};
|
||||
|
||||
fn check_crate(tcx: ty::ctxt, crate: @crate) {
|
||||
let cx = {tcx: tcx, mut allow_block: false};
|
||||
let v = visit::mk_vt(@{visit_expr: visit_expr
|
||||
with *visit::default_visitor()});
|
||||
visit::visit_crate(*crate, cx, v);
|
||||
}
|
||||
|
||||
fn visit_expr(ex: @expr, cx: ctx, v: visit::vt<ctx>) {
|
||||
if !cx.allow_block {
|
||||
match ty::get(ty::expr_ty(cx.tcx, ex)).struct {
|
||||
ty::ty_fn({proto: p, _}) if ty::is_blockish(p) => {
|
||||
cx.tcx.sess.span_err(ex.span,
|
||||
~"expressions with stack closure type \
|
||||
can only appear in callee or (by-ref) argument position");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
let outer = cx.allow_block;
|
||||
match ex.node {
|
||||
expr_call(f, args, _) => {
|
||||
cx.allow_block = true;
|
||||
v.visit_expr(f, cx, v);
|
||||
let mut i = 0u;
|
||||
for ty::ty_fn_args(ty::expr_ty(cx.tcx, f)).each |arg_t| {
|
||||
cx.allow_block = (ty::arg_mode(cx.tcx, arg_t) == by_ref);
|
||||
v.visit_expr(args[i], cx, v);
|
||||
i += 1u;
|
||||
}
|
||||
}
|
||||
expr_loop_body(body) | expr_do_body(body) => {
|
||||
cx.allow_block = true;
|
||||
v.visit_expr(body, cx, v);
|
||||
}
|
||||
_ => {
|
||||
cx.allow_block = false;
|
||||
visit::visit_expr(ex, cx, v);
|
||||
}
|
||||
}
|
||||
cx.allow_block = outer;
|
||||
}
|
@ -55,7 +55,7 @@ fn collect_freevars(def_map: resolve3::DefMap, blk: ast::blk)
|
||||
let mut def = df;
|
||||
while i < depth {
|
||||
match copy def {
|
||||
ast::def_upvar(_, inner, _) => { def = *inner; }
|
||||
ast::def_upvar(_, inner, _, _) => { def = *inner; }
|
||||
_ => break
|
||||
}
|
||||
i += 1;
|
||||
|
@ -103,7 +103,7 @@ fn with_appropriate_checker(cx: ctx, id: node_id, b: fn(check_fn)) {
|
||||
|
||||
// copied in data must be copyable, but moved in data can be anything
|
||||
let is_implicit = fv.is_some();
|
||||
if !is_move { check_copy(cx, id, var_t, sp, is_implicit); }
|
||||
if !is_move { check_copy(cx, id, var_t, sp, is_implicit); }
|
||||
|
||||
// check that only immutable variables are implicitly copied in
|
||||
for fv.each |fv| {
|
||||
@ -426,7 +426,7 @@ fn check_imm_free_var(cx: ctx, def: def, sp: span) {
|
||||
}
|
||||
}
|
||||
}
|
||||
def_upvar(_, def1, _) => {
|
||||
def_upvar(_, def1, _, _) => {
|
||||
check_imm_free_var(cx, *def1, sp);
|
||||
}
|
||||
def_binding(*) | def_self(*) => { /*ok*/ }
|
||||
|
@ -378,7 +378,7 @@ impl &mem_categorization_ctxt {
|
||||
mutbl:m_imm, ty:expr_ty}
|
||||
}
|
||||
|
||||
ast::def_upvar(upvid, inner, fn_node_id) => {
|
||||
ast::def_upvar(upvid, inner, fn_node_id, _) => {
|
||||
let ty = ty::node_id_to_type(self.tcx, fn_node_id);
|
||||
let proto = ty::ty_fn_proto(ty);
|
||||
match proto {
|
||||
|
@ -199,7 +199,7 @@ enum RibKind {
|
||||
|
||||
// We passed through a function scope at the given node ID. Translate
|
||||
// upvars as appropriate.
|
||||
FunctionRibKind(node_id),
|
||||
FunctionRibKind(node_id /* func id */, node_id /* body id */),
|
||||
|
||||
// We passed through a class, impl, or trait and are now in one of its
|
||||
// methods. Allow references to ty params that that class, impl or trait
|
||||
@ -2752,11 +2752,12 @@ struct Resolver {
|
||||
NormalRibKind => {
|
||||
// Nothing to do. Continue.
|
||||
}
|
||||
FunctionRibKind(function_id) => {
|
||||
FunctionRibKind(function_id, body_id) => {
|
||||
if !is_ty_param {
|
||||
def = def_upvar(def_id_of_def(def).node,
|
||||
@def,
|
||||
function_id);
|
||||
function_id,
|
||||
body_id);
|
||||
}
|
||||
}
|
||||
MethodRibKind(item_id, method_id) => {
|
||||
@ -4164,7 +4165,7 @@ struct Resolver {
|
||||
|
||||
expr_fn(_, fn_decl, block, capture_clause) |
|
||||
expr_fn_block(fn_decl, block, capture_clause) => {
|
||||
self.resolve_function(FunctionRibKind(expr.id),
|
||||
self.resolve_function(FunctionRibKind(expr.id, block.node.id),
|
||||
some(@fn_decl),
|
||||
NoTypeParameters,
|
||||
block,
|
||||
|
@ -2464,7 +2464,7 @@ fn trans_local_var(cx: block, def: ast::def) -> local_var_result {
|
||||
}
|
||||
}
|
||||
match def {
|
||||
ast::def_upvar(nid, _, _) => {
|
||||
ast::def_upvar(nid, _, _, _) => {
|
||||
assert (cx.fcx.llupvars.contains_key(nid));
|
||||
return { val: cx.fcx.llupvars.get(nid), kind: lv_owned };
|
||||
}
|
||||
|
@ -961,7 +961,8 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item,
|
||||
let fty = ty::mk_fn(bcx.tcx(), {
|
||||
purity: ast::impure_fn,
|
||||
proto:
|
||||
ty::proto_vstore(ty::vstore_slice(ty::re_bound(ty::br_anon))),
|
||||
ty::proto_vstore(ty::vstore_slice(
|
||||
ty::re_bound(ty::br_anon(0)))),
|
||||
bounds: @~[],
|
||||
inputs: ~[{
|
||||
mode: ast::expl(ast::by_val),
|
||||
|
@ -525,7 +525,7 @@ fn expr_to_constr_arg(tcx: ty::ctxt, e: @expr) -> @constr_arg_use {
|
||||
expr_path(p) {
|
||||
match tcx.def_map.find(e.id) {
|
||||
some(def_local(nid, _)) | some(def_arg(nid, _)) |
|
||||
some(def_binding(nid, _)) | some(def_upvar(nid, _, _)) {
|
||||
some(def_binding(nid, _)) | some(def_upvar(nid, _, _, _)) {
|
||||
return @respan(p.span,
|
||||
carg_ident({ident: p.idents[0], node: nid}));
|
||||
}
|
||||
|
@ -377,8 +377,8 @@ enum bound_region {
|
||||
/// The self region for classes, impls (&T in a type defn or &self/T)
|
||||
br_self,
|
||||
|
||||
/// Anonymous region parameter for a given fn (&T)
|
||||
br_anon,
|
||||
/// An anonymous region parameter for a given fn (&T)
|
||||
br_anon(uint),
|
||||
|
||||
/// Named region parameters for functions (a in &a/T)
|
||||
br_named(ast::ident),
|
||||
@ -2192,9 +2192,10 @@ fn index_sty(cx: ctxt, sty: &sty) -> option<mt> {
|
||||
pure fn hash_bound_region(br: &bound_region) -> uint {
|
||||
match *br { // no idea if this is any good
|
||||
ty::br_self => 0u,
|
||||
ty::br_anon => 1u,
|
||||
ty::br_named(str) => str::hash(str),
|
||||
ty::br_cap_avoid(id, br) => id as uint | hash_bound_region(br)
|
||||
ty::br_anon(idx) => 1u | (idx << 2),
|
||||
ty::br_named(str) => 2u | (str::hash(str) << 2),
|
||||
ty::br_cap_avoid(id, br) =>
|
||||
3u | (id as uint << 2) | hash_bound_region(br)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2304,7 +2304,7 @@ fn ty_param_bounds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) ->
|
||||
ast::def_ty(_) | ast::def_prim_ty(_) => {
|
||||
fcx.ccx.tcx.sess.span_fatal(sp, ~"expected value but found type");
|
||||
}
|
||||
ast::def_upvar(_, inner, _) => {
|
||||
ast::def_upvar(_, inner, _, _) => {
|
||||
return ty_param_bounds_and_ty_for_def(fcx, sp, *inner);
|
||||
}
|
||||
ast::def_ty_param(did, n) => {
|
||||
@ -2513,7 +2513,8 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) {
|
||||
let fty = ty::mk_fn(ccx.tcx, {
|
||||
purity: ast::impure_fn,
|
||||
proto:
|
||||
ty::proto_vstore(ty::vstore_slice(ty::re_bound(ty::br_anon))),
|
||||
ty::proto_vstore(ty::vstore_slice(
|
||||
ty::re_bound(ty::br_anon(0)))),
|
||||
bounds: @~[],
|
||||
inputs: ~[{
|
||||
mode: ast::expl(ast::by_val),
|
||||
|
@ -21,12 +21,42 @@ import util::ppaux;
|
||||
import ppaux::{note_and_explain_region, ty_to_str};
|
||||
import syntax::print::pprust;
|
||||
import infer::{resolve_and_force_all_but_regions, fres};
|
||||
import syntax::ast::{def_arg, def_binding, def_local, def_self, def_upvar};
|
||||
import middle::freevars::get_freevars;
|
||||
import middle::kind::check_owned;
|
||||
import middle::pat_util::pat_bindings;
|
||||
import middle::ty::{encl_region, proto_bare, proto_vstore, re_scope};
|
||||
import middle::ty::{ty_fn_proto, vstore_box, vstore_fixed, vstore_slice};
|
||||
import middle::ty::{vstore_uniq};
|
||||
|
||||
enum rcx { rcx_({fcx: @fn_ctxt, mut errors_reported: uint}) }
|
||||
type rvt = visit::vt<@rcx>;
|
||||
|
||||
fn encl_region_of_def(fcx: @fn_ctxt, def: ast::def) -> ty::region {
|
||||
let tcx = fcx.tcx();
|
||||
match def {
|
||||
def_local(node_id, _) | def_arg(node_id, _) | def_self(node_id) |
|
||||
def_binding(node_id, _) =>
|
||||
return encl_region(tcx, node_id),
|
||||
def_upvar(local_id, subdef, closure_id, body_id) => {
|
||||
match ty_fn_proto(fcx.node_ty(closure_id)) {
|
||||
proto_bare =>
|
||||
tcx.sess.bug(~"proto_bare in encl_region_of_def?!"),
|
||||
proto_vstore(vstore_fixed(_)) =>
|
||||
tcx.sess.bug(~"vstore_fixed in encl_region_of_def?!"),
|
||||
proto_vstore(vstore_slice(_)) =>
|
||||
encl_region_of_def(fcx, *subdef),
|
||||
proto_vstore(vstore_uniq) | proto_vstore(vstore_box) =>
|
||||
re_scope(body_id)
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
tcx.sess.bug(fmt!("unexpected def in encl_region_of_def: %?",
|
||||
def))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl @rcx {
|
||||
/// Try to resolve the type for the given node.
|
||||
///
|
||||
@ -180,6 +210,22 @@ fn visit_expr(e: @ast::expr, &&rcx: @rcx, v: rvt) {
|
||||
// See #3148 for more details.
|
||||
}
|
||||
|
||||
ast::expr_fn(*) | ast::expr_fn_block(*) => {
|
||||
match rcx.resolve_node_type(e.id) {
|
||||
result::err(_) => return, // Typechecking will fail anyhow.
|
||||
result::ok(function_type) => {
|
||||
match ty::get(function_type).struct {
|
||||
ty::ty_fn({
|
||||
proto: proto_vstore(vstore_slice(region)), _
|
||||
}) => {
|
||||
constrain_free_variables(rcx, region, e);
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ => ()
|
||||
}
|
||||
|
||||
@ -217,6 +263,39 @@ fn visit_node(id: ast::node_id, span: span, rcx: @rcx) -> bool {
|
||||
return constrain_regions_in_type(rcx, encl_region, span, ty);
|
||||
}
|
||||
|
||||
fn constrain_free_variables(
|
||||
rcx: @rcx,
|
||||
region: ty::region,
|
||||
expr: @ast::expr)
|
||||
{
|
||||
// Make sure that all regions referenced by the free
|
||||
// variables inside the closure outlive the closure
|
||||
// itself.
|
||||
let tcx = rcx.fcx.ccx.tcx;
|
||||
for get_freevars(tcx, expr.id).each |freevar| {
|
||||
debug!("freevar def is %?", freevar.def);
|
||||
let def = freevar.def;
|
||||
let en_region = encl_region_of_def(rcx.fcx, def);
|
||||
match rcx.fcx.mk_subr(true, freevar.span,
|
||||
region, en_region) {
|
||||
result::ok(()) => {}
|
||||
result::err(_) => {
|
||||
tcx.sess.span_err(
|
||||
freevar.span,
|
||||
~"captured variable does not outlive the enclosing closure");
|
||||
note_and_explain_region(
|
||||
tcx,
|
||||
~"captured variable is valid for",
|
||||
en_region);
|
||||
note_and_explain_region(
|
||||
tcx,
|
||||
~"closure is valid for",
|
||||
region);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn constrain_regions_in_type(
|
||||
rcx: @rcx,
|
||||
encl_region: ty::region,
|
||||
|
@ -148,7 +148,7 @@ fn replace_bound_regions_in_fn_ty(
|
||||
// As long as we are not within a fn() type, `&T` is
|
||||
// mapped to the free region anon_r. But within a fn
|
||||
// type, it remains bound.
|
||||
ty::re_bound(ty::br_anon) if in_fn => r,
|
||||
ty::re_bound(ty::br_anon(_)) if in_fn => r,
|
||||
|
||||
ty::re_bound(br) => {
|
||||
match isr.find(br) {
|
||||
|
@ -321,7 +321,7 @@ fn early_resolve_expr(ex: @ast::expr, &&fcx: @fn_ctxt, is_early: bool) {
|
||||
if !is_early { cx.vtable_map.insert(callee_id, vtbls); }
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
none => ()
|
||||
}
|
||||
}
|
||||
ast::expr_cast(src, _) => {
|
||||
|
@ -52,15 +52,20 @@ impl @anon_rscope: region_scope {
|
||||
}
|
||||
}
|
||||
|
||||
enum binding_rscope = {base: region_scope};
|
||||
struct binding_rscope {
|
||||
base: region_scope;
|
||||
mut anon_bindings: uint;
|
||||
}
|
||||
fn in_binding_rscope<RS: region_scope copy owned>(self: RS)
|
||||
-> @binding_rscope {
|
||||
let base = self as region_scope;
|
||||
@binding_rscope({base: base})
|
||||
@binding_rscope { base: base, anon_bindings: 0 }
|
||||
}
|
||||
impl @binding_rscope: region_scope {
|
||||
fn anon_region(_span: span) -> result<ty::region, ~str> {
|
||||
result::ok(ty::re_bound(ty::br_anon))
|
||||
let idx = self.anon_bindings;
|
||||
self.anon_bindings += 1;
|
||||
result::ok(ty::re_bound(ty::br_anon(idx)))
|
||||
}
|
||||
fn named_region(span: span, id: ast::ident) -> result<ty::region, ~str> {
|
||||
do self.base.named_region(span, id).chain_err |_e| {
|
||||
|
@ -94,7 +94,6 @@ mod middle {
|
||||
}
|
||||
mod mem_categorization;
|
||||
mod liveness;
|
||||
mod block_use;
|
||||
mod kind;
|
||||
mod freevars;
|
||||
mod capture;
|
||||
|
@ -68,18 +68,21 @@ fn explain_region_and_span(cx: ctxt, region: ty::region)
|
||||
}
|
||||
|
||||
re_free(id, br) => {
|
||||
let prefix = match br {
|
||||
br_anon(idx) => fmt!("the anonymous lifetime #%u defined on",
|
||||
idx + 1),
|
||||
_ => fmt!("the lifetime %s as defined on",
|
||||
bound_region_to_str(cx, br))
|
||||
};
|
||||
|
||||
match cx.items.find(id) {
|
||||
some(ast_map::node_block(blk)) => {
|
||||
let (msg, opt_span) = explain_span(cx, ~"block", blk.span);
|
||||
(fmt!("the lifetime %s as defined on %s",
|
||||
bound_region_to_str(cx, br), msg),
|
||||
opt_span)
|
||||
(fmt!("%s %s", prefix, msg), opt_span)
|
||||
}
|
||||
some(_) | none => {
|
||||
// this really should not happen
|
||||
(fmt!("the lifetime %s as defined on node %d",
|
||||
bound_region_to_str(cx, br), id),
|
||||
none)
|
||||
(fmt!("%s node %d", prefix, id), none)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -103,10 +106,13 @@ fn explain_region_and_span(cx: ctxt, region: ty::region)
|
||||
|
||||
fn bound_region_to_str(cx: ctxt, br: bound_region) -> ~str {
|
||||
match br {
|
||||
br_anon => { ~"&" }
|
||||
br_named(str) => { fmt!{"&%s", *str} }
|
||||
br_self if cx.sess.ppregions() => { ~"&<self>" }
|
||||
br_self => { ~"&self" }
|
||||
br_named(str) => fmt!{"&%s", *str},
|
||||
br_self if cx.sess.ppregions() => ~"&<self>",
|
||||
br_self => ~"&self",
|
||||
|
||||
br_anon(idx) => {
|
||||
if cx.sess.ppregions() {fmt!("&%u", idx)} else {~"&"}
|
||||
}
|
||||
|
||||
// FIXME(#3011) -- even if this arm is removed, exhaustiveness checking
|
||||
// does not fail
|
||||
|
@ -13,7 +13,9 @@ fn item_check(t: &tree) -> int {
|
||||
}
|
||||
}
|
||||
|
||||
fn bottom_up_tree(arena: &arena::arena, item: int, depth: int) -> &tree {
|
||||
fn bottom_up_tree(arena: &r/arena::arena,
|
||||
item: int,
|
||||
depth: int) -> &r/tree {
|
||||
if depth > 0 {
|
||||
return arena.alloc(
|
||||
|| node(bottom_up_tree(arena, 2 * item - 1, depth - 1),
|
||||
|
@ -1,8 +0,0 @@
|
||||
// error-pattern: stack closure type can only appear
|
||||
|
||||
fn lol(f: fn()) -> fn() { return f; }
|
||||
fn main() {
|
||||
let i = 8;
|
||||
let f = lol(fn&() { log(error, i); });
|
||||
f();
|
||||
}
|
@ -8,7 +8,7 @@
|
||||
fn get() -> &int {
|
||||
let x = 3;
|
||||
return &x;
|
||||
//~^ ERROR illegal borrow: borrowed pointer must be valid for the lifetime & as defined on the block at 8:17, but the borrowed value is only valid for the block at 8:17
|
||||
//~^ ERROR illegal borrow: borrowed pointer must be valid for the anonymous lifetime #1 defined on the block at 8:17, but the borrowed value is only valid for the block at 8:17
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,8 +0,0 @@
|
||||
type t<T> = { f: fn() -> T };
|
||||
|
||||
fn f<T>(_x: t<T>) {}
|
||||
|
||||
fn main() {
|
||||
let x: t<()> = { f: || () }; //~ ERROR expressions with stack closure
|
||||
f(x);
|
||||
}
|
9
src/test/compile-fail/regions-freevar.rs
Normal file
9
src/test/compile-fail/regions-freevar.rs
Normal file
@ -0,0 +1,9 @@
|
||||
fn wants_static_fn(_x: &static/fn()) {}
|
||||
|
||||
fn main() {
|
||||
let i = 3;
|
||||
do wants_static_fn {
|
||||
#debug("i=%d", i);
|
||||
//~^ ERROR captured variable does not outlive the enclosing closure
|
||||
}
|
||||
}
|
@ -11,7 +11,7 @@ mod argparse {
|
||||
mut value: uint;
|
||||
}
|
||||
|
||||
fn flag(name: &str, desc: &str) -> Flag {
|
||||
fn flag(name: &r/str, desc: &r/str) -> Flag/&r {
|
||||
Flag { name: name, desc: desc, max_count: 1, value: 0 }
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
type point = {x: int, y: int};
|
||||
|
||||
fn x_coord(p: &point) -> &int {
|
||||
fn x_coord(p: &r/point) -> &r/int {
|
||||
return &p.x;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
fn borrow<T>(x: &T) -> &T {x}
|
||||
fn borrow<T>(x: &r/T) -> &r/T {x}
|
||||
|
||||
fn foo(cond: fn() -> bool, box: fn() -> @int) {
|
||||
let mut y: ∫
|
||||
|
@ -1,4 +1,4 @@
|
||||
fn select(x: &int, y: &int) -> &int { x }
|
||||
fn select(x: &r/int, y: &r/int) -> &r/int { x }
|
||||
|
||||
fn with<T>(f: fn(x: &int) -> T) -> T {
|
||||
f(&20)
|
||||
|
15
src/test/compile-fail/regions-steal-closure.rs
Normal file
15
src/test/compile-fail/regions-steal-closure.rs
Normal file
@ -0,0 +1,15 @@
|
||||
struct closure_box {
|
||||
cl: &fn();
|
||||
}
|
||||
|
||||
fn box_it(x: &r/fn()) -> closure_box/&r {
|
||||
closure_box {cl: x}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let cl_box = {
|
||||
let mut i = 3;
|
||||
box_it(|| i += 1) //~ ERROR cannot infer an appropriate lifetime
|
||||
};
|
||||
cl_box.cl();
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
fn borrow<T>(x: &T) -> &T {x}
|
||||
fn borrow<T>(x: &r/T) -> &r/T {x}
|
||||
|
||||
fn main() {
|
||||
let rec = @{mut f: @22};
|
||||
|
@ -19,13 +19,13 @@ fn compute_area(shape: &shape) -> float {
|
||||
impl shape {
|
||||
// self is in the implicit self region
|
||||
fn select<T>(&self, threshold: float,
|
||||
a: &T, b: &T) -> &T {
|
||||
a: &r/T, b: &r/T) -> &r/T {
|
||||
if compute_area(self) > threshold {a} else {b}
|
||||
}
|
||||
}
|
||||
|
||||
fn select_based_on_unit_circle<T>(
|
||||
threshold: float, a: &T, b: &T) -> &T {
|
||||
threshold: float, a: &r/T, b: &r/T) -> &r/T {
|
||||
|
||||
let shape = &circle({x: 0.0, y: 0.0}, 1.0);
|
||||
shape.select(threshold, a, b)
|
||||
|
@ -1,4 +1,4 @@
|
||||
fn thing(x: &[int]) -> &[int] { x }
|
||||
fn thing(x: &r/[int]) -> &r/[int] { x }
|
||||
fn main() {
|
||||
let x = &[1,2,3];
|
||||
let y = x;
|
||||
|
@ -1,4 +1,4 @@
|
||||
fn get<T>(opt: &option<T>) -> &T {
|
||||
fn get<T>(opt: &r/option<T>) -> &r/T {
|
||||
match *opt {
|
||||
some(ref v) => v,
|
||||
none => fail ~"none"
|
||||
|
@ -1,7 +1,7 @@
|
||||
type point = { x: int, y: int };
|
||||
type character = { pos: ~point };
|
||||
|
||||
fn get_x(x: &character) -> &int {
|
||||
fn get_x(x: &r/character) -> &r/int {
|
||||
// interesting case because the scope of this
|
||||
// borrow of the unique pointer is in fact
|
||||
// larger than the fn itself
|
||||
|
15
src/test/run-pass/regions-copy-closure.rs
Normal file
15
src/test/run-pass/regions-copy-closure.rs
Normal file
@ -0,0 +1,15 @@
|
||||
struct closure_box {
|
||||
cl: &fn();
|
||||
}
|
||||
|
||||
fn box_it(x: &r/fn()) -> closure_box/&r {
|
||||
closure_box {cl: x}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut i = 3;
|
||||
let cl_box = box_it(|| i += 1);
|
||||
assert i == 3;
|
||||
cl_box.cl();
|
||||
assert i == 4;
|
||||
}
|
@ -3,7 +3,7 @@ enum ast {
|
||||
add(&ast, &ast)
|
||||
}
|
||||
|
||||
fn mk_add_ok(x: &ast, y: &ast) -> ast {
|
||||
fn mk_add_ok(x: &r/ast, y: &r/ast) -> ast/&r {
|
||||
add(x, y)
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
fn foo(x: &uint) -> &uint { x }
|
||||
fn foo(x: &r/uint) -> &r/uint { x }
|
||||
fn bar(x: &uint) -> uint { *x }
|
||||
|
||||
fn main() {
|
||||
|
@ -1,4 +1,4 @@
|
||||
fn view<T>(x: &[T]) -> &[T] {x}
|
||||
fn view<T>(x: &r/[T]) -> &r/[T] {x}
|
||||
|
||||
fn main() {
|
||||
let v = ~[1, 2, 3];
|
||||
|
@ -1,4 +1,4 @@
|
||||
fn borrow<T>(x: &T) -> &T {x}
|
||||
fn borrow<T>(x: &r/T) -> &r/T {x}
|
||||
|
||||
fn main() {
|
||||
let x = @3;
|
||||
|
@ -1,6 +1,6 @@
|
||||
type point = {x: int, y: int};
|
||||
|
||||
fn x_coord(p: &point) -> &int {
|
||||
fn x_coord(p: &r/point) -> &r/int {
|
||||
return &p.x;
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@ type ccx = {
|
||||
x: int
|
||||
};
|
||||
|
||||
fn h(bcx : &bcx) -> &bcx {
|
||||
fn h(bcx : &r/bcx) -> &r/bcx {
|
||||
return bcx.fcx.arena.alloc(|| { fcx: bcx.fcx });
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@ enum roption {
|
||||
a, b(&uint)
|
||||
}
|
||||
|
||||
fn mk(cond: bool, ptr: &uint) -> roption {
|
||||
fn mk(cond: bool, ptr: &r/uint) -> roption/&r {
|
||||
if cond {a} else {b(ptr)}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
fn region_identity(x: &uint) -> &uint { x }
|
||||
fn region_identity(x: &r/uint) -> &r/uint { x }
|
||||
|
||||
fn apply<T>(t: T, f: fn(T) -> T) -> T { f(t) }
|
||||
|
||||
|
16
src/test/run-pass/regions-static-closure.rs
Normal file
16
src/test/run-pass/regions-static-closure.rs
Normal file
@ -0,0 +1,16 @@
|
||||
struct closure_box {
|
||||
cl: &fn();
|
||||
}
|
||||
|
||||
fn box_it(x: &r/fn()) -> closure_box/&r {
|
||||
closure_box {cl: x}
|
||||
}
|
||||
|
||||
fn call_static_closure(cl: closure_box/&static) {
|
||||
cl.cl();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let cl_box = box_it(|| debug!("Hello, world!"));
|
||||
call_static_closure(cl_box);
|
||||
}
|
Loading…
Reference in New Issue
Block a user