auto merge of #9492 : pnkfelix/rust/fsk-syntax-visit-refactor-remainder, r=huonw
r? anyone Part of #7081. Removed many unnecessary context arguments, turning them into visitors. Removed some @allocation. If this lands, then I think the only thing left that is unaddressed are: * the various lint visitors, and * middle/privacy.rs, which has `impl<'self> Visitor<&'self method_map> for PrivacyVisitor`
This commit is contained in:
commit
797a373cd1
10 changed files with 250 additions and 259 deletions
|
@ -226,7 +226,9 @@ struct env {
|
|||
idstack: @mut ~[NodeId]
|
||||
}
|
||||
|
||||
struct CheckItemRecursionVisitor;
|
||||
struct CheckItemRecursionVisitor {
|
||||
env: env,
|
||||
}
|
||||
|
||||
// Make sure a const item doesn't recursively refer to itself
|
||||
// FIXME: Should use the dependency graph when it's available (#1356)
|
||||
|
@ -242,27 +244,27 @@ pub fn check_item_recursion(sess: Session,
|
|||
idstack: @mut ~[]
|
||||
};
|
||||
|
||||
let mut visitor = CheckItemRecursionVisitor;
|
||||
visitor.visit_item(it, env);
|
||||
let mut visitor = CheckItemRecursionVisitor { env: env };
|
||||
visitor.visit_item(it, ());
|
||||
}
|
||||
|
||||
impl Visitor<env> for CheckItemRecursionVisitor {
|
||||
fn visit_item(&mut self, it: @item, env: env) {
|
||||
if env.idstack.iter().any(|x| x == &(it.id)) {
|
||||
env.sess.span_fatal(env.root_it.span, "recursive constant");
|
||||
impl Visitor<()> for CheckItemRecursionVisitor {
|
||||
fn visit_item(&mut self, it: @item, _: ()) {
|
||||
if self.env.idstack.iter().any(|x| x == &(it.id)) {
|
||||
self.env.sess.span_fatal(self.env.root_it.span, "recursive constant");
|
||||
}
|
||||
env.idstack.push(it.id);
|
||||
visit::walk_item(self, it, env);
|
||||
env.idstack.pop();
|
||||
self.env.idstack.push(it.id);
|
||||
visit::walk_item(self, it, ());
|
||||
self.env.idstack.pop();
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, e: @Expr, env: env) {
|
||||
fn visit_expr(&mut self, e: @Expr, _: ()) {
|
||||
match e.node {
|
||||
ExprPath(*) => match env.def_map.find(&e.id) {
|
||||
ExprPath(*) => match self.env.def_map.find(&e.id) {
|
||||
Some(&DefStatic(def_id, _)) if ast_util::is_local(def_id) =>
|
||||
match env.ast_map.get_copy(&def_id.node) {
|
||||
match self.env.ast_map.get_copy(&def_id.node) {
|
||||
ast_map::node_item(it, _) => {
|
||||
self.visit_item(it, env);
|
||||
self.visit_item(it, ());
|
||||
}
|
||||
_ => fail!("const not bound to an item")
|
||||
},
|
||||
|
@ -270,6 +272,6 @@ impl Visitor<env> for CheckItemRecursionVisitor {
|
|||
},
|
||||
_ => ()
|
||||
}
|
||||
visit::walk_expr(self, e, env);
|
||||
visit::walk_expr(self, e, ());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,43 +54,38 @@ use syntax::visit::Visitor;
|
|||
pub struct Context {
|
||||
tcx: ty::ctxt,
|
||||
method_map: typeck::method_map,
|
||||
current_item: NodeId
|
||||
}
|
||||
|
||||
struct KindAnalysisVisitor;
|
||||
impl Visitor<()> for Context {
|
||||
|
||||
impl Visitor<Context> for KindAnalysisVisitor {
|
||||
|
||||
fn visit_expr(&mut self, ex:@Expr, e:Context) {
|
||||
check_expr(self, ex, e);
|
||||
fn visit_expr(&mut self, ex:@Expr, _:()) {
|
||||
check_expr(self, ex);
|
||||
}
|
||||
|
||||
fn visit_fn(&mut self, fk:&visit::fn_kind, fd:&fn_decl, b:&Block, s:Span, n:NodeId, e:Context) {
|
||||
check_fn(self, fk, fd, b, s, n, e);
|
||||
fn visit_fn(&mut self, fk:&visit::fn_kind, fd:&fn_decl, b:&Block, s:Span, n:NodeId, _:()) {
|
||||
check_fn(self, fk, fd, b, s, n);
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, t:&Ty, e:Context) {
|
||||
check_ty(self, t, e);
|
||||
fn visit_ty(&mut self, t:&Ty, _:()) {
|
||||
check_ty(self, t);
|
||||
}
|
||||
fn visit_item(&mut self, i:@item, e:Context) {
|
||||
check_item(self, i, e);
|
||||
fn visit_item(&mut self, i:@item, _:()) {
|
||||
check_item(self, i);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_crate(tcx: ty::ctxt,
|
||||
method_map: typeck::method_map,
|
||||
crate: &Crate) {
|
||||
let ctx = Context {
|
||||
let mut ctx = Context {
|
||||
tcx: tcx,
|
||||
method_map: method_map,
|
||||
current_item: -1
|
||||
};
|
||||
let mut visit = KindAnalysisVisitor;
|
||||
visit::walk_crate(&mut visit, crate, ctx);
|
||||
visit::walk_crate(&mut ctx, crate, ());
|
||||
tcx.sess.abort_if_errors();
|
||||
}
|
||||
|
||||
fn check_struct_safe_for_destructor(cx: Context,
|
||||
fn check_struct_safe_for_destructor(cx: &mut Context,
|
||||
span: Span,
|
||||
struct_did: DefId) {
|
||||
let struct_tpt = ty::lookup_item_type(cx.tcx, struct_did);
|
||||
|
@ -120,7 +115,7 @@ fn check_struct_safe_for_destructor(cx: Context,
|
|||
}
|
||||
}
|
||||
|
||||
fn check_impl_of_trait(cx: Context, it: @item, trait_ref: &trait_ref, self_type: &Ty) {
|
||||
fn check_impl_of_trait(cx: &mut Context, it: @item, trait_ref: &trait_ref, self_type: &Ty) {
|
||||
let ast_trait_def = cx.tcx.def_map.find(&trait_ref.ref_id)
|
||||
.expect("trait ref not in def map!");
|
||||
let trait_def_id = ast_util::def_id_of_def(*ast_trait_def);
|
||||
|
@ -156,7 +151,7 @@ fn check_impl_of_trait(cx: Context, it: @item, trait_ref: &trait_ref, self_type:
|
|||
}
|
||||
}
|
||||
|
||||
fn check_item(visitor: &mut KindAnalysisVisitor, item: @item, cx: Context) {
|
||||
fn check_item(cx: &mut Context, item: @item) {
|
||||
if !attr::contains_name(item.attrs, "unsafe_destructor") {
|
||||
match item.node {
|
||||
item_impl(_, Some(ref trait_ref), ref self_type, _) => {
|
||||
|
@ -166,16 +161,15 @@ fn check_item(visitor: &mut KindAnalysisVisitor, item: @item, cx: Context) {
|
|||
}
|
||||
}
|
||||
|
||||
let cx = Context { current_item: item.id, ..cx };
|
||||
visit::walk_item(visitor, item, cx);
|
||||
visit::walk_item(cx, item, ());
|
||||
}
|
||||
|
||||
// Yields the appropriate function to check the kind of closed over
|
||||
// variables. `id` is the NodeId for some expression that creates the
|
||||
// closure.
|
||||
fn with_appropriate_checker(cx: Context, id: NodeId,
|
||||
b: &fn(checker: &fn(Context, @freevar_entry))) {
|
||||
fn check_for_uniq(cx: Context, fv: &freevar_entry, bounds: ty::BuiltinBounds) {
|
||||
fn with_appropriate_checker(cx: &Context, id: NodeId,
|
||||
b: &fn(checker: &fn(&Context, @freevar_entry))) {
|
||||
fn check_for_uniq(cx: &Context, fv: &freevar_entry, bounds: ty::BuiltinBounds) {
|
||||
// all captured data must be owned, regardless of whether it is
|
||||
// moved in or copied in.
|
||||
let id = ast_util::def_id_of_def(fv.def).node;
|
||||
|
@ -187,7 +181,7 @@ fn with_appropriate_checker(cx: Context, id: NodeId,
|
|||
check_freevar_bounds(cx, fv.span, var_t, bounds, None);
|
||||
}
|
||||
|
||||
fn check_for_box(cx: Context, fv: &freevar_entry, bounds: ty::BuiltinBounds) {
|
||||
fn check_for_box(cx: &Context, fv: &freevar_entry, bounds: ty::BuiltinBounds) {
|
||||
// all captured data must be owned
|
||||
let id = ast_util::def_id_of_def(fv.def).node;
|
||||
let var_t = ty::node_id_to_type(cx.tcx, id);
|
||||
|
@ -198,7 +192,7 @@ fn with_appropriate_checker(cx: Context, id: NodeId,
|
|||
check_freevar_bounds(cx, fv.span, var_t, bounds, None);
|
||||
}
|
||||
|
||||
fn check_for_block(cx: Context, fv: &freevar_entry,
|
||||
fn check_for_block(cx: &Context, fv: &freevar_entry,
|
||||
bounds: ty::BuiltinBounds, region: ty::Region) {
|
||||
let id = ast_util::def_id_of_def(fv.def).node;
|
||||
let var_t = ty::node_id_to_type(cx.tcx, id);
|
||||
|
@ -209,7 +203,7 @@ fn with_appropriate_checker(cx: Context, id: NodeId,
|
|||
bounds, Some(var_t));
|
||||
}
|
||||
|
||||
fn check_for_bare(cx: Context, fv: @freevar_entry) {
|
||||
fn check_for_bare(cx: &Context, fv: @freevar_entry) {
|
||||
cx.tcx.sess.span_err(
|
||||
fv.span,
|
||||
"can't capture dynamic environment in a fn item; \
|
||||
|
@ -252,13 +246,12 @@ fn with_appropriate_checker(cx: Context, id: NodeId,
|
|||
// Check that the free variables used in a shared/sendable closure conform
|
||||
// to the copy/move kind bounds. Then recursively check the function body.
|
||||
fn check_fn(
|
||||
v: &mut KindAnalysisVisitor,
|
||||
cx: &mut Context,
|
||||
fk: &visit::fn_kind,
|
||||
decl: &fn_decl,
|
||||
body: &Block,
|
||||
sp: Span,
|
||||
fn_id: NodeId,
|
||||
cx: Context) {
|
||||
fn_id: NodeId) {
|
||||
|
||||
// Check kinds on free variables:
|
||||
do with_appropriate_checker(cx, fn_id) |chk| {
|
||||
|
@ -268,10 +261,10 @@ fn check_fn(
|
|||
}
|
||||
}
|
||||
|
||||
visit::walk_fn(v, fk, decl, body, sp, fn_id, cx);
|
||||
visit::walk_fn(cx, fk, decl, body, sp, fn_id, ());
|
||||
}
|
||||
|
||||
pub fn check_expr(v: &mut KindAnalysisVisitor, e: @Expr, cx: Context) {
|
||||
pub fn check_expr(cx: &mut Context, e: @Expr) {
|
||||
debug!("kind::check_expr(%s)", expr_to_str(e, cx.tcx.sess.intr()));
|
||||
|
||||
// Handle any kind bounds on type parameters
|
||||
|
@ -336,10 +329,10 @@ pub fn check_expr(v: &mut KindAnalysisVisitor, e: @Expr, cx: Context) {
|
|||
}
|
||||
_ => {}
|
||||
}
|
||||
visit::walk_expr(v, e, cx);
|
||||
visit::walk_expr(cx, e, ());
|
||||
}
|
||||
|
||||
fn check_ty(v: &mut KindAnalysisVisitor, aty: &Ty, cx: Context) {
|
||||
fn check_ty(cx: &mut Context, aty: &Ty) {
|
||||
match aty.node {
|
||||
ty_path(_, _, id) => {
|
||||
let r = cx.tcx.node_type_substs.find(&id);
|
||||
|
@ -354,11 +347,11 @@ fn check_ty(v: &mut KindAnalysisVisitor, aty: &Ty, cx: Context) {
|
|||
}
|
||||
_ => {}
|
||||
}
|
||||
visit::walk_ty(v, aty, cx);
|
||||
visit::walk_ty(cx, aty, ());
|
||||
}
|
||||
|
||||
// Calls "any_missing" if any bounds were missing.
|
||||
pub fn check_builtin_bounds(cx: Context, ty: ty::t, bounds: ty::BuiltinBounds,
|
||||
pub fn check_builtin_bounds(cx: &Context, ty: ty::t, bounds: ty::BuiltinBounds,
|
||||
any_missing: &fn(ty::BuiltinBounds))
|
||||
{
|
||||
let kind = ty::type_contents(cx.tcx, ty);
|
||||
|
@ -373,7 +366,7 @@ pub fn check_builtin_bounds(cx: Context, ty: ty::t, bounds: ty::BuiltinBounds,
|
|||
}
|
||||
}
|
||||
|
||||
pub fn check_typaram_bounds(cx: Context,
|
||||
pub fn check_typaram_bounds(cx: &Context,
|
||||
_type_parameter_id: NodeId,
|
||||
sp: Span,
|
||||
ty: ty::t,
|
||||
|
@ -389,7 +382,7 @@ pub fn check_typaram_bounds(cx: Context,
|
|||
}
|
||||
}
|
||||
|
||||
pub fn check_freevar_bounds(cx: Context, sp: Span, ty: ty::t,
|
||||
pub fn check_freevar_bounds(cx: &Context, sp: Span, ty: ty::t,
|
||||
bounds: ty::BuiltinBounds, referenced_ty: Option<ty::t>)
|
||||
{
|
||||
do check_builtin_bounds(cx, ty, bounds) |missing| {
|
||||
|
@ -412,7 +405,7 @@ pub fn check_freevar_bounds(cx: Context, sp: Span, ty: ty::t,
|
|||
}
|
||||
}
|
||||
|
||||
pub fn check_trait_cast_bounds(cx: Context, sp: Span, ty: ty::t,
|
||||
pub fn check_trait_cast_bounds(cx: &Context, sp: Span, ty: ty::t,
|
||||
bounds: ty::BuiltinBounds) {
|
||||
do check_builtin_bounds(cx, ty, bounds) |missing| {
|
||||
cx.tcx.sess.span_err(sp,
|
||||
|
@ -423,7 +416,7 @@ pub fn check_trait_cast_bounds(cx: Context, sp: Span, ty: ty::t,
|
|||
}
|
||||
}
|
||||
|
||||
fn is_nullary_variant(cx: Context, ex: @Expr) -> bool {
|
||||
fn is_nullary_variant(cx: &Context, ex: @Expr) -> bool {
|
||||
match ex.node {
|
||||
ExprPath(_) => {
|
||||
match cx.tcx.def_map.get_copy(&ex.id) {
|
||||
|
@ -437,7 +430,7 @@ fn is_nullary_variant(cx: Context, ex: @Expr) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_imm_free_var(cx: Context, def: Def, sp: Span) {
|
||||
fn check_imm_free_var(cx: &Context, def: Def, sp: Span) {
|
||||
match def {
|
||||
DefLocal(_, is_mutbl) => {
|
||||
if is_mutbl {
|
||||
|
@ -457,7 +450,7 @@ fn check_imm_free_var(cx: Context, def: Def, sp: Span) {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_copy(cx: Context, ty: ty::t, sp: Span, reason: &str) {
|
||||
fn check_copy(cx: &Context, ty: ty::t, sp: Span, reason: &str) {
|
||||
debug!("type_contents(%s)=%s",
|
||||
ty_to_str(cx.tcx, ty),
|
||||
ty::type_contents(cx.tcx, ty).to_str());
|
||||
|
@ -469,7 +462,7 @@ fn check_copy(cx: Context, ty: ty::t, sp: Span, reason: &str) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn check_send(cx: Context, ty: ty::t, sp: Span) -> bool {
|
||||
pub fn check_send(cx: &Context, ty: ty::t, sp: Span) -> bool {
|
||||
if !ty::type_is_sendable(cx.tcx, ty) {
|
||||
cx.tcx.sess.span_err(
|
||||
sp, fmt!("value has non-sendable type `%s`",
|
||||
|
@ -525,7 +518,7 @@ pub fn check_durable(tcx: ty::ctxt, ty: ty::t, sp: Span) -> bool {
|
|||
///
|
||||
/// FIXME(#5723)---This code should probably move into regionck.
|
||||
pub fn check_cast_for_escaping_regions(
|
||||
cx: Context,
|
||||
cx: &Context,
|
||||
source: &Expr,
|
||||
target: &Expr)
|
||||
{
|
||||
|
@ -601,7 +594,7 @@ pub fn check_cast_for_escaping_regions(
|
|||
}
|
||||
}
|
||||
|
||||
fn is_subregion_of(cx: Context, r_sub: ty::Region, r_sup: ty::Region) -> bool {
|
||||
fn is_subregion_of(cx: &Context, r_sub: ty::Region, r_sup: ty::Region) -> bool {
|
||||
cx.tcx.region_maps.is_subregion_of(r_sub, r_sup)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -345,20 +345,18 @@ impl IrMaps {
|
|||
}
|
||||
}
|
||||
|
||||
struct ErrorCheckVisitor;
|
||||
|
||||
impl Visitor<@Liveness> for ErrorCheckVisitor {
|
||||
fn visit_fn(&mut self, fk:&fn_kind, fd:&fn_decl, b:&Block, s:Span, n:NodeId, e:@Liveness) {
|
||||
check_fn(self, fk, fd, b, s, n, e);
|
||||
impl Visitor<()> for Liveness {
|
||||
fn visit_fn(&mut self, fk:&fn_kind, fd:&fn_decl, b:&Block, s:Span, n:NodeId, _:()) {
|
||||
check_fn(self, fk, fd, b, s, n);
|
||||
}
|
||||
fn visit_local(&mut self, l:@Local, e:@Liveness) {
|
||||
check_local(self, l, e);
|
||||
fn visit_local(&mut self, l:@Local, _:()) {
|
||||
check_local(self, l);
|
||||
}
|
||||
fn visit_expr(&mut self, ex:@Expr, e:@Liveness) {
|
||||
check_expr(self, ex, e);
|
||||
fn visit_expr(&mut self, ex:@Expr, _:()) {
|
||||
check_expr(self, ex);
|
||||
}
|
||||
fn visit_arm(&mut self, a:&Arm, e:@Liveness) {
|
||||
check_arm(self, a, e);
|
||||
fn visit_arm(&mut self, a:&Arm, _:()) {
|
||||
check_arm(self, a);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -419,12 +417,11 @@ fn visit_fn(v: &mut LivenessVisitor,
|
|||
};
|
||||
|
||||
// compute liveness
|
||||
let lsets = @Liveness(fn_maps, specials);
|
||||
let entry_ln = (*lsets).compute(decl, body);
|
||||
let mut lsets = Liveness(fn_maps, specials);
|
||||
let entry_ln = lsets.compute(decl, body);
|
||||
|
||||
// check for various error conditions
|
||||
let mut check_vt = ErrorCheckVisitor;
|
||||
check_vt.visit_block(body, lsets);
|
||||
lsets.visit_block(body, ());
|
||||
lsets.check_ret(id, sp, fk, entry_ln);
|
||||
lsets.warn_about_unused_args(decl, entry_ln);
|
||||
}
|
||||
|
@ -1423,7 +1420,7 @@ impl Liveness {
|
|||
// _______________________________________________________________________
|
||||
// Checking for error conditions
|
||||
|
||||
fn check_local(vt: &mut ErrorCheckVisitor, local: @Local, this: @Liveness) {
|
||||
fn check_local(this: &mut Liveness, local: @Local) {
|
||||
match local.init {
|
||||
Some(_) => {
|
||||
this.warn_about_unused_or_dead_vars_in_pat(local.pat);
|
||||
|
@ -1449,48 +1446,48 @@ fn check_local(vt: &mut ErrorCheckVisitor, local: @Local, this: @Liveness) {
|
|||
}
|
||||
}
|
||||
|
||||
visit::walk_local(vt, local, this);
|
||||
visit::walk_local(this, local, ());
|
||||
}
|
||||
|
||||
fn check_arm(vt: &mut ErrorCheckVisitor, arm: &Arm, this: @Liveness) {
|
||||
fn check_arm(this: &mut Liveness, arm: &Arm) {
|
||||
do this.arm_pats_bindings(arm.pats) |ln, var, sp, id| {
|
||||
this.warn_about_unused(sp, id, ln, var);
|
||||
}
|
||||
visit::walk_arm(vt, arm, this);
|
||||
visit::walk_arm(this, arm, ());
|
||||
}
|
||||
|
||||
fn check_expr(vt: &mut ErrorCheckVisitor, expr: @Expr, this: @Liveness) {
|
||||
fn check_expr(this: &mut Liveness, expr: @Expr) {
|
||||
match expr.node {
|
||||
ExprAssign(l, r) => {
|
||||
this.check_lvalue(l, vt);
|
||||
vt.visit_expr(r, this);
|
||||
this.check_lvalue(l);
|
||||
this.visit_expr(r, ());
|
||||
|
||||
visit::walk_expr(vt, expr, this);
|
||||
visit::walk_expr(this, expr, ());
|
||||
}
|
||||
|
||||
ExprAssignOp(_, _, l, _) => {
|
||||
this.check_lvalue(l, vt);
|
||||
this.check_lvalue(l);
|
||||
|
||||
visit::walk_expr(vt, expr, this);
|
||||
visit::walk_expr(this, expr, ());
|
||||
}
|
||||
|
||||
ExprInlineAsm(ref ia) => {
|
||||
for &(_, input) in ia.inputs.iter() {
|
||||
vt.visit_expr(input, this);
|
||||
this.visit_expr(input, ());
|
||||
}
|
||||
|
||||
// Output operands must be lvalues
|
||||
for &(_, out) in ia.outputs.iter() {
|
||||
match out.node {
|
||||
ExprAddrOf(_, inner) => {
|
||||
this.check_lvalue(inner, vt);
|
||||
this.check_lvalue(inner);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
vt.visit_expr(out, this);
|
||||
this.visit_expr(out, ());
|
||||
}
|
||||
|
||||
visit::walk_expr(vt, expr, this);
|
||||
visit::walk_expr(this, expr, ());
|
||||
}
|
||||
|
||||
// no correctness conditions related to liveness
|
||||
|
@ -1502,19 +1499,18 @@ fn check_expr(vt: &mut ErrorCheckVisitor, expr: @Expr, this: @Liveness) {
|
|||
ExprAgain(*) | ExprLit(_) | ExprBlock(*) |
|
||||
ExprMac(*) | ExprAddrOf(*) | ExprStruct(*) | ExprRepeat(*) |
|
||||
ExprParen(*) | ExprFnBlock(*) | ExprPath(*) | ExprSelf(*) => {
|
||||
visit::walk_expr(vt, expr, this);
|
||||
visit::walk_expr(this, expr, ());
|
||||
}
|
||||
ExprForLoop(*) => fail!("non-desugared expr_for_loop")
|
||||
}
|
||||
}
|
||||
|
||||
fn check_fn(_v: &mut ErrorCheckVisitor,
|
||||
fn check_fn(_v: &Liveness,
|
||||
_fk: &visit::fn_kind,
|
||||
_decl: &fn_decl,
|
||||
_body: &Block,
|
||||
_sp: Span,
|
||||
_id: NodeId,
|
||||
_self: @Liveness) {
|
||||
_id: NodeId) {
|
||||
// do not check contents of nested fns
|
||||
}
|
||||
|
||||
|
@ -1549,7 +1545,7 @@ impl Liveness {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn check_lvalue(@self, expr: @Expr, vt: &mut ErrorCheckVisitor) {
|
||||
pub fn check_lvalue(&mut self, expr: @Expr) {
|
||||
match expr.node {
|
||||
ExprPath(_) => {
|
||||
match self.tcx.def_map.get_copy(&expr.id) {
|
||||
|
@ -1578,7 +1574,7 @@ impl Liveness {
|
|||
_ => {
|
||||
// For other kinds of lvalues, no checks are required,
|
||||
// and any embedded expressions are actually rvalues
|
||||
visit::walk_expr(vt, expr, self);
|
||||
visit::walk_expr(self, expr, ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,12 +65,6 @@ pub struct RegionMaps {
|
|||
|
||||
#[deriving(Clone)]
|
||||
pub struct Context {
|
||||
sess: Session,
|
||||
def_map: resolve::DefMap,
|
||||
|
||||
// Generated maps:
|
||||
region_maps: @mut RegionMaps,
|
||||
|
||||
// Scope where variables should be parented to
|
||||
var_parent: Option<ast::NodeId>,
|
||||
|
||||
|
@ -78,6 +72,15 @@ pub struct Context {
|
|||
parent: Option<ast::NodeId>,
|
||||
}
|
||||
|
||||
struct RegionResolutionVisitor {
|
||||
sess: Session,
|
||||
def_map: resolve::DefMap,
|
||||
|
||||
// Generated maps:
|
||||
region_maps: @mut RegionMaps,
|
||||
}
|
||||
|
||||
|
||||
impl RegionMaps {
|
||||
pub fn relate_free_regions(&mut self, sub: FreeRegion, sup: FreeRegion) {
|
||||
match self.free_region_map.find_mut(&sub) {
|
||||
|
@ -318,11 +321,12 @@ impl RegionMaps {
|
|||
}
|
||||
|
||||
/// Records the current parent (if any) as the parent of `child_id`.
|
||||
fn parent_to_expr(cx: Context, child_id: ast::NodeId, sp: Span) {
|
||||
fn parent_to_expr(visitor: &mut RegionResolutionVisitor,
|
||||
cx: Context, child_id: ast::NodeId, sp: Span) {
|
||||
debug!("region::parent_to_expr(span=%?)",
|
||||
cx.sess.codemap.span_to_str(sp));
|
||||
visitor.sess.codemap.span_to_str(sp));
|
||||
for parent_id in cx.parent.iter() {
|
||||
cx.region_maps.record_parent(child_id, *parent_id);
|
||||
visitor.region_maps.record_parent(child_id, *parent_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -330,12 +334,11 @@ fn resolve_block(visitor: &mut RegionResolutionVisitor,
|
|||
blk: &ast::Block,
|
||||
cx: Context) {
|
||||
// Record the parent of this block.
|
||||
parent_to_expr(cx, blk.id, blk.span);
|
||||
parent_to_expr(visitor, cx, blk.id, blk.span);
|
||||
|
||||
// Descend.
|
||||
let new_cx = Context {var_parent: Some(blk.id),
|
||||
parent: Some(blk.id),
|
||||
..cx};
|
||||
parent: Some(blk.id)};
|
||||
visit::walk_block(visitor, blk, new_cx);
|
||||
}
|
||||
|
||||
|
@ -349,7 +352,7 @@ fn resolve_pat(visitor: &mut RegionResolutionVisitor,
|
|||
pat: @ast::Pat,
|
||||
cx: Context) {
|
||||
assert_eq!(cx.var_parent, cx.parent);
|
||||
parent_to_expr(cx, pat.id, pat.span);
|
||||
parent_to_expr(visitor, cx, pat.id, pat.span);
|
||||
visit::walk_pat(visitor, pat, cx);
|
||||
}
|
||||
|
||||
|
@ -362,18 +365,18 @@ fn resolve_stmt(visitor: &mut RegionResolutionVisitor,
|
|||
}
|
||||
ast::StmtExpr(_, stmt_id) |
|
||||
ast::StmtSemi(_, stmt_id) => {
|
||||
parent_to_expr(cx, stmt_id, stmt.span);
|
||||
parent_to_expr(visitor, cx, stmt_id, stmt.span);
|
||||
let expr_cx = Context {parent: Some(stmt_id), ..cx};
|
||||
visit::walk_stmt(visitor, stmt, expr_cx);
|
||||
}
|
||||
ast::StmtMac(*) => cx.sess.bug("unexpanded macro")
|
||||
ast::StmtMac(*) => visitor.sess.bug("unexpanded macro")
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_expr(visitor: &mut RegionResolutionVisitor,
|
||||
expr: @ast::Expr,
|
||||
cx: Context) {
|
||||
parent_to_expr(cx, expr.id, expr.span);
|
||||
parent_to_expr(visitor, cx, expr.id, expr.span);
|
||||
|
||||
let mut new_cx = cx;
|
||||
new_cx.parent = Some(expr.id);
|
||||
|
@ -415,7 +418,7 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor,
|
|||
local: @ast::Local,
|
||||
cx: Context) {
|
||||
assert_eq!(cx.var_parent, cx.parent);
|
||||
parent_to_expr(cx, local.id, local.span);
|
||||
parent_to_expr(visitor, cx, local.id, local.span);
|
||||
visit::walk_local(visitor, local, cx);
|
||||
}
|
||||
|
||||
|
@ -439,7 +442,7 @@ fn resolve_fn(visitor: &mut RegionResolutionVisitor,
|
|||
body.id=%?, \
|
||||
cx.parent=%?)",
|
||||
id,
|
||||
cx.sess.codemap.span_to_str(sp),
|
||||
visitor.sess.codemap.span_to_str(sp),
|
||||
body.id,
|
||||
cx.parent);
|
||||
|
||||
|
@ -449,7 +452,7 @@ fn resolve_fn(visitor: &mut RegionResolutionVisitor,
|
|||
..cx};
|
||||
match *fk {
|
||||
visit::fk_method(_, _, method) => {
|
||||
cx.region_maps.record_parent(method.self_id, body.id);
|
||||
visitor.region_maps.record_parent(method.self_id, body.id);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -470,8 +473,6 @@ fn resolve_fn(visitor: &mut RegionResolutionVisitor,
|
|||
visitor.visit_block(body, body_cx);
|
||||
}
|
||||
|
||||
struct RegionResolutionVisitor;
|
||||
|
||||
impl Visitor<Context> for RegionResolutionVisitor {
|
||||
|
||||
fn visit_block(&mut self, b:&Block, cx:Context) {
|
||||
|
@ -511,12 +512,13 @@ pub fn resolve_crate(sess: Session,
|
|||
free_region_map: HashMap::new(),
|
||||
cleanup_scopes: HashSet::new(),
|
||||
};
|
||||
let cx = Context {sess: sess,
|
||||
def_map: def_map,
|
||||
region_maps: region_maps,
|
||||
parent: None,
|
||||
let cx = Context {parent: None,
|
||||
var_parent: None};
|
||||
let mut visitor = RegionResolutionVisitor;
|
||||
let mut visitor = RegionResolutionVisitor {
|
||||
sess: sess,
|
||||
def_map: def_map,
|
||||
region_maps: region_maps,
|
||||
};
|
||||
visit::walk_crate(&mut visitor, crate, cx);
|
||||
return region_maps;
|
||||
}
|
||||
|
@ -733,10 +735,9 @@ impl DetermineRpCtxt {
|
|||
}
|
||||
|
||||
fn determine_rp_in_item(visitor: &mut DetermineRpVisitor,
|
||||
item: @ast::item,
|
||||
cx: @mut DetermineRpCtxt) {
|
||||
do cx.with(item.id, true) {
|
||||
visit::walk_item(visitor, item, cx);
|
||||
item: @ast::item) {
|
||||
do visitor.cx.with(item.id, true) {
|
||||
visit::walk_item(visitor, item, ());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -745,32 +746,33 @@ fn determine_rp_in_fn(visitor: &mut DetermineRpVisitor,
|
|||
decl: &ast::fn_decl,
|
||||
body: &ast::Block,
|
||||
_: Span,
|
||||
_: ast::NodeId,
|
||||
cx: @mut DetermineRpCtxt) {
|
||||
_: ast::NodeId) {
|
||||
let cx = visitor.cx;
|
||||
do cx.with(cx.item_id, false) {
|
||||
do cx.with_ambient_variance(rv_contravariant) {
|
||||
for a in decl.inputs.iter() {
|
||||
visitor.visit_ty(&a.ty, cx);
|
||||
visitor.visit_ty(&a.ty, ());
|
||||
}
|
||||
}
|
||||
visitor.visit_ty(&decl.output, cx);
|
||||
visitor.visit_ty(&decl.output, ());
|
||||
let generics = visit::generics_of_fn(fk);
|
||||
visitor.visit_generics(&generics, cx);
|
||||
visitor.visit_block(body, cx);
|
||||
visitor.visit_generics(&generics, ());
|
||||
visitor.visit_block(body, ());
|
||||
}
|
||||
}
|
||||
|
||||
fn determine_rp_in_ty_method(visitor: &mut DetermineRpVisitor,
|
||||
ty_m: &ast::TypeMethod,
|
||||
cx: @mut DetermineRpCtxt) {
|
||||
ty_m: &ast::TypeMethod) {
|
||||
let cx = visitor.cx;
|
||||
do cx.with(cx.item_id, false) {
|
||||
visit::walk_ty_method(visitor, ty_m, cx);
|
||||
visit::walk_ty_method(visitor, ty_m, ());
|
||||
}
|
||||
}
|
||||
|
||||
fn determine_rp_in_ty(visitor: &mut DetermineRpVisitor,
|
||||
ty: &ast::Ty,
|
||||
cx: @mut DetermineRpCtxt) {
|
||||
ty: &ast::Ty) {
|
||||
let cx = visitor.cx;
|
||||
|
||||
// we are only interested in types that will require an item to
|
||||
// be region-parameterized. if cx.item_id is zero, then this type
|
||||
// is not a member of a type defn nor is it a constitutent of an
|
||||
|
@ -854,14 +856,14 @@ fn determine_rp_in_ty(visitor: &mut DetermineRpVisitor,
|
|||
match ty.node {
|
||||
ast::ty_box(ref mt) | ast::ty_uniq(ref mt) | ast::ty_vec(ref mt) |
|
||||
ast::ty_rptr(_, ref mt) | ast::ty_ptr(ref mt) => {
|
||||
visit_mt(visitor, mt, cx);
|
||||
visit_mt(visitor, mt);
|
||||
}
|
||||
|
||||
ast::ty_path(ref path, _, _) => {
|
||||
// type parameters are---for now, anyway---always invariant
|
||||
do cx.with_ambient_variance(rv_invariant) {
|
||||
for tp in path.segments.iter().flat_map(|s| s.types.iter()) {
|
||||
visitor.visit_ty(tp, cx);
|
||||
visitor.visit_ty(tp, ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -874,57 +876,58 @@ fn determine_rp_in_ty(visitor: &mut DetermineRpVisitor,
|
|||
// parameters are contravariant
|
||||
do cx.with_ambient_variance(rv_contravariant) {
|
||||
for a in decl.inputs.iter() {
|
||||
visitor.visit_ty(&a.ty, cx);
|
||||
visitor.visit_ty(&a.ty, ());
|
||||
}
|
||||
}
|
||||
visitor.visit_ty(&decl.output, cx);
|
||||
visitor.visit_ty(&decl.output, ());
|
||||
}
|
||||
}
|
||||
|
||||
_ => {
|
||||
visit::walk_ty(visitor, ty, cx);
|
||||
visit::walk_ty(visitor, ty, ());
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_mt(visitor: &mut DetermineRpVisitor,
|
||||
mt: &ast::mt,
|
||||
cx: @mut DetermineRpCtxt) {
|
||||
mt: &ast::mt) {
|
||||
let cx = visitor.cx;
|
||||
// mutability is invariant
|
||||
if mt.mutbl == ast::MutMutable {
|
||||
do cx.with_ambient_variance(rv_invariant) {
|
||||
visitor.visit_ty(mt.ty, cx);
|
||||
visitor.visit_ty(mt.ty, ());
|
||||
}
|
||||
} else {
|
||||
visitor.visit_ty(mt.ty, cx);
|
||||
visitor.visit_ty(mt.ty, ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn determine_rp_in_struct_field(visitor: &mut DetermineRpVisitor,
|
||||
cm: @ast::struct_field,
|
||||
cx: @mut DetermineRpCtxt) {
|
||||
visit::walk_struct_field(visitor, cm, cx);
|
||||
cm: @ast::struct_field) {
|
||||
visit::walk_struct_field(visitor, cm, ());
|
||||
}
|
||||
|
||||
struct DetermineRpVisitor;
|
||||
struct DetermineRpVisitor {
|
||||
cx: @mut DetermineRpCtxt
|
||||
}
|
||||
|
||||
impl Visitor<@mut DetermineRpCtxt> for DetermineRpVisitor {
|
||||
impl Visitor<()> for DetermineRpVisitor {
|
||||
|
||||
fn visit_fn(&mut self, fk:&fn_kind, fd:&fn_decl,
|
||||
b:&Block, s:Span, n:NodeId, e:@mut DetermineRpCtxt) {
|
||||
determine_rp_in_fn(self, fk, fd, b, s, n, e);
|
||||
b:&Block, s:Span, n:NodeId, _:()) {
|
||||
determine_rp_in_fn(self, fk, fd, b, s, n);
|
||||
}
|
||||
fn visit_item(&mut self, i:@item, e:@mut DetermineRpCtxt) {
|
||||
determine_rp_in_item(self, i, e);
|
||||
fn visit_item(&mut self, i:@item, _:()) {
|
||||
determine_rp_in_item(self, i);
|
||||
}
|
||||
fn visit_ty(&mut self, t:&Ty, e:@mut DetermineRpCtxt) {
|
||||
determine_rp_in_ty(self, t, e);
|
||||
fn visit_ty(&mut self, t:&Ty, _:()) {
|
||||
determine_rp_in_ty(self, t);
|
||||
}
|
||||
fn visit_ty_method(&mut self, t:&TypeMethod, e:@mut DetermineRpCtxt) {
|
||||
determine_rp_in_ty_method(self, t, e);
|
||||
fn visit_ty_method(&mut self, t:&TypeMethod, _:()) {
|
||||
determine_rp_in_ty_method(self, t);
|
||||
}
|
||||
fn visit_struct_field(&mut self, s:@struct_field, e:@mut DetermineRpCtxt) {
|
||||
determine_rp_in_struct_field(self, s, e);
|
||||
fn visit_struct_field(&mut self, s:@struct_field, _:()) {
|
||||
determine_rp_in_struct_field(self, s);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -947,8 +950,8 @@ pub fn determine_rp_in_crate(sess: Session,
|
|||
};
|
||||
|
||||
// Gather up the base set, worklist and dep_map
|
||||
let mut visitor = DetermineRpVisitor;
|
||||
visit::walk_crate(&mut visitor, crate, cx);
|
||||
let mut visitor = DetermineRpVisitor { cx: cx };
|
||||
visit::walk_crate(&mut visitor, crate, ());
|
||||
|
||||
// Propagate indirect dependencies
|
||||
//
|
||||
|
|
|
@ -28,56 +28,53 @@ use util::ppaux::Repr;
|
|||
|
||||
#[deriving(Clone)]
|
||||
struct Context {
|
||||
tcx: ty::ctxt,
|
||||
safe_stack: bool
|
||||
}
|
||||
|
||||
struct StackCheckVisitor;
|
||||
struct StackCheckVisitor {
|
||||
tcx: ty::ctxt,
|
||||
}
|
||||
|
||||
impl Visitor<Context> for StackCheckVisitor {
|
||||
fn visit_item(&mut self, i:@ast::item, e:Context) {
|
||||
stack_check_item(*self, i, e);
|
||||
stack_check_item(self, i, e);
|
||||
}
|
||||
fn visit_fn(&mut self, fk:&visit::fn_kind, fd:&ast::fn_decl,
|
||||
b:&ast::Block, s:Span, n:ast::NodeId, e:Context) {
|
||||
stack_check_fn(*self, fk, fd, b, s, n, e);
|
||||
stack_check_fn(self, fk, fd, b, s, n, e);
|
||||
}
|
||||
fn visit_expr(&mut self, ex:@ast::Expr, e:Context) {
|
||||
stack_check_expr(*self, ex, e);
|
||||
stack_check_expr(self, ex, e);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stack_check_crate(tcx: ty::ctxt,
|
||||
crate: &ast::Crate) {
|
||||
let new_cx = Context {
|
||||
tcx: tcx,
|
||||
safe_stack: false
|
||||
};
|
||||
let mut visitor = StackCheckVisitor;
|
||||
let new_cx = Context { safe_stack: false };
|
||||
let mut visitor = StackCheckVisitor { tcx: tcx };
|
||||
visit::walk_crate(&mut visitor, crate, new_cx);
|
||||
}
|
||||
|
||||
fn stack_check_item(v: StackCheckVisitor,
|
||||
fn stack_check_item(v: &mut StackCheckVisitor,
|
||||
item: @ast::item,
|
||||
in_cx: Context) {
|
||||
let mut v = v;
|
||||
match item.node {
|
||||
ast::item_fn(_, ast::extern_fn, _, _, _) => {
|
||||
// an extern fn is already being called from C code...
|
||||
let new_cx = Context {safe_stack: true, ..in_cx};
|
||||
visit::walk_item(&mut v, item, new_cx);
|
||||
let new_cx = Context {safe_stack: true};
|
||||
visit::walk_item(v, item, new_cx);
|
||||
}
|
||||
ast::item_fn(*) => {
|
||||
let safe_stack = fixed_stack_segment(item.attrs);
|
||||
let new_cx = Context {safe_stack: safe_stack, ..in_cx};
|
||||
visit::walk_item(&mut v, item, new_cx);
|
||||
let new_cx = Context {safe_stack: safe_stack};
|
||||
visit::walk_item(v, item, new_cx);
|
||||
}
|
||||
ast::item_impl(_, _, _, ref methods) => {
|
||||
// visit_method() would make this nicer
|
||||
for &method in methods.iter() {
|
||||
let safe_stack = fixed_stack_segment(method.attrs);
|
||||
let new_cx = Context {safe_stack: safe_stack, ..in_cx};
|
||||
visit::walk_method_helper(&mut v, method, new_cx);
|
||||
let new_cx = Context {safe_stack: safe_stack};
|
||||
visit::walk_method_helper(v, method, new_cx);
|
||||
}
|
||||
}
|
||||
ast::item_trait(_, _, ref methods) => {
|
||||
|
@ -85,15 +82,15 @@ fn stack_check_item(v: StackCheckVisitor,
|
|||
match *method {
|
||||
ast::provided(@ref method) => {
|
||||
let safe_stack = fixed_stack_segment(method.attrs);
|
||||
let new_cx = Context {safe_stack: safe_stack, ..in_cx};
|
||||
visit::walk_method_helper(&mut v, method, new_cx);
|
||||
let new_cx = Context {safe_stack: safe_stack};
|
||||
visit::walk_method_helper(v, method, new_cx);
|
||||
}
|
||||
ast::required(*) => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
visit::walk_item(&mut v, item, in_cx);
|
||||
visit::walk_item(v, item, in_cx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,7 +99,7 @@ fn stack_check_item(v: StackCheckVisitor,
|
|||
}
|
||||
}
|
||||
|
||||
fn stack_check_fn<'a>(v: StackCheckVisitor,
|
||||
fn stack_check_fn<'a>(v: &mut StackCheckVisitor,
|
||||
fk: &visit::fn_kind,
|
||||
decl: &ast::fn_decl,
|
||||
body: &ast::Block,
|
||||
|
@ -114,7 +111,7 @@ fn stack_check_fn<'a>(v: StackCheckVisitor,
|
|||
in_cx.safe_stack // see stack_check_item above
|
||||
}
|
||||
visit::fk_anon(*) | visit::fk_fn_block => {
|
||||
match ty::get(ty::node_id_to_type(in_cx.tcx, id)).sty {
|
||||
match ty::get(ty::node_id_to_type(v.tcx, id)).sty {
|
||||
ty::ty_bare_fn(*) |
|
||||
ty::ty_closure(ty::ClosureTy {sigil: ast::OwnedSigil, _}) => {
|
||||
false
|
||||
|
@ -125,26 +122,25 @@ fn stack_check_fn<'a>(v: StackCheckVisitor,
|
|||
}
|
||||
}
|
||||
};
|
||||
let new_cx = Context {safe_stack: safe_stack, ..in_cx};
|
||||
let new_cx = Context {safe_stack: safe_stack};
|
||||
debug!("stack_check_fn(safe_stack=%b, id=%?)", safe_stack, id);
|
||||
let mut v = v;
|
||||
visit::walk_fn(&mut v, fk, decl, body, sp, id, new_cx);
|
||||
visit::walk_fn(v, fk, decl, body, sp, id, new_cx);
|
||||
}
|
||||
|
||||
fn stack_check_expr<'a>(v: StackCheckVisitor,
|
||||
fn stack_check_expr<'a>(v: &mut StackCheckVisitor,
|
||||
expr: @ast::Expr,
|
||||
cx: Context) {
|
||||
debug!("stack_check_expr(safe_stack=%b, expr=%s)",
|
||||
cx.safe_stack, expr.repr(cx.tcx));
|
||||
cx.safe_stack, expr.repr(v.tcx));
|
||||
if !cx.safe_stack {
|
||||
match expr.node {
|
||||
ast::ExprCall(callee, _, _) => {
|
||||
let callee_ty = ty::expr_ty(cx.tcx, callee);
|
||||
debug!("callee_ty=%s", callee_ty.repr(cx.tcx));
|
||||
let callee_ty = ty::expr_ty(v.tcx, callee);
|
||||
debug!("callee_ty=%s", callee_ty.repr(v.tcx));
|
||||
match ty::get(callee_ty).sty {
|
||||
ty::ty_bare_fn(ref fty) => {
|
||||
if !fty.abis.is_rust() && !fty.abis.is_intrinsic() {
|
||||
call_to_extern_fn(cx, callee);
|
||||
call_to_extern_fn(v, callee);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
@ -153,18 +149,17 @@ fn stack_check_expr<'a>(v: StackCheckVisitor,
|
|||
_ => {}
|
||||
}
|
||||
}
|
||||
let mut v = v;
|
||||
visit::walk_expr(&mut v, expr, cx);
|
||||
visit::walk_expr(v, expr, cx);
|
||||
}
|
||||
|
||||
fn call_to_extern_fn(cx: Context, callee: @ast::Expr) {
|
||||
fn call_to_extern_fn(v: &mut StackCheckVisitor, callee: @ast::Expr) {
|
||||
// Permit direct calls to extern fns that are annotated with
|
||||
// #[rust_stack]. This is naturally a horrible pain to achieve.
|
||||
match callee.node {
|
||||
ast::ExprPath(*) => {
|
||||
match cx.tcx.def_map.find(&callee.id) {
|
||||
match v.tcx.def_map.find(&callee.id) {
|
||||
Some(&ast::DefFn(id, _)) if id.crate == ast::LOCAL_CRATE => {
|
||||
match cx.tcx.items.find(&id.node) {
|
||||
match v.tcx.items.find(&id.node) {
|
||||
Some(&ast_map::node_foreign_item(item, _, _, _)) => {
|
||||
if attr::contains_name(item.attrs, "rust_stack") {
|
||||
return;
|
||||
|
@ -179,7 +174,7 @@ fn call_to_extern_fn(cx: Context, callee: @ast::Expr) {
|
|||
_ => {}
|
||||
}
|
||||
|
||||
cx.tcx.sess.add_lint(lint::cstack,
|
||||
v.tcx.sess.add_lint(lint::cstack,
|
||||
callee.id,
|
||||
callee.span,
|
||||
fmt!("invoking non-Rust fn in fn without \
|
||||
|
|
|
@ -2194,11 +2194,13 @@ pub fn trans_enum_def(ccx: @mut CrateContext, enum_definition: &ast::enum_def,
|
|||
}
|
||||
}
|
||||
|
||||
pub struct TransItemVisitor;
|
||||
pub struct TransItemVisitor {
|
||||
ccx: @mut CrateContext,
|
||||
}
|
||||
|
||||
impl Visitor<@mut CrateContext> for TransItemVisitor {
|
||||
fn visit_item(&mut self, i: @ast::item, ccx: @mut CrateContext) {
|
||||
trans_item(ccx, i);
|
||||
impl Visitor<()> for TransItemVisitor {
|
||||
fn visit_item(&mut self, i: @ast::item, _:()) {
|
||||
trans_item(self.ccx, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2235,8 +2237,8 @@ pub fn trans_item(ccx: @mut CrateContext, item: &ast::item) {
|
|||
} else {
|
||||
// Be sure to travel more than just one layer deep to catch nested
|
||||
// items in blocks and such.
|
||||
let mut v = TransItemVisitor;
|
||||
v.visit_block(body, ccx);
|
||||
let mut v = TransItemVisitor{ ccx: ccx };
|
||||
v.visit_block(body, ());
|
||||
}
|
||||
}
|
||||
ast::item_impl(ref generics, _, _, ref ms) => {
|
||||
|
@ -2288,8 +2290,8 @@ pub fn trans_item(ccx: @mut CrateContext, item: &ast::item) {
|
|||
// functions, but the trait still needs to be walked. Otherwise default
|
||||
// methods with items will not get translated and will cause ICE's when
|
||||
// metadata time comes around.
|
||||
let mut v = TransItemVisitor;
|
||||
visit::walk_item(&mut v, item, ccx);
|
||||
let mut v = TransItemVisitor{ ccx: ccx };
|
||||
visit::walk_item(&mut v, item, ());
|
||||
}
|
||||
_ => {/* fall through */ }
|
||||
}
|
||||
|
|
|
@ -570,18 +570,20 @@ pub fn trans_lang_call_with_type_params(bcx: @mut Block,
|
|||
}
|
||||
|
||||
|
||||
struct CalleeTranslationVisitor;
|
||||
struct CalleeTranslationVisitor {
|
||||
flag: bool,
|
||||
}
|
||||
|
||||
impl Visitor<@mut bool> for CalleeTranslationVisitor {
|
||||
impl Visitor<()> for CalleeTranslationVisitor {
|
||||
|
||||
fn visit_item(&mut self, _:@ast::item, _:@mut bool) { }
|
||||
fn visit_item(&mut self, _:@ast::item, _:()) { }
|
||||
|
||||
fn visit_expr(&mut self, e:@ast::Expr, cx:@mut bool) {
|
||||
fn visit_expr(&mut self, e:@ast::Expr, _:()) {
|
||||
|
||||
if !*cx {
|
||||
if !self.flag {
|
||||
match e.node {
|
||||
ast::ExprRet(_) => *cx = true,
|
||||
_ => visit::walk_expr(self, e, cx),
|
||||
ast::ExprRet(_) => self.flag = true,
|
||||
_ => visit::walk_expr(self, e, ()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -589,10 +591,9 @@ impl Visitor<@mut bool> for CalleeTranslationVisitor {
|
|||
}
|
||||
|
||||
pub fn body_contains_ret(body: &ast::Block) -> bool {
|
||||
let cx = @mut false;
|
||||
let mut v = CalleeTranslationVisitor;
|
||||
visit::walk_block(&mut v, body, cx);
|
||||
*cx
|
||||
let mut v = CalleeTranslationVisitor{ flag: false };
|
||||
visit::walk_block(&mut v, body, ());
|
||||
v.flag
|
||||
}
|
||||
|
||||
pub fn trans_call_inner(in_cx: @mut Block,
|
||||
|
|
|
@ -61,9 +61,9 @@ pub fn trans_impl(ccx: @mut CrateContext,
|
|||
// Both here and below with generic methods, be sure to recurse and look for
|
||||
// items that we need to translate.
|
||||
if !generics.ty_params.is_empty() {
|
||||
let mut v = TransItemVisitor;
|
||||
let mut v = TransItemVisitor{ ccx: ccx };
|
||||
for method in methods.iter() {
|
||||
visit::walk_method_helper(&mut v, *method, ccx);
|
||||
visit::walk_method_helper(&mut v, *method, ());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -80,8 +80,8 @@ pub fn trans_impl(ccx: @mut CrateContext,
|
|||
None,
|
||||
llfn);
|
||||
} else {
|
||||
let mut v = TransItemVisitor;
|
||||
visit::walk_method_helper(&mut v, *method, ccx);
|
||||
let mut v = TransItemVisitor{ ccx: ccx };
|
||||
visit::walk_method_helper(&mut v, *method, ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ pub fn type_uses_for(ccx: @mut CrateContext, fn_id: DefId, n_tps: uint)
|
|||
// Conservatively assume full use for recursive loops
|
||||
ccx.type_use_cache.insert(fn_id, @vec::from_elem(n_tps, use_all));
|
||||
|
||||
let cx = Context {
|
||||
let mut cx = Context {
|
||||
ccx: ccx,
|
||||
uses: @mut vec::from_elem(n_tps, 0u)
|
||||
};
|
||||
|
@ -112,7 +112,7 @@ pub fn type_uses_for(ccx: @mut CrateContext, fn_id: DefId, n_tps: uint)
|
|||
ast_map::node_item(@ast::item { node: item_fn(_, _, _, _, ref body),
|
||||
_ }, _) |
|
||||
ast_map::node_method(@ast::method {body: ref body, _}, _, _) => {
|
||||
handle_body(&cx, body);
|
||||
handle_body(&mut cx, body);
|
||||
}
|
||||
ast_map::node_trait_method(*) => {
|
||||
// This will be a static trait method. For now, we just assume
|
||||
|
@ -414,39 +414,36 @@ pub fn mark_for_expr(cx: &Context, e: &Expr) {
|
|||
}
|
||||
}
|
||||
|
||||
struct TypeUseVisitor;
|
||||
impl Visitor<()> for Context {
|
||||
|
||||
impl<'self> Visitor<&'self Context> for TypeUseVisitor {
|
||||
|
||||
fn visit_expr<'a>(&mut self, e:@Expr, cx: &'a Context) {
|
||||
visit::walk_expr(self, e, cx);
|
||||
mark_for_expr(cx, e);
|
||||
fn visit_expr(&mut self, e:@Expr, _: ()) {
|
||||
visit::walk_expr(self, e, ());
|
||||
mark_for_expr(self, e);
|
||||
}
|
||||
|
||||
fn visit_local<'a>(&mut self, l:@Local, cx: &'a Context) {
|
||||
visit::walk_local(self, l, cx);
|
||||
node_type_needs(cx, use_repr, l.id);
|
||||
fn visit_local(&mut self, l:@Local, _:()) {
|
||||
visit::walk_local(self, l, ());
|
||||
node_type_needs(self, use_repr, l.id);
|
||||
}
|
||||
|
||||
fn visit_pat<'a>(&mut self, p:@Pat, cx: &'a Context) {
|
||||
visit::walk_pat(self, p, cx);
|
||||
node_type_needs(cx, use_repr, p.id);
|
||||
fn visit_pat(&mut self, p:@Pat, _: ()) {
|
||||
visit::walk_pat(self, p, ());
|
||||
node_type_needs(self, use_repr, p.id);
|
||||
}
|
||||
|
||||
fn visit_block<'a>(&mut self, b:&Block, cx: &'a Context) {
|
||||
visit::walk_block(self, b, cx);
|
||||
fn visit_block(&mut self, b:&Block, _: ()) {
|
||||
visit::walk_block(self, b, ());
|
||||
for e in b.expr.iter() {
|
||||
node_type_needs(cx, use_repr, e.id);
|
||||
node_type_needs(self, use_repr, e.id);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_item<'a>(&mut self, _:@item, _: &'a Context) {
|
||||
fn visit_item(&mut self, _:@item, _: ()) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub fn handle_body(cx: &Context, body: &Block) {
|
||||
let mut v = TypeUseVisitor;
|
||||
v.visit_block(body, cx);
|
||||
pub fn handle_body(cx: &mut Context, body: &Block) {
|
||||
cx.visit_block(body, ());
|
||||
}
|
||||
|
|
|
@ -61,17 +61,18 @@ pub fn field_exprs(fields: ~[ast::Field]) -> ~[@ast::Expr] {
|
|||
}
|
||||
|
||||
struct LoopQueryVisitor<'self> {
|
||||
p: &'self fn(&ast::Expr_) -> bool
|
||||
p: &'self fn(&ast::Expr_) -> bool,
|
||||
flag: bool,
|
||||
}
|
||||
|
||||
impl<'self> Visitor<@mut bool> for LoopQueryVisitor<'self> {
|
||||
fn visit_expr(&mut self, e: @ast::Expr, flag: @mut bool) {
|
||||
*flag |= (self.p)(&e.node);
|
||||
impl<'self> Visitor<()> for LoopQueryVisitor<'self> {
|
||||
fn visit_expr(&mut self, e: @ast::Expr, _: ()) {
|
||||
self.flag |= (self.p)(&e.node);
|
||||
match e.node {
|
||||
// Skip inner loops, since a break in the inner loop isn't a
|
||||
// break inside the outer loop
|
||||
ast::ExprLoop(*) | ast::ExprWhile(*) => {}
|
||||
_ => visit::walk_expr(self, e, flag)
|
||||
_ => visit::walk_expr(self, e, ())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -79,34 +80,35 @@ impl<'self> Visitor<@mut bool> for LoopQueryVisitor<'self> {
|
|||
// Takes a predicate p, returns true iff p is true for any subexpressions
|
||||
// of b -- skipping any inner loops (loop, while, loop_body)
|
||||
pub fn loop_query(b: &ast::Block, p: &fn(&ast::Expr_) -> bool) -> bool {
|
||||
let rs = @mut false;
|
||||
let mut v = LoopQueryVisitor {
|
||||
p: p,
|
||||
flag: false,
|
||||
};
|
||||
visit::walk_block(&mut v, b, rs);
|
||||
return *rs;
|
||||
visit::walk_block(&mut v, b, ());
|
||||
return v.flag;
|
||||
}
|
||||
|
||||
struct BlockQueryVisitor<'self> {
|
||||
p: &'self fn(@ast::Expr) -> bool
|
||||
p: &'self fn(@ast::Expr) -> bool,
|
||||
flag: bool,
|
||||
}
|
||||
|
||||
impl<'self> Visitor<@mut bool> for BlockQueryVisitor<'self> {
|
||||
fn visit_expr(&mut self, e: @ast::Expr, flag: @mut bool) {
|
||||
*flag |= (self.p)(e);
|
||||
visit::walk_expr(self, e, flag)
|
||||
impl<'self> Visitor<()> for BlockQueryVisitor<'self> {
|
||||
fn visit_expr(&mut self, e: @ast::Expr, _:()) {
|
||||
self.flag |= (self.p)(e);
|
||||
visit::walk_expr(self, e, ())
|
||||
}
|
||||
}
|
||||
|
||||
// Takes a predicate p, returns true iff p is true for any subexpressions
|
||||
// of b -- skipping any inner loops (loop, while, loop_body)
|
||||
pub fn block_query(b: &ast::Block, p: &fn(@ast::Expr) -> bool) -> bool {
|
||||
let rs = @mut false;
|
||||
let mut v = BlockQueryVisitor {
|
||||
p: p,
|
||||
flag: false,
|
||||
};
|
||||
visit::walk_block(&mut v, b, rs);
|
||||
return *rs;
|
||||
visit::walk_block(&mut v, b, ());
|
||||
return v.flag;
|
||||
}
|
||||
|
||||
pub fn local_rhs_span(l: @ast::Local, def: Span) -> Span {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue