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:
parent
e4c141a331
commit
87e097a853
|
@ -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)
|
||||||
})
|
})
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
});
|
});
|
||||||
|
|
|
@ -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}]; }
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
_ {}
|
_ {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 }
|
||||||
};
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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; }
|
||||||
_ {}
|
_ {}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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); }
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue