Disallow ret inside of block functions

Also adds proper checking for cont/break being inside a loop.

Closes #1854
Issue #1619
This commit is contained in:
Marijn Haverbeke 2012-03-26 12:39:20 +02:00
parent e4c141a331
commit 87e097a853
16 changed files with 153 additions and 151 deletions

View File

@ -399,7 +399,7 @@ Loop through a rope, char by char, until the end.
fn iter_chars(rope: rope, it: fn(char)) { fn iter_chars(rope: rope, it: fn(char)) {
loop_chars(rope) {|x| loop_chars(rope) {|x|
it(x); it(x);
ret true true
}; };
} }
@ -1043,7 +1043,7 @@ mod node {
fn loop_chars(node: @node, it: fn(char) -> bool) -> bool { fn loop_chars(node: @node, it: fn(char) -> bool) -> bool {
ret loop_leaves(node, {|leaf| ret loop_leaves(node, {|leaf|
ret str::all_between(*leaf.content, str::all_between(*leaf.content,
leaf.byte_offset, leaf.byte_offset,
leaf.byte_len, it) leaf.byte_len, it)
}) })

View File

@ -155,6 +155,8 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
time(time_passes, "block-use checking", time(time_passes, "block-use checking",
bind middle::block_use::check_crate(ty_cx, crate)); bind middle::block_use::check_crate(ty_cx, crate));
time(time_passes, "loop checking",
bind middle::check_loop::check_crate(sess, crate));
time(time_passes, "function usage", time(time_passes, "function usage",
bind fn_usage::check_crate_fn_usage(ty_cx, crate)); bind fn_usage::check_crate_fn_usage(ty_cx, crate));
time(time_passes, "alt checking", time(time_passes, "alt checking",

View File

@ -654,8 +654,8 @@ impl unify_methods for infer_ctxt {
self.constrs(a, b) self.constrs(a, b)
} }
} else { } else {
ret self.uerr(ty::terr_constr_len(a_constrs.len(), self.uerr(ty::terr_constr_len(a_constrs.len(),
b_constrs.len())); b_constrs.len()))
} }
} }
} }

View File

@ -71,7 +71,7 @@ fn find_last_uses(c: @crate, def_map: resolve::def_map,
visit::visit_crate(*c, cx, v); visit::visit_crate(*c, cx, v);
let mini_table = std::map::int_hash(); let mini_table = std::map::int_hash();
cx.last_uses.items {|key, val| cx.last_uses.items {|key, val|
if !val { ret; } if val {
alt key { alt key {
path(id) { path(id) {
mini_table.insert(id, is_last_use); mini_table.insert(id, is_last_use);
@ -88,6 +88,7 @@ fn find_last_uses(c: @crate, def_map: resolve::def_map,
} }
} }
} }
}
ret (mini_table, cx.spill_map); ret (mini_table, cx.spill_map);
} }
@ -211,15 +212,16 @@ fn visit_stmt(s: @stmt, cx: ctx, v: visit::vt<ctx>) {
alt s.node { alt s.node {
stmt_decl(@{node: decl_local(ls), _}, _) { stmt_decl(@{node: decl_local(ls), _}, _) {
shadow_in_current(cx, {|id| shadow_in_current(cx, {|id|
let mut rslt = false;
for local in ls { for local in ls {
let mut found = false; let mut found = false;
pat_util::pat_bindings(cx.tcx.def_map, local.node.pat, pat_util::pat_bindings(cx.tcx.def_map, local.node.pat,
{|pid, _a, _b| {|pid, _a, _b|
if pid == id { found = true; } if pid == id { found = true; }
}); });
if found { ret true; } if found { rslt = true; break; }
} }
false rslt
}); });
} }
_ {} _ {}
@ -236,8 +238,7 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
proto_any | proto_block { proto_any | proto_block {
visit_block(func, cx, {|| visit_block(func, cx, {||
shadow_in_current(cx, {|id| shadow_in_current(cx, {|id|
for arg in decl.inputs { if arg.id == id { ret true; } } vec::any(decl.inputs, {|arg| arg.id == id})
false
}); });
visit::visit_fn(fk, decl, body, sp, id, cx, v); visit::visit_fn(fk, decl, body, sp, id, cx, v);
}); });

View File

@ -2162,7 +2162,7 @@ fn find_impls_in_view_item(e: env, vi: @ast::view_item,
if vec::len(*pt) == 1u { if vec::len(*pt) == 1u {
option::may(sc) {|sc| option::may(sc) {|sc|
list::iter(sc) {|level| list::iter(sc) {|level|
if vec::len(found) > 0u { ret; } if vec::len(found) == 0u {
for imp in *level { for imp in *level {
if imp.ident == pt[0] { if imp.ident == pt[0] {
found += [@{ident: name with *imp}]; found += [@{ident: name with *imp}];
@ -2171,6 +2171,7 @@ fn find_impls_in_view_item(e: env, vi: @ast::view_item,
if vec::len(found) > 0u { impls += found; } if vec::len(found) > 0u { impls += found; }
} }
} }
}
} else { } else {
lookup_imported_impls(e, id) {|is| lookup_imported_impls(e, id) {|is|
for i in *is { impls += [@{ident: name with *i}]; } for i in *is { impls += [@{ident: name with *i}]; }

View File

@ -2772,12 +2772,13 @@ fn get_landing_pad(bcx: block) -> BasicBlockRef {
in_lpad_scope_cx(bcx) {|info| in_lpad_scope_cx(bcx) {|info|
// If there is a valid landing pad still around, use it // If there is a valid landing pad still around, use it
alt info.landing_pad { alt info.landing_pad {
some(target) { cached = some(target); ret; } some(target) { cached = some(target); }
none {} none {
}
pad_bcx = sub_block(bcx, "unwind"); pad_bcx = sub_block(bcx, "unwind");
info.landing_pad = some(pad_bcx.llbb); info.landing_pad = some(pad_bcx.llbb);
} }
}
}
alt cached { some(b) { ret b; } none {} } // Can't return from block above alt cached { some(b) { ret b; } none {} } // Can't return from block above
// The landing pad return type (the type being propagated). Not sure what // The landing pad return type (the type being propagated). Not sure what
// this represents but it's determined by the personality function and // this represents but it's determined by the personality function and
@ -3374,13 +3375,7 @@ fn trans_break_cont(bcx: block, to_end: bool)
} }
_ {} _ {}
} }
unwind = alt check unwind.parent { unwind = alt check unwind.parent { parent_some(cx) { cx } };
parent_some(cx) { cx }
parent_none {
bcx.sess().bug
(if to_end { "break" } else { "cont" } + " outside a loop");
}
};
} }
cleanup_and_Br(bcx, unwind, target.llbb); cleanup_and_Br(bcx, unwind, target.llbb);
Unreachable(bcx); Unreachable(bcx);

View File

@ -265,7 +265,7 @@ fn revoke_clean(cx: block, val: ValueRef) {
vec::slice(info.cleanups, 0u, i) + vec::slice(info.cleanups, 0u, i) +
vec::slice(info.cleanups, i + 1u, info.cleanups.len()); vec::slice(info.cleanups, i + 1u, info.cleanups.len());
scope_clean_changed(info); scope_clean_changed(info);
ret; break;
} }
_ {} _ {}
} }

View File

@ -180,7 +180,7 @@ fn trans_append(bcx: block, vec_ty: ty::t, lhsptr: ValueRef,
load_if_immediate(bcx, addr, unit_ty), unit_ty); load_if_immediate(bcx, addr, unit_ty), unit_ty);
Store(bcx, InBoundsGEP(bcx, write_ptr, [C_int(ccx, 1)]), Store(bcx, InBoundsGEP(bcx, write_ptr, [C_int(ccx, 1)]),
write_ptr_ptr); write_ptr_ptr);
ret bcx; bcx
}) })
} }

View File

@ -96,25 +96,27 @@ fn type_needs(cx: ctx, use: uint, ty: ty::t) {
fn type_needs_inner(cx: ctx, use: uint, ty: ty::t) { fn type_needs_inner(cx: ctx, use: uint, ty: ty::t) {
ty::maybe_walk_ty(ty) {|ty| ty::maybe_walk_ty(ty) {|ty|
if !ty::type_has_params(ty) { ret false; } if ty::type_has_params(ty) {
alt ty::get(ty).struct { alt ty::get(ty).struct {
ty::ty_fn(_) | ty::ty_ptr(_) | ty::ty_rptr(_, _) | ty::ty_fn(_) | ty::ty_ptr(_) | ty::ty_rptr(_, _) |
ty::ty_box(_) | ty::ty_iface(_, _) { ret false; } ty::ty_box(_) | ty::ty_iface(_, _) { false }
ty::ty_enum(did, tps) { ty::ty_enum(did, tps) {
for v in *ty::enum_variants(cx.ccx.tcx, did) { for v in *ty::enum_variants(cx.ccx.tcx, did) {
for aty in v.args { for aty in v.args {
let t = ty::substitute_type_params(cx.ccx.tcx, tps, aty); let t = ty::substitute_type_params(cx.ccx.tcx, tps,
aty);
type_needs_inner(cx, use, t); type_needs_inner(cx, use, t);
} }
} }
ret false; false
} }
ty::ty_param(n, _) { ty::ty_param(n, _) {
cx.uses[n] |= use; cx.uses[n] |= use;
false
} }
_ {} _ { true }
} }
ret true; } else { false }
} }
} }

View File

@ -1036,12 +1036,7 @@ fn type_allows_implicit_copy(cx: ctxt, ty: t) -> bool {
mt.mutbl != ast::m_imm mt.mutbl != ast::m_imm
} }
ty_rec(fields) { ty_rec(fields) {
for field in fields { vec::any(fields, {|f| f.mt.mutbl != ast::m_imm})
if field.mt.mutbl != ast::m_imm {
ret true;
}
}
false
} }
_ { false } _ { false }
} }
@ -1050,12 +1045,12 @@ fn type_allows_implicit_copy(cx: ctxt, ty: t) -> bool {
fn type_structurally_contains_uniques(cx: ctxt, ty: t) -> bool { fn type_structurally_contains_uniques(cx: ctxt, ty: t) -> bool {
ret type_structurally_contains(cx, ty, {|sty| ret type_structurally_contains(cx, ty, {|sty|
ret alt sty { alt sty {
ty_uniq(_) { ret true; } ty_uniq(_) { true }
ty_vec(_) { true } ty_vec(_) { true }
ty_str { true } ty_str { true }
_ { ret false; } _ { false }
}; }
}); });
} }

View File

@ -2169,7 +2169,7 @@ fn lookup_method_inner(fcx: @fn_ctxt, expr: @ast::expr,
let mut result = none, complained = false; let mut result = none, complained = false;
std::list::iter(fcx.ccx.impl_map.get(expr.id)) {|impls| std::list::iter(fcx.ccx.impl_map.get(expr.id)) {|impls|
if option::is_some(result) { ret; } if option::is_none(result) {
for @{did, methods, _} in *impls { for @{did, methods, _} in *impls {
alt vec::find(methods, {|m| m.ident == name}) { alt vec::find(methods, {|m| m.ident == name}) {
some(m) { some(m) {
@ -2186,9 +2186,10 @@ fn lookup_method_inner(fcx: @fn_ctxt, expr: @ast::expr,
alt unify::unify(fcx, self_ty, ty) { alt unify::unify(fcx, self_ty, ty) {
result::ok(_) { result::ok(_) {
if option::is_some(result) { if option::is_some(result) {
// FIXME[impl] score specificity to resolve ambiguity? // FIXME[impl] score specificity?
if !complained { if !complained {
tcx.sess.span_err(expr.span, "multiple applicable \ tcx.sess.span_err(expr.span,
"multiple applicable \
methods in scope"); methods in scope");
complained = true; complained = true;
} }
@ -2209,6 +2210,7 @@ fn lookup_method_inner(fcx: @fn_ctxt, expr: @ast::expr,
} }
} }
} }
}
result result
} }
@ -3786,7 +3788,7 @@ mod vtable {
_ { _ {
let mut found = none; let mut found = none;
std::list::iter(isc) {|impls| std::list::iter(isc) {|impls|
if option::is_some(found) { ret; } if option::is_none(found) {
for im in *impls { for im in *impls {
let match = alt ty::impl_iface(tcx, im.did) { let match = alt ty::impl_iface(tcx, im.did) {
some(ity) { some(ity) {
@ -3797,20 +3799,22 @@ mod vtable {
_ { false } _ { false }
}; };
if match { if match {
let {n_tps, ty: self_ty} = impl_self_ty(tcx, im.did); let {n_tps, ty: self_ty} =
impl_self_ty(tcx, im.did);
let {vars, ty: self_ty} = if n_tps > 0u { let {vars, ty: self_ty} = if n_tps > 0u {
bind_params(fcx, self_ty, n_tps) bind_params(fcx, self_ty, n_tps)
} else { {vars: [], ty: self_ty} }; } else { {vars: [], ty: self_ty} };
let im_bs = ty::lookup_item_type(tcx, im.did).bounds; let im_bs =
ty::lookup_item_type(tcx, im.did).bounds;
alt unify::unify(fcx, ty, self_ty) { alt unify::unify(fcx, ty, self_ty) {
result::ok(_) { result::ok(_) {
if option::is_some(found) { if option::is_some(found) {
tcx.sess.span_err( tcx.sess.span_err(
sp, "multiple applicable implementations \ sp, "multiple applicable implemen\
in scope"); tations in scope");
} else { } else {
connect_iface_tps(fcx, sp, vars, iface_tps, connect_iface_tps(fcx, sp, vars,
im.did); iface_tps, im.did);
let params = vec::map(vars, {|t| let params = vec::map(vars, {|t|
fixup_ty(fcx, sp, t)}); fixup_ty(fcx, sp, t)});
let subres = lookup_vtables( let subres = lookup_vtables(
@ -3824,6 +3828,7 @@ mod vtable {
} }
} }
} }
}
alt found { alt found {
some(rslt) { ret rslt; } some(rslt) { ret rslt; }
_ {} _ {}

View File

@ -36,6 +36,7 @@ mod middle {
mod resolve; mod resolve;
mod typeck; mod typeck;
mod fn_usage; mod fn_usage;
mod check_loop;
mod check_alt; mod check_alt;
mod check_const; mod check_const;
mod lint; mod lint;

View File

@ -134,21 +134,20 @@ fn get_cargo_root_nearest() -> result<path, str> {
let mut dirpath = path::split(dirname); let mut dirpath = path::split(dirname);
let cwd_cargo = path::connect(cwd, ".cargo"); let cwd_cargo = path::connect(cwd, ".cargo");
let mut par_cargo = path::connect(dirname, ".cargo"); let mut par_cargo = path::connect(dirname, ".cargo");
let mut rslt = result::ok(cwd_cargo);
if os::path_is_dir(cwd_cargo) || cwd_cargo == p { if !os::path_is_dir(cwd_cargo) && cwd_cargo != p {
ret result::ok(cwd_cargo);
}
while vec::is_not_empty(dirpath) && par_cargo != p { while vec::is_not_empty(dirpath) && par_cargo != p {
if os::path_is_dir(par_cargo) { if os::path_is_dir(par_cargo) {
ret result::ok(par_cargo); rslt = result::ok(par_cargo);
break;
} }
vec::pop(dirpath); vec::pop(dirpath);
dirname = path::dirname(dirname); dirname = path::dirname(dirname);
par_cargo = path::connect(dirname, ".cargo"); par_cargo = path::connect(dirname, ".cargo");
} }
}
result::ok(cwd_cargo) rslt
} }
} }

View File

@ -285,9 +285,10 @@ fn future_writer() -> (writer, future::future<str>) {
loop { loop {
alt comm::recv(port) { alt comm::recv(port) {
write(s) { res += s } write(s) { res += s }
done { ret res; } done { break; }
} }
}; }
res
}; };
(writer, future) (writer, future)
} }

View File

@ -1,4 +1,4 @@
// error-pattern:break outside a loop // error-pattern:`break` outside of loop
fn main() { fn main() {
let pth = break; let pth = break;

View File

@ -11,7 +11,7 @@ fn call_id_2() { id(true) && id(ret); }
fn call_id_3() { id(ret) && id(ret); } fn call_id_3() { id(ret) && id(ret); }
fn call_id_4() { while id(break) { } } fn call_id_4() { while id(ret) { } }
fn bind_id_1() { bind id(fail); } fn bind_id_1() { bind id(fail); }