remove ctor from ast (take 2) (no review: just dead code removal)

This commit is contained in:
Niko Matsakis 2012-10-08 11:49:01 -07:00
parent cb55e246ba
commit 98887cc7ee
31 changed files with 137 additions and 672 deletions

View File

@ -137,7 +137,7 @@ enum def {
@def, // closed over def
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_class(def_id),
def_typaram_binder(node_id), /* class, impl or trait that has ty params */
def_region(node_id),
def_label(node_id)
@ -238,9 +238,9 @@ impl def : cmp::Eq {
_ => false
}
}
def_class(e0a, e1a) => {
def_class(e0a) => {
match (*other) {
def_class(e0b, e1b) => e0a == e0b && e1a == e1b,
def_class(e0b) => e0a == e0b,
_ => false
}
}
@ -1465,8 +1465,6 @@ enum struct_field_kind {
fields: ~[@struct_field], /* fields */
methods: ~[@method], /* methods */
/* (not including ctor or dtor) */
/* ctor is optional, and will soon go away */
ctor: Option<class_ctor>,
/* dtor is optional */
dtor: Option<class_dtor>
};
@ -1566,7 +1564,6 @@ enum inlined_item {
ii_item(@item),
ii_method(def_id /* impl id */, @method),
ii_foreign(@foreign_item),
ii_ctor(class_ctor, ident, ~[ty_param], def_id /* parent id */),
ii_dtor(class_dtor, ident, ~[ty_param], def_id /* parent id */)
}

View File

@ -71,9 +71,6 @@ enum ast_node {
// order they are introduced.
node_arg(arg, uint),
node_local(uint),
// Constructor for a class
// def_id is parent id
node_ctor(ident, ~[ty_param], @class_ctor, def_id, @path),
// Destructor for a class
node_dtor(~[ty_param], @class_dtor, def_id, @path),
node_block(blk),
@ -132,7 +129,7 @@ fn map_decoded_item(diag: span_handler,
// don't decode and instantiate the impl, but just the method, we have to
// add it to the table now:
match ii {
ii_item(*) | ii_ctor(*) | ii_dtor(*) => { /* fallthrough */ }
ii_item(*) | ii_dtor(*) => { /* fallthrough */ }
ii_foreign(i) => {
cx.map.insert(i.id, node_foreign_item(i, foreign_abi_rust_intrinsic,
@path));
@ -155,18 +152,6 @@ fn map_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
cx.local_id += 1u;
}
match fk {
visit::fk_ctor(nm, attrs, tps, self_id, parent_id) => {
let ct = @{node: {id: id,
attrs: attrs,
self_id: self_id,
dec: /* FIXME (#2543) */ copy decl,
body: /* FIXME (#2543) */ copy body},
span: sp};
cx.map.insert(id, node_ctor(/* FIXME (#2543) */ copy nm,
/* FIXME (#2543) */ copy tps,
ct, parent_id,
@/* FIXME (#2543) */ copy cx.path));
}
visit::fk_dtor(tps, attrs, self_id, parent_id) => {
let dt = @{node: {id: id, attrs: attrs, self_id: self_id,
body: /* FIXME (#2543) */ copy body}, span: sp};
@ -382,9 +367,6 @@ fn node_id_to_str(map: map, id: node_id, itr: @ident_interner) -> ~str {
Some(node_local(_)) => { // add more info here
fmt!("local (id=%?)", id)
}
Some(node_ctor(*)) => { // add more info here
fmt!("node_ctor (id=%?)", id)
}
Some(node_dtor(*)) => { // add more info here
fmt!("node_dtor (id=%?)", id)
}

View File

@ -57,7 +57,7 @@ fn variant_def_ids(d: def) -> {enm: def_id, var: def_id} {
def_fn(id, _) | def_static_method(id, _, _) | def_mod(id) |
def_foreign_mod(id) | def_const(id) |
def_variant(_, id) | def_ty(id) | def_ty_param(id, _) |
def_use(id) | def_class(id, _) => {
def_use(id) | def_class(id) => {
id
}
def_arg(id, _) | def_local(id, _) | def_self(id) |
@ -338,7 +338,6 @@ fn ident() -> ident {
ii_item(i) => /* FIXME (#2543) */ copy i.ident,
ii_foreign(i) => /* FIXME (#2543) */ copy i.ident,
ii_method(_, m) => /* FIXME (#2543) */ copy m.ident,
ii_ctor(_, nm, _, _) => /* FIXME (#2543) */ copy nm,
ii_dtor(_, nm, _, _) => /* FIXME (#2543) */ copy nm
}
}
@ -348,7 +347,6 @@ fn id() -> ast::node_id {
ii_item(i) => i.id,
ii_foreign(i) => i.id,
ii_method(_, m) => m.id,
ii_ctor(ctor, _, _, _) => ctor.node.id,
ii_dtor(dtor, _, _, _) => dtor.node.id
}
}
@ -358,9 +356,6 @@ fn accept<E>(e: E, v: visit::vt<E>) {
ii_item(i) => v.visit_item(i, e, v),
ii_foreign(i) => v.visit_foreign_item(i, e, v),
ii_method(_, m) => visit::visit_method_helper(m, e, v),
ii_ctor(ctor, nm, tps, parent_id) => {
visit::visit_class_ctor_helper(ctor, nm, tps, parent_id, e, v);
}
ii_dtor(dtor, _, tps, parent_id) => {
visit::visit_class_dtor_helper(dtor, tps, parent_id, e, v);
}
@ -494,12 +489,6 @@ fn id_visitor(vfn: fn@(node_id)) -> visit::vt<()> {
vfn(id);
match fk {
visit::fk_ctor(_, _, tps, self_id, parent_id) => {
for vec::each(tps) |tp| { vfn(tp.id); }
vfn(id);
vfn(self_id);
vfn(parent_id.node);
}
visit::fk_dtor(tps, _, self_id, parent_id) => {
for vec::each(tps) |tp| { vfn(tp.id); }
vfn(id);

View File

@ -271,23 +271,6 @@ fn noop_fold_item_underscore(i: item_, fld: ast_fold) -> item_ {
fn fold_struct_def(struct_def: @ast::struct_def, fld: ast_fold)
-> @ast::struct_def {
let resulting_optional_constructor;
match struct_def.ctor {
None => {
resulting_optional_constructor = None;
}
Some(constructor) => {
resulting_optional_constructor = Some({
node: {
body: fld.fold_block(constructor.node.body),
dec: fold_fn_decl(constructor.node.dec, fld),
id: fld.new_id(constructor.node.id),
.. constructor.node
},
.. constructor
});
}
}
let dtor = do option::map(&struct_def.dtor) |dtor| {
let dtor_body = fld.fold_block(dtor.node.body);
let dtor_id = fld.new_id(dtor.node.id);
@ -298,7 +281,6 @@ fn fold_struct_def(struct_def: @ast::struct_def, fld: ast_fold)
traits: vec::map(struct_def.traits, |p| fold_trait_ref(*p, fld)),
fields: vec::map(struct_def.fields, |f| fold_struct_field(*f, fld)),
methods: vec::map(struct_def.methods, |m| fld.fold_method(*m)),
ctor: resulting_optional_constructor,
dtor: dtor
};
}
@ -585,7 +567,6 @@ fn fold_variant_arg_(va: variant_arg, fld: ast_fold) -> variant_arg {
|f| fld.fold_struct_field(*f)),
methods: vec::map(struct_def.methods,
|m| fld.fold_method(*m)),
ctor: None,
dtor: dtor
})
}

View File

@ -115,8 +115,7 @@ enum class_member {
So that we can distinguish a class ctor or dtor
from other class members
*/
enum class_contents { ctor_decl(fn_decl, ~[attribute], blk, codemap::span),
dtor_decl(blk, ~[attribute], codemap::span),
enum class_contents { dtor_decl(blk, ~[attribute], codemap::span),
members(~[@class_member]) }
type arg_or_capture_item = Either<arg, capture_item>;
@ -2683,30 +2682,13 @@ fn parse_item_class() -> item_info {
let mut fields: ~[@struct_field];
let mut methods: ~[@method] = ~[];
let mut the_ctor: Option<(fn_decl, ~[attribute], blk, codemap::span)>
= None;
let mut the_dtor: Option<(blk, ~[attribute], codemap::span)> = None;
let ctor_id = self.get_id();
if self.eat(token::LBRACE) {
// It's a record-like struct.
fields = ~[];
while self.token != token::RBRACE {
match self.parse_class_item() {
ctor_decl(a_fn_decl, attrs, blk, s) => {
match the_ctor {
Some((_, _, _, s_first)) => {
self.span_note(s, fmt!("Duplicate constructor \
declaration for class %s",
*self.interner.get(class_name)));
self.span_fatal(copy s_first, ~"First constructor \
declared here");
}
None => {
the_ctor = Some((a_fn_decl, attrs, blk, s));
}
}
}
dtor_decl(blk, attrs, s) => {
match the_dtor {
Some((_, _, s_first)) => {
@ -2764,36 +2746,14 @@ fn parse_item_class() -> item_info {
self_id: self.get_id(),
body: d_body},
span: d_s}};
match the_ctor {
Some((ct_d, ct_attrs, ct_b, ct_s)) => {
(class_name,
item_class(@{
traits: traits,
fields: move fields,
methods: move methods,
ctor: Some({
node: {id: ctor_id,
attrs: ct_attrs,
self_id: self.get_id(),
dec: ct_d,
body: ct_b},
span: ct_s}),
dtor: actual_dtor
}, ty_params),
None)
}
None => {
(class_name,
item_class(@{
traits: traits,
fields: move fields,
methods: move methods,
ctor: None,
dtor: actual_dtor
}, ty_params),
None)
}
}
(class_name,
item_class(@{
traits: traits,
fields: move fields,
methods: move methods,
dtor: actual_dtor
}, ty_params),
None)
}
fn token_is_pound_or_doc_comment(++tok: token::token) -> bool {
@ -3097,12 +3057,6 @@ fn parse_struct_def() -> @struct_def {
let mut methods: ~[@method] = ~[];
while self.token != token::RBRACE {
match self.parse_class_item() {
ctor_decl(*) => {
self.span_fatal(copy self.span,
~"deprecated explicit \
constructors are not allowed \
here");
}
dtor_decl(blk, attrs, s) => {
match the_dtor {
Some((_, _, s_first)) => {
@ -3143,7 +3097,6 @@ fn parse_struct_def() -> @struct_def {
traits: ~[],
fields: move fields,
methods: move methods,
ctor: None,
dtor: actual_dtor
};
}

View File

@ -653,18 +653,6 @@ fn print_struct(s: ps, struct_def: @ast::struct_def, tps: ~[ast::ty_param],
}
bopen(s);
hardbreak_if_not_bol(s);
do struct_def.ctor.iter |ctor| {
maybe_print_comment(s, ctor.span.lo);
print_outer_attributes(s, ctor.node.attrs);
// Doesn't call head because there shouldn't be a space after new.
cbox(s, indent_unit);
ibox(s, 4);
word(s.s, ~"new(");
print_fn_args(s, ctor.node.dec, ~[], None);
word(s.s, ~")");
space(s.s);
print_block(s, ctor.node.body);
}
do struct_def.dtor.iter |dtor| {
hardbreak_if_not_bol(s);
maybe_print_comment(s, dtor.span.lo);

View File

@ -17,8 +17,6 @@ enum fn_kind {
fk_method(ident, ~[ty_param], @method),
fk_anon(proto, capture_clause), //< an anonymous function like fn@(...)
fk_fn_block(capture_clause), //< a block {||...}
fk_ctor(ident, ~[attribute], ~[ty_param], node_id /* self id */,
def_id /* parent class id */), // class constructor
fk_dtor(~[ty_param], ~[attribute], node_id /* self id */,
def_id /* parent class id */) // class destructor
@ -26,8 +24,9 @@ enum fn_kind {
fn name_of_fn(fk: fn_kind) -> ident {
match fk {
fk_item_fn(name, _, _) | fk_method(name, _, _)
| fk_ctor(name, _, _, _, _) => /* FIXME (#2543) */ copy name,
fk_item_fn(name, _, _) | fk_method(name, _, _) => {
/* FIXME (#2543) */ copy name
}
fk_anon(*) | fk_fn_block(*) => parse::token::special_idents::anon,
fk_dtor(*) => parse::token::special_idents::dtor
}
@ -35,11 +34,11 @@ fn name_of_fn(fk: fn_kind) -> ident {
fn tps_of_fn(fk: fn_kind) -> ~[ty_param] {
match fk {
fk_item_fn(_, tps, _) | fk_method(_, tps, _)
| fk_ctor(_, _, tps, _, _) | fk_dtor(tps, _, _, _) => {
/* FIXME (#2543) */ copy tps
}
fk_anon(*) | fk_fn_block(*) => ~[]
fk_item_fn(_, tps, _) | fk_method(_, tps, _) |
fk_dtor(tps, _, _, _) => {
/* FIXME (#2543) */ copy tps
}
fk_anon(*) | fk_fn_block(*) => ~[]
}
}
@ -291,17 +290,6 @@ fn visit_method_helper<E>(m: @method, e: E, v: vt<E>) {
m.decl, m.body, m.span, m.id, e, v);
}
// Similar logic to the comment on visit_method_helper - Tim
fn visit_class_ctor_helper<E>(ctor: class_ctor, nm: ident, tps: ~[ty_param],
parent_id: def_id, e: E, v: vt<E>) {
v.visit_fn(fk_ctor(/* FIXME (#2543) */ copy nm,
ctor.node.attrs,
/* FIXME (#2543) */ copy tps,
ctor.node.self_id, parent_id),
ctor.node.dec, ctor.node.body, ctor.span, ctor.node.id, e, v)
}
fn visit_class_dtor_helper<E>(dtor: class_dtor, tps: ~[ty_param],
parent_id: def_id, e: E, v: vt<E>) {
v.visit_fn(fk_dtor(/* FIXME (#2543) */ copy tps, dtor.node.attrs,
@ -330,7 +318,7 @@ fn visit_trait_method<E>(m: trait_method, e: E, v: vt<E>) {
}
}
fn visit_struct_def<E>(sd: @struct_def, nm: ast::ident, tps: ~[ty_param],
fn visit_struct_def<E>(sd: @struct_def, _nm: ast::ident, tps: ~[ty_param],
id: node_id, e: E, v: vt<E>) {
for sd.fields.each |f| {
v.visit_struct_field(*f, e, v);
@ -341,9 +329,6 @@ fn visit_struct_def<E>(sd: @struct_def, nm: ast::ident, tps: ~[ty_param],
for sd.traits.each |p| {
visit_path(p.path, e, v);
}
do option::iter(&sd.ctor) |ctor| {
visit_class_ctor_helper(*ctor, nm, tps, ast_util::local_def(id), e, v);
};
do option::iter(&sd.dtor) |dtor| {
visit_class_dtor_helper(*dtor, tps, ast_util::local_def(id), e, v)
};

View File

@ -124,7 +124,6 @@ enum Family {
Variant, // v
Impl, // i
Trait, // I
Class, // C
Struct, // S
PublicField, // g
PrivateField, // j
@ -157,7 +156,6 @@ fn item_family(item: ebml::Doc) -> Family {
'v' => Variant,
'i' => Impl,
'I' => Trait,
'C' => Class,
'S' => Struct,
'g' => PublicField,
'j' => PrivateField,
@ -308,8 +306,7 @@ fn item_to_def_like(item: ebml::Doc, did: ast::def_id, cnum: ast::crate_num)
let fam = item_family(item);
match fam {
Const => dl_def(ast::def_const(did)),
Class => dl_def(ast::def_class(did, true)),
Struct => dl_def(ast::def_class(did, false)),
Struct => dl_def(ast::def_class(did)),
UnsafeFn => dl_def(ast::def_fn(did, ast::unsafe_fn)),
Fn => dl_def(ast::def_fn(did, ast::impure_fn)),
PureFn => dl_def(ast::def_fn(did, ast::pure_fn)),
@ -832,7 +829,6 @@ fn item_family_to_str(fam: Family) -> ~str {
Variant => ~"variant",
Impl => ~"impl",
Trait => ~"trait",
Class => ~"class",
Struct => ~"struct",
PublicField => ~"public field",
PrivateField => ~"private field",

View File

@ -635,12 +635,7 @@ fn add_to_index_(item: @item, ebml_w: ebml::Serializer,
/* Now, make an item for the class itself */
ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, local_def(item.id));
match struct_def.ctor {
None => encode_family(ebml_w, 'S'),
Some(_) => encode_family(ebml_w, 'C')
}
encode_family(ebml_w, 'S');
encode_type_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
encode_name(ecx, ebml_w, item.ident);
@ -699,21 +694,6 @@ fn add_to_index_(item: @item, ebml_w: ebml::Serializer,
let bkts = create_index(idx);
encode_index(ebml_w, bkts, write_int);
ebml_w.end_tag();
/* Encode the constructor */
for struct_def.ctor.each |ctor| {
debug!("encoding info for ctor %s %d",
ecx.tcx.sess.str_of(item.ident), ctor.node.id);
index.push({
val: ctor.node.id,
pos: ebml_w.writer.tell()
});
encode_info_for_ctor(ecx, ebml_w, ctor.node.id, item.ident,
path, if tps.len() > 0u {
Some(ii_ctor(*ctor, item.ident, tps,
local_def(item.id))) }
else { None }, tps);
}
}
item_impl(tps, opt_trait, _, methods) => {
add_to_index();

View File

@ -261,13 +261,6 @@ fn drop_nested_items(blk: ast::blk_, fld: fold::ast_fold) -> ast::blk_ {
ast::ii_foreign(i) => {
ast::ii_foreign(fld.fold_foreign_item(i))
}
ast::ii_ctor(ctor, nm, tps, parent_id) => {
let ctor_body = fld.fold_block(ctor.node.body);
let ctor_decl = fold::fold_fn_decl(ctor.node.dec, fld);
ast::ii_ctor({node: {body: ctor_body, dec: ctor_decl,
.. ctor.node},
.. ctor}, nm, tps, parent_id)
}
ast::ii_dtor(dtor, nm, tps, parent_id) => {
let dtor_body = fld.fold_block(dtor.node.body);
ast::ii_dtor({node: {body: dtor_body,
@ -301,18 +294,6 @@ fn renumber_ast(xcx: extended_decode_ctxt, ii: ast::inlined_item)
ast::ii_foreign(i) => {
ast::ii_foreign(fld.fold_foreign_item(i))
}
ast::ii_ctor(ctor, nm, tps, parent_id) => {
let ctor_body = fld.fold_block(ctor.node.body);
let ctor_attrs = fld.fold_attributes(ctor.node.attrs);
let ctor_decl = fold::fold_fn_decl(ctor.node.dec, fld);
let new_params = fold::fold_ty_params(tps, fld);
let ctor_id = fld.new_id(ctor.node.id);
let new_parent = xcx.tr_def_id(parent_id);
ast::ii_ctor({node: {body: ctor_body, attrs: ctor_attrs,
dec: ctor_decl, id: ctor_id,
.. ctor.node},
.. ctor}, nm, new_params, new_parent)
}
ast::ii_dtor(dtor, nm, tps, parent_id) => {
let dtor_body = fld.fold_block(dtor.node.body);
let dtor_attrs = fld.fold_attributes(dtor.node.attrs);
@ -368,8 +349,8 @@ fn tr(xcx: extended_decode_ctxt) -> ast::def {
xcx.tr_id(nid2),
xcx.tr_id(nid3))
}
ast::def_class(did, has_constructor) => {
ast::def_class(did.tr(xcx), has_constructor)
ast::def_class(did) => {
ast::def_class(did.tr(xcx))
}
ast::def_region(nid) => ast::def_region(xcx.tr_id(nid)),
ast::def_typaram_binder(nid) => {

View File

@ -17,10 +17,6 @@ enum check_loan_ctxt = @{
reported: HashMap<ast::node_id, ()>,
// Keep track of whether we're inside a ctor, so as to
// allow mutating immutable fields in the same class if
// we are in a ctor, we track the self id
mut in_ctor: bool,
mut declared_purity: ast::purity,
mut fn_args: @~[ast::node_id]
};
@ -62,7 +58,6 @@ fn check_loans(bccx: borrowck_ctxt,
let clcx = check_loan_ctxt(@{bccx: bccx,
req_maps: req_maps,
reported: HashMap(),
mut in_ctor: false,
mut declared_purity: ast::impure_fn,
mut fn_args: @~[]});
let vt = visit::mk_vt(@{visit_expr: check_loans_in_expr,
@ -320,10 +315,7 @@ fn check_assignment(at: assignment_type, ex: @ast::expr) {
debug!("check_assignment(cmt=%s)",
self.bccx.cmt_to_repr(cmt));
if self.in_ctor && self.is_self_field(cmt)
&& at.checked_by_liveness() {
// assigning to self.foo in a ctor is always allowed.
} else if self.is_local_variable(cmt) && at.checked_by_liveness() {
if self.is_local_variable(cmt) && at.checked_by_liveness() {
// liveness guarantees that immutable local variables
// are only assigned once
} else {
@ -542,42 +534,28 @@ fn check_loans_in_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk,
visitor: visit::vt<check_loan_ctxt>) {
debug!("purity on entry=%?", copy self.declared_purity);
do save_and_restore(&mut(self.in_ctor)) {
do save_and_restore(&mut(self.declared_purity)) {
do save_and_restore(&mut(self.fn_args)) {
let is_stack_closure = self.is_stack_closure(id);
let fty = ty::node_id_to_type(self.tcx(), id);
self.declared_purity = ty::determine_inherited_purity(
copy self.declared_purity,
ty::ty_fn_purity(fty),
ty::ty_fn_proto(fty));
do save_and_restore(&mut(self.declared_purity)) {
do save_and_restore(&mut(self.fn_args)) {
let is_stack_closure = self.is_stack_closure(id);
let fty = ty::node_id_to_type(self.tcx(), id);
self.declared_purity = ty::determine_inherited_purity(
copy self.declared_purity,
ty::ty_fn_purity(fty),
ty::ty_fn_proto(fty));
// In principle, we could consider fk_anon(*) or
// fk_fn_block(*) to be in a ctor, I suppose, but the
// purpose of the in_ctor flag is to allow modifications
// of otherwise immutable fields and typestate wouldn't be
// able to "see" into those functions anyway, so it
// wouldn't be very helpful.
match fk {
visit::fk_ctor(*) => {
self.in_ctor = true;
self.fn_args = @decl.inputs.map(|i| i.id );
}
visit::fk_anon(*) |
visit::fk_fn_block(*) if is_stack_closure => {
self.in_ctor = false;
match fk {
visit::fk_anon(*) |
visit::fk_fn_block(*) if is_stack_closure => {
// inherits the fn_args from enclosing ctxt
}
visit::fk_anon(*) | visit::fk_fn_block(*) |
visit::fk_method(*) | visit::fk_item_fn(*) |
visit::fk_dtor(*) => {
self.in_ctor = false;
self.fn_args = @decl.inputs.map(|i| i.id );
}
}
visit::visit_fn(fk, decl, body, sp, id, self, visitor);
visit::fk_anon(*) | visit::fk_fn_block(*) |
visit::fk_method(*) | visit::fk_item_fn(*) |
visit::fk_dtor(*) => {
self.fn_args = @decl.inputs.map(|i| i.id );
}
}
visit::visit_fn(fk, decl, body, sp, id, self, visitor);
}
}
debug!("purity on exit=%?", copy self.declared_purity);

View File

@ -71,11 +71,11 @@ fn req_loans_in_fn(fk: visit::fn_kind,
self.root_ub = body.node.id;
match fk {
visit::fk_anon(*) | visit::fk_fn_block(*) => {}
visit::fk_item_fn(*) | visit::fk_method(*) |
visit::fk_ctor(*) | visit::fk_dtor(*) => {
self.item_ub = body.node.id;
}
visit::fk_anon(*) | visit::fk_fn_block(*) => {}
visit::fk_item_fn(*) | visit::fk_method(*) |
visit::fk_dtor(*) => {
self.item_ub = body.node.id;
}
}
visit::visit_fn(fk, decl, body, sp, id, self, v);

View File

@ -181,9 +181,9 @@ fn check_fn(fk: visit::fn_kind, decl: fn_decl, body: blk, sp: span,
// variables. This list is used below to avoid checking and reporting
// on a given variable twice.
let cap_clause = match fk {
visit::fk_anon(_, cc) | visit::fk_fn_block(cc) => cc,
visit::fk_item_fn(*) | visit::fk_method(*) |
visit::fk_ctor(*) | visit::fk_dtor(*) => @~[]
visit::fk_anon(_, cc) | visit::fk_fn_block(cc) => cc,
visit::fk_item_fn(*) | visit::fk_method(*) |
visit::fk_dtor(*) => @~[]
};
let captured_vars = do (*cap_clause).map |cap_item| {
let cap_def = cx.tcx.def_map.get(cap_item.id);

View File

@ -35,12 +35,6 @@
* Any use of the variable where the variable is dead afterwards is a
* last use.
*
* # Extension to handle constructors
*
* Each field is assigned an index just as with local variables. A use of
* `self` is considered a use of all fields. A use of `self.f` is just a use
* of `f`.
*
* # Implementation details
*
* The actual implementation contains two (nested) walks over the AST.
@ -96,8 +90,6 @@
* - `no_ret_var`: a synthetic variable that is only 'read' from, the
* fallthrough node. This allows us to detect functions where we fail
* to return explicitly.
*
* - `self_var`: a variable representing 'self'
*/
use dvec::DVec;
@ -230,9 +222,11 @@ impl LiveNode {
fn invalid_node() -> LiveNode { LiveNode(uint::max_value) }
enum RelevantDef { RelevantVar(node_id), RelevantSelf }
type CaptureInfo = {ln: LiveNode, is_move: bool, rv: RelevantDef};
struct CaptureInfo {
ln: LiveNode,
is_move: bool,
var_nid: node_id
}
enum LocalKind {
FromMatch(binding_mode),
@ -250,18 +244,15 @@ struct LocalInfo {
enum VarKind {
Arg(node_id, ident, rmode),
Local(LocalInfo),
Field(ident),
Self,
ImplicitRet
}
fn relevant_def(def: def) -> Option<RelevantDef> {
fn relevant_def(def: def) -> Option<node_id> {
match def {
def_self(_) => Some(RelevantSelf),
def_binding(nid, _) |
def_arg(nid, _) |
def_local(nid, _) => Some(RelevantVar(nid)),
def_local(nid, _) => Some(nid),
_ => None
}
@ -276,7 +267,6 @@ struct IrMaps {
mut num_vars: uint,
live_node_map: HashMap<node_id, LiveNode>,
variable_map: HashMap<node_id, Variable>,
field_map: HashMap<ident, Variable>,
capture_map: HashMap<node_id, @~[CaptureInfo]>,
mut var_kinds: ~[VarKind],
mut lnks: ~[LiveNodeKind],
@ -293,7 +283,6 @@ fn IrMaps(tcx: ty::ctxt, method_map: typeck::method_map,
live_node_map: HashMap(),
variable_map: HashMap(),
capture_map: HashMap(),
field_map: HashMap(),
var_kinds: ~[],
lnks: ~[]
}
@ -323,15 +312,12 @@ fn add_variable(vk: VarKind) -> Variable {
self.num_vars += 1u;
match vk {
Local(LocalInfo {id:node_id, _}) |
Arg(node_id, _, _) => {
self.variable_map.insert(node_id, v);
}
Field(name) => {
self.field_map.insert(name, v);
}
Self | ImplicitRet => {
}
Local(LocalInfo {id:node_id, _}) |
Arg(node_id, _, _) => {
self.variable_map.insert(node_id, v);
}
Self | ImplicitRet => {
}
}
debug!("%s is %?", v.to_str(), vk);
@ -351,11 +337,10 @@ fn variable(node_id: node_id, span: span) -> Variable {
fn variable_name(var: Variable) -> ~str {
match copy self.var_kinds[*var] {
Local(LocalInfo {ident: nm, _}) |
Arg(_, nm, _) => self.tcx.sess.str_of(nm),
Field(nm) => ~"self." + self.tcx.sess.str_of(nm),
Self => ~"self",
ImplicitRet => ~"<implicit-ret>"
Local(LocalInfo {ident: nm, _}) |
Arg(_, nm, _) => self.tcx.sess.str_of(nm),
Self => ~"self",
ImplicitRet => ~"<implicit-ret>"
}
}
@ -399,7 +384,7 @@ fn add_last_use(expr_id: node_id, var: Variable) {
(*v).push(id);
}
Arg(_, _, by_ref) |
Arg(_, _, by_val) | Self | Field(_) | ImplicitRet |
Arg(_, _, by_val) | Self | ImplicitRet |
Local(LocalInfo {kind: FromMatch(bind_by_implicit_ref), _}) => {
debug!("--but it is not owned");
}
@ -428,13 +413,6 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
// and so forth:
visit::visit_fn(fk, decl, body, sp, id, fn_maps, v);
match fk {
visit::fk_ctor(_, _, _, _, class_did) => {
add_class_fields(fn_maps, class_did);
}
_ => {}
}
// Special nodes and variables:
// - exit_ln represents the end of the fn, either by return or fail
// - implicit_ret_var is a pseudo-variable that represents
@ -442,8 +420,7 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
let specials = {
exit_ln: (*fn_maps).add_live_node(ExitNode),
fallthrough_ln: (*fn_maps).add_live_node(ExitNode),
no_ret_var: (*fn_maps).add_variable(ImplicitRet),
self_var: (*fn_maps).add_variable(Self)
no_ret_var: (*fn_maps).add_variable(ImplicitRet)
};
// compute liveness
@ -460,18 +437,9 @@ fn visit_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
});
check_vt.visit_block(body, lsets, check_vt);
lsets.check_ret(id, sp, fk, entry_ln);
lsets.check_fields(sp, entry_ln);
lsets.warn_about_unused_args(sp, decl, entry_ln);
}
fn add_class_fields(self: @IrMaps, did: def_id) {
for ty::lookup_class_fields(self.tcx, did).each |field_ty| {
assert field_ty.id.crate == local_crate;
let var = self.add_variable(Field(field_ty.ident));
self.field_map.insert(field_ty.ident, var);
}
}
fn visit_local(local: @local, &&self: @IrMaps, vt: vt<@IrMaps>) {
let def_map = self.tcx.def_map;
do pat_util::pat_bindings(def_map, local.node.pat) |_bm, p_id, sp, path| {
@ -540,7 +508,9 @@ fn visit_expr(expr: @expr, &&self: @IrMaps, vt: vt<@IrMaps>) {
cap_move | cap_drop => true, // var must be dead afterwards
cap_copy | cap_ref => false // var can still be used
};
call_caps.push({ln: cv_ln, is_move: is_move, rv: rv});
call_caps.push(CaptureInfo {ln: cv_ln,
is_move: is_move,
var_nid: rv});
}
None => {}
}
@ -595,8 +565,7 @@ fn invalid_users() -> users {
type Specials = {
exit_ln: LiveNode,
fallthrough_ln: LiveNode,
no_ret_var: Variable,
self_var: Variable
no_ret_var: Variable
};
const ACC_READ: uint = 1u;
@ -647,19 +616,12 @@ fn live_node(node_id: node_id, span: span) -> LiveNode {
}
}
fn variable_from_rdef(rv: RelevantDef, span: span) -> Variable {
match rv {
RelevantSelf => self.s.self_var,
RelevantVar(nid) => self.variable(nid, span)
}
}
fn variable_from_path(expr: @expr) -> Option<Variable> {
match expr.node {
expr_path(_) => {
let def = self.tcx.def_map.get(expr.id);
relevant_def(def).map(
|rdef| self.variable_from_rdef(*rdef, expr.span)
|rdef| self.variable(*rdef, expr.span)
)
}
_ => None
@ -675,7 +637,7 @@ fn variable_from_def_map(node_id: node_id,
match self.tcx.def_map.find(node_id) {
Some(def) => {
relevant_def(def).map(
|rdef| self.variable_from_rdef(*rdef, span)
|rdef| self.variable(*rdef, span)
)
}
None => {
@ -934,14 +896,6 @@ fn propagate_through_fn_block(decl: fn_decl, blk: blk) -> LiveNode {
}
}
// as above, the "self" variable is a non-owned variable
self.acc(self.s.exit_ln, self.s.self_var, ACC_READ);
// in a ctor, there is an implicit use of self.f for all fields f:
for self.ir.field_map.each_value |var| {
self.acc(self.s.exit_ln, var, ACC_READ|ACC_USE);
}
// the fallthrough exit is only for those cases where we do not
// explicitly return:
self.init_from_succ(self.s.fallthrough_ln, self.s.exit_ln);
@ -1023,24 +977,11 @@ fn propagate_through_expr(expr: @expr, succ: LiveNode) -> LiveNode {
// Interesting cases with control flow or which gen/kill
expr_path(_) => {
self.access_path(expr, succ, ACC_READ | ACC_USE)
self.access_path(expr, succ, ACC_READ | ACC_USE)
}
expr_field(e, nm, _) => {
// If this is a reference to `self.f` inside of a ctor,
// then we treat it as a read of that variable.
// Otherwise, we ignore it and just propagate down to
// process `e`.
match self.as_self_field(e, nm) {
Some((ln, var)) => {
self.init_from_succ(ln, succ);
self.acc(ln, var, ACC_READ | ACC_USE);
ln
}
None => {
self.propagate_through_expr(e, succ)
}
}
expr_field(e, _, _) => {
self.propagate_through_expr(e, succ)
}
expr_fn(*) | expr_fn_block(*) => {
@ -1049,7 +990,7 @@ fn propagate_through_expr(expr: @expr, succ: LiveNode) -> LiveNode {
let caps = (*self.ir).captures(expr);
do (*caps).foldr(succ) |cap, succ| {
self.init_from_succ(cap.ln, succ);
let var = self.variable_from_rdef(cap.rv, expr.span);
let var = self.variable(cap.var_nid, expr.span);
self.acc(cap.ln, var, ACC_READ | ACC_USE);
cap.ln
}
@ -1269,8 +1210,8 @@ fn propagate_through_lvalue_components(expr: @expr,
// In general, the full flow graph structure for an
// assignment/move/etc can be handled in one of two ways,
// depending on whether what is being assigned is a "tracked
// value" or not. A tracked value is basically a local variable
// or argument, or a self-field (`self.f`) in a ctor.
// value" or not. A tracked value is basically a local
// variable or argument.
//
// The two kinds of graphs are:
//
@ -1293,12 +1234,11 @@ fn propagate_through_lvalue_components(expr: @expr,
//
// # Tracked lvalues
//
// A tracked lvalue is either a local variable/argument `x` or
// else it is a self-field `self.f` in a constructor. In
// A tracked lvalue is a local variable/argument `x`. In
// these cases, the link_node where the write occurs is linked
// to node id of `x` or `self`, respectively. The
// `write_lvalue()` routine generates the contents of this
// node. There are no subcomponents to consider.
// to node id of `x`. The `write_lvalue()` routine generates
// the contents of this node. There are no subcomponents to
// consider.
//
// # Non-tracked lvalues
//
@ -1315,12 +1255,9 @@ fn propagate_through_lvalue_components(expr: @expr,
// just ignore such cases and treat them as reads.
match expr.node {
expr_path(_) => succ,
expr_field(e, nm, _) => match self.as_self_field(e, nm) {
Some(_) => succ,
None => self.propagate_through_expr(e, succ)
},
_ => self.propagate_through_expr(expr, succ)
expr_path(_) => succ,
expr_field(e, _, _) => self.propagate_through_expr(e, succ),
_ => self.propagate_through_expr(expr, succ)
}
}
@ -1330,14 +1267,6 @@ fn write_lvalue(expr: @expr,
acc: uint) -> LiveNode {
match expr.node {
expr_path(_) => self.access_path(expr, succ, acc),
expr_field(e, nm, _) => match self.as_self_field(e, nm) {
Some((ln, var)) => {
self.init_from_succ(ln, succ);
self.acc(ln, var, acc);
ln
}
None => succ
},
// We do not track other lvalues, so just propagate through
// to their subcomponents. Also, it may happen that
@ -1350,27 +1279,7 @@ fn write_lvalue(expr: @expr,
fn access_path(expr: @expr, succ: LiveNode, acc: uint) -> LiveNode {
let def = self.tcx.def_map.get(expr.id);
match relevant_def(def) {
Some(RelevantSelf) => {
// Accessing `self` is like accessing every field of
// the current object. This allows something like
// `self = ...;` (it will be considered a write to
// every field, sensibly enough), though the borrowck
// pass will reject it later on.
//
// Also, note that, within a ctor at least, an
// expression like `self.f` is "shortcircuiting"
// before it reaches this point by the code for
// expr_field.
let ln = self.live_node(expr.id, expr.span);
if acc != 0u {
self.init_from_succ(ln, succ);
for self.ir.field_map.each_value |var| {
self.acc(ln, var, acc);
}
}
ln
}
Some(RelevantVar(nid)) => {
Some(nid) => {
let ln = self.live_node(expr.id, expr.span);
if acc != 0u {
self.init_from_succ(ln, succ);
@ -1383,29 +1292,6 @@ fn access_path(expr: @expr, succ: LiveNode, acc: uint) -> LiveNode {
}
}
fn as_self_field(expr: @expr,
fld: ident) -> Option<(LiveNode,Variable)> {
// If we checking a constructor, then we treat self.f as a
// variable. we use the live_node id that will be assigned to
// the reference to self but the variable id for `f`.
match expr.node {
expr_path(_) => {
let def = self.tcx.def_map.get(expr.id);
match def {
def_self(_) => {
// Note: the field_map is empty unless we are in a ctor
return self.ir.field_map.find(fld).map(|var| {
let ln = self.live_node(expr.id, expr.span);
(ln, *var)
});
}
_ => return None
}
}
_ => return None
}
}
fn propagate_through_loop(expr: @expr,
cond: Option<@expr>,
body: blk,
@ -1533,7 +1419,7 @@ fn check_expr(expr: @expr, &&self: @Liveness, vt: vt<@Liveness>) {
expr_fn(*) | expr_fn_block(*) => {
let caps = (*self.ir).captures(expr);
for (*caps).each |cap| {
let var = self.variable_from_rdef(cap.rv, expr.span);
let var = self.variable(cap.var_nid, expr.span);
self.consider_last_use(expr, cap.ln, var);
if cap.is_move {
self.check_move_from_var(expr.span, cap.ln, var);
@ -1613,24 +1499,7 @@ enum ReadKind {
}
impl @Liveness {
fn check_fields(sp: span, entry_ln: LiveNode) {
for self.ir.field_map.each |nm, var| {
match self.live_on_entry(entry_ln, var) {
None => { /* ok */ }
Some(ExitNode) => {
self.tcx.sess.span_err(
sp, fmt!("field `self.%s` is never initialized",
self.tcx.sess.str_of(nm)));
}
Some(lnk) => {
self.report_illegal_read(
sp, lnk, var, PossiblyUninitializedField);
}
}
}
}
fn check_ret(id: node_id, sp: span, fk: visit::fn_kind,
fn check_ret(id: node_id, sp: span, _fk: visit::fn_kind,
entry_ln: LiveNode) {
if self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() {
// if no_ret_var is live, then we fall off the end of the
@ -1644,15 +1513,8 @@ fn check_ret(id: node_id, sp: span, fk: visit::fn_kind,
self.tcx.sess.span_err(
sp, ~"some control paths may return");
} else {
match fk {
visit::fk_ctor(*) => {
// ctors are written as though they are unit.
}
_ => {
self.tcx.sess.span_err(
sp, ~"not all control paths return a value");
}
}
self.tcx.sess.span_err(
sp, ~"not all control paths return a value");
}
}
}
@ -1732,12 +1594,11 @@ fn check_lvalue(expr: @expr, vt: vt<@Liveness>) {
}
def => {
match relevant_def(def) {
Some(RelevantVar(nid)) => {
Some(nid) => {
let ln = self.live_node(expr.id, expr.span);
let var = self.variable(nid, expr.span);
self.warn_about_dead_assign(expr.span, ln, var);
}
Some(RelevantSelf) => {}
None => {}
}
}
@ -1796,13 +1657,6 @@ fn report_illegal_move(move_span: span,
copy or move mode", self.tcx.sess.str_of(name)));
return;
}
Field(name) => {
self.tcx.sess.span_err(
move_span,
fmt!("illegal move from field `%s`",
self.tcx.sess.str_of(name)));
return;
}
Self => {
self.tcx.sess.span_err(
move_span,

View File

@ -305,16 +305,16 @@ fn resolve_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk,
visitor: visit::vt<ctxt>) {
let fn_cx = match fk {
visit::fk_item_fn(*) | visit::fk_method(*) |
visit::fk_ctor(*) | visit::fk_dtor(*) => {
// Top-level functions are a root scope.
ctxt {parent: Some(id),.. cx}
}
visit::fk_item_fn(*) | visit::fk_method(*) |
visit::fk_dtor(*) => {
// Top-level functions are a root scope.
ctxt {parent: Some(id),.. cx}
}
visit::fk_anon(*) | visit::fk_fn_block(*) => {
// Closures continue with the inherited scope.
cx
}
visit::fk_anon(*) | visit::fk_fn_block(*) => {
// Closures continue with the inherited scope.
cx
}
};
debug!("visiting fn with body %d. cx.parent: %? \
@ -641,7 +641,7 @@ fn determine_rp_in_ty(ty: @ast::ty,
match ty.node {
ast::ty_path(path, id) => {
match cx.def_map.get(id) {
ast::def_ty(did) | ast::def_class(did, _) => {
ast::def_ty(did) | ast::def_class(did) => {
if did.crate == ast::local_crate {
if cx.opt_region_is_relevant(path.rp) {
cx.add_dep(did.node);

View File

@ -757,7 +757,7 @@ struct Resolver {
unused_import_lint_level: level,
trait_info: HashMap<def_id,@HashMap<ident,()>>,
structs: HashMap<def_id,bool>,
structs: HashMap<def_id,()>,
// The number of imports that are currently unresolved.
mut unresolved_imports: uint,
@ -1069,36 +1069,15 @@ fn build_reduced_graph_for_item(item: @item,
}
// These items live in both the type and value namespaces.
item_class(struct_definition, _) => {
let new_parent =
match struct_definition.ctor {
None => {
let (name_bindings, new_parent) =
self.add_child(ident, parent, ~[TypeNS], sp);
item_class(*) => {
let (name_bindings, new_parent) =
self.add_child(ident, parent, ~[TypeNS], sp);
(*name_bindings).define_type
(privacy, def_ty(local_def(item.id)), sp);
new_parent
}
Some(ctor) => {
let (name_bindings, new_parent) =
self.add_child(ident, parent, ~[ValueNS, TypeNS],
sp);
(*name_bindings).define_type
(privacy, def_ty(local_def(item.id)), sp);
let purity = impure_fn;
let ctor_def = def_fn(local_def(ctor.node.id),
purity);
(*name_bindings).define_value(privacy, ctor_def, sp);
new_parent
}
};
(*name_bindings).define_type
(privacy, def_ty(local_def(item.id)), sp);
// Record the def ID of this struct.
self.structs.insert(local_def(item.id),
struct_definition.ctor.is_some());
self.structs.insert(local_def(item.id), ());
visit_item(item, new_parent, visitor);
}
@ -1184,7 +1163,7 @@ fn build_reduced_graph_for_variant(variant: variant,
def_variant(item_id,
local_def(variant.node.id)),
variant.span);
self.structs.insert(local_def(variant.node.id), false);
self.structs.insert(local_def(variant.node.id), ());
}
enum_variant_kind(enum_definition) => {
(*child).define_type(privacy,
@ -1521,18 +1500,12 @@ trait method '%s'",
child_name_bindings.define_type(Public, def, dummy_sp());
}
def_class(def_id, has_constructor) => {
def_class(def_id) => {
debug!("(building reduced graph for external \
crate) building type %s (value? %d)",
final_ident,
if has_constructor { 1 } else { 0 });
crate) building type %s",
final_ident);
child_name_bindings.define_type(Public, def, dummy_sp());
if has_constructor {
child_name_bindings.define_value(Public, def, dummy_sp());
}
self.structs.insert(def_id, has_constructor);
self.structs.insert(def_id, ());
}
def_self(*) | def_arg(*) | def_local(*) |
def_prim_ty(*) | def_ty_param(*) | def_binding(*) |
@ -3307,7 +3280,6 @@ fn resolve_item(item: @item, visitor: ResolveVisitor) {
struct_def.traits,
struct_def.fields,
struct_def.methods,
struct_def.ctor,
struct_def.dtor,
visitor);
}
@ -3549,7 +3521,6 @@ fn resolve_class(id: node_id,
traits: ~[@trait_ref],
fields: ~[@struct_field],
methods: ~[@method],
optional_constructor: Option<class_ctor>,
optional_destructor: Option<class_dtor>,
visitor: ResolveVisitor) {
@ -3601,23 +3572,6 @@ fn resolve_class(id: node_id,
self.resolve_type(field.node.ty, visitor);
}
// Resolve the constructor, if applicable.
match optional_constructor {
None => {
// Nothing to do.
}
Some(constructor) => {
self.resolve_function(NormalRibKind,
Some(@constructor.node.dec),
NoTypeParameters,
constructor.node.body,
HasSelfBinding(constructor.node.
self_id),
NoCaptureClause,
visitor);
}
}
// Resolve the destructor, if applicable.
match optional_destructor {
None => {
@ -4090,9 +4044,7 @@ enum variant",
match self.resolve_path(path, TypeNS, false, visitor) {
Some(def_ty(class_id))
if self.structs.contains_key(class_id) => {
let has_constructor = self.structs.get(class_id);
let class_def = def_class(class_id,
has_constructor);
let class_def = def_class(class_id);
self.record_def(pattern.id, class_def);
}
Some(definition @ def_variant(_, variant_id))
@ -4560,10 +4512,9 @@ fn resolve_expr(expr: @expr, visitor: ResolveVisitor) {
// let bar = Bar { ... } // no type parameters
match self.resolve_path(path, TypeNS, false, visitor) {
Some(def_ty(class_id)) | Some(def_class(class_id, _))
Some(def_ty(class_id)) | Some(def_class(class_id))
if self.structs.contains_key(class_id) => {
let has_constructor = self.structs.get(class_id);
let class_def = def_class(class_id, has_constructor);
let class_def = def_class(class_id);
self.record_def(expr.id, class_def);
}
Some(definition @ def_variant(_, class_id))

View File

@ -1596,18 +1596,14 @@ fn trans_closure(ccx: @crate_ctxt, path: path, decl: ast::fn_decl,
// translation calls that don't have a return value (trans_crate,
// trans_mod, trans_item, et cetera) and those that do
// (trans_block, trans_expr, et cetera).
if !ccx.class_ctors.contains_key(id) // hack --
/* avoids the need for special cases to assign a type to
the constructor body (since it has no explicit return) */
&&
(body.node.expr.is_none() ||
ty::type_is_bot(block_ty) ||
ty::type_is_nil(block_ty)) {
if body.node.expr.is_none() || ty::type_is_bot(block_ty) ||
ty::type_is_nil(block_ty)
{
bcx = controlflow::trans_block(bcx, body, expr::Ignore);
} else {
bcx = controlflow::trans_block(bcx, body, expr::SaveIn(fcx.llretptr));
}
finish(bcx);
cleanup_and_Br(bcx, bcx_top, fcx.llreturn);
@ -1698,60 +1694,6 @@ fn trans_enum_variant(ccx: @crate_ctxt,
finish_fn(fcx, lltop);
}
fn trans_class_ctor(ccx: @crate_ctxt, path: path, decl: ast::fn_decl,
body: ast::blk, llctor_decl: ValueRef,
psubsts: param_substs, ctor_id: ast::node_id,
parent_id: ast::def_id, sp: span) {
// Add ctor to the ctor map
ccx.class_ctors.insert(ctor_id, parent_id);
// Translate the ctor
// Set up the type for the result of the ctor
// kludgy -- this wouldn't be necessary if the typechecker
// special-cased constructors, then we could just look up
// the ctor's return type.
let rslt_ty = ty::mk_class(ccx.tcx, parent_id,
dummy_substs(psubsts.tys));
// Make the fn context
let fcx = new_fn_ctxt_w_id(ccx, path, llctor_decl, ctor_id,
Some(psubsts), Some(sp));
let raw_llargs = create_llargs_for_fn_args(fcx, no_self, decl.inputs);
let mut bcx_top = top_scope_block(fcx, body.info());
let lltop = bcx_top.llbb;
let arg_tys = ty::ty_fn_args(node_id_type(bcx_top, ctor_id));
bcx_top = copy_args_to_allocas(fcx, bcx_top, decl.inputs,
raw_llargs, arg_tys);
// Create a temporary for `self` that we will return at the end
let selfdatum = datum::scratch_datum(bcx_top, rslt_ty, true);
// Initialize dtor flag (if any) to 1
if ty::ty_dtor(bcx_top.tcx(), parent_id).is_some() {
let flag = GEPi(bcx_top, selfdatum.val, [0, 1]);
Store(bcx_top, C_u8(1), flag);
}
// initialize fields to zero
let mut bcx = bcx_top;
// note we don't want to take *or* drop self.
fcx.llself = Some(ValSelfData {v: selfdatum.val,
t: rslt_ty,
is_owned: false});
// Translate the body of the ctor
bcx = controlflow::trans_block(bcx, body, expr::Ignore);
// Generate the return expression
bcx = selfdatum.move_to(bcx, datum::INIT, fcx.llretptr);
cleanup_and_leave(bcx, None, Some(fcx.llreturn));
Unreachable(bcx);
finish_fn(fcx, lltop);
}
fn trans_class_dtor(ccx: @crate_ctxt, path: path,
body: ast::blk, dtor_id: ast::node_id,
psubsts: Option<param_substs>,
@ -1921,14 +1863,6 @@ fn trans_struct_def(ccx: @crate_ctxt, struct_def: @ast::struct_def,
tps: ~[ast::ty_param], path: @ast_map::path,
ident: ast::ident, id: ast::node_id) {
if tps.len() == 0u {
let psubsts = {tys: ty::ty_params_to_tys(ccx.tcx, tps),
vtables: None,
bounds: @~[]};
do option::iter(&struct_def.ctor) |ctor| {
trans_class_ctor(ccx, *path, ctor.node.dec, ctor.node.body,
get_item_val(ccx, ctor.node.id), psubsts,
ctor.node.id, local_def(id), ctor.span);
}
do option::iter(&struct_def.dtor) |dtor| {
trans_class_dtor(ccx, *path, dtor.node.body,
dtor.node.id, None, None, local_def(id));
@ -2184,10 +2118,6 @@ fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
}
}
}
ast_map::node_ctor(nm, _, ctor, _, pt) => {
let my_path = vec::append(*pt, ~[path_name(nm)]);
register_fn(ccx, ctor.span, my_path, ctor.node.id)
}
ast_map::node_dtor(_, dt, parent_id, pt) => {
/*
Don't just call register_fn, since we don't want to add
@ -2712,7 +2642,6 @@ fn trans_crate(sess: session::session,
crate_map: crate_map,
mut uses_gc: false,
dbg_cx: dbg_cx,
class_ctors: HashMap(),
mut do_not_commit_warning_issued: false};

View File

@ -170,11 +170,6 @@ fn BuilderRef_res(B: BuilderRef) -> BuilderRef_res {
// is not emitted by LLVM's GC pass when no functions use GC.
mut uses_gc: bool,
dbg_cx: Option<debuginfo::debug_ctxt>,
// Mapping from class constructors to parent class --
// used in base::trans_closure
// parent_class must be a def_id because ctors can be
// inlined, so the parent may be in a different crate
class_ctors: HashMap<ast::node_id, ast::def_id>,
mut do_not_commit_warning_issued: bool};
// Types used for llself.

View File

@ -732,10 +732,6 @@ fn create_function(fcx: fn_ctxt) -> @metadata<subprogram_md> {
ast_map::node_method(method, _, _) => {
(method.ident, method.decl.output, method.id)
}
ast_map::node_ctor(nm, _, ctor, _, _) => {
// FIXME: output type may be wrong (#2194)
(nm, ctor.node.dec.output, ctor.node.id)
}
ast_map::node_expr(expr) => {
match expr.node {
ast::expr_fn(_, decl, _, _) => {

View File

@ -34,10 +34,6 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id)
trans_item(ccx, *item);
local_def(item.id)
}
csearch::found(ast::ii_ctor(ctor, _, _, _)) => {
ccx.external.insert(fn_id, Some(ctor.node.id));
local_def(ctor.node.id)
}
csearch::found(ast::ii_foreign(item)) => {
ccx.external.insert(fn_id, Some(item.id));
local_def(item.id)

View File

@ -5,7 +5,7 @@
use base::{trans_item, get_item_val, no_self, self_arg, trans_fn,
impl_self, decl_internal_cdecl_fn,
set_inline_hint_if_appr, set_inline_hint,
trans_enum_variant, trans_class_ctor, trans_class_dtor,
trans_enum_variant, trans_class_dtor,
get_insn_ctxt};
use syntax::parse::token::special_idents;
use type_of::type_of_fn_from_ty;
@ -71,7 +71,6 @@ fn monomorphic_fn(ccx: @crate_ctxt,
return {val: get_item_val(ccx, fn_id.node),
must_cast: true};
}
ast_map::node_ctor(nm, _, ct, _, pt) => (pt, nm, ct.span),
ast_map::node_dtor(_, dtor, _, pt) =>
(pt, special_idents::dtor, dtor.span),
ast_map::node_trait_method(*) => {
@ -162,16 +161,6 @@ fn monomorphic_fn(ccx: @crate_ctxt,
meth::trans_method(ccx, pt, mth, psubsts, None, d);
d
}
ast_map::node_ctor(_, tps, ctor, parent_id, _) => {
// ctors don't have attrs, at least not right now
let d = mk_lldecl();
let tp_tys = ty::ty_params_to_tys(ccx.tcx, tps);
trans_class_ctor(ccx, pt, ctor.node.dec, ctor.node.body, d,
option::get_default(&psubsts,
{tys:tp_tys, vtables: None, bounds: @~[]}),
fn_id.node, parent_id, ctor.span);
d
}
ast_map::node_dtor(_, dtor, _, pt) => {
let parent_id = match ty::ty_to_def_id(ty::node_id_to_type(ccx.tcx,
dtor.node.self_id)) {

View File

@ -59,10 +59,6 @@ fn traverse_def_id(cx: ctx, did: def_id) {
cx.rmap.insert(item.id, ());
}
ast_map::node_variant(v, _, _) => { cx.rmap.insert(v.node.id, ()); }
// If it's a ctor, consider the parent reachable
ast_map::node_ctor(_, _, _, parent_id, _) => {
traverse_def_id(cx, parent_id);
}
_ => ()
}
}
@ -104,13 +100,6 @@ fn traverse_public_item(cx: ctx, item: @item) {
}
}
item_class(struct_def, tps) => {
do option::iter(&struct_def.ctor) |ctor| {
cx.rmap.insert(ctor.node.id, ());
if tps.len() > 0u || attr::find_inline_attr(ctor.node.attrs)
!= attr::ia_none {
traverse_inline_body(cx, ctor.node.body);
}
}
do option::iter(&struct_def.dtor) |dtor| {
cx.rmap.insert(dtor.node.id, ());
if tps.len() > 0u || attr::find_inline_attr(dtor.node.attrs)

View File

@ -109,9 +109,6 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint)
for uint::range(0u, n_tps) |n| { cx.uses[n] |= flags;}
}
}
ast_map::node_ctor(_, _, ctor, _, _) => {
handle_body(cx, ctor.node.body);
}
ast_map::node_dtor(_, dtor, _, _) => {
handle_body(cx, dtor.node.body);
}

View File

@ -3318,7 +3318,7 @@ fn note_and_explain_type_err(cx: ctxt, err: &type_err) {
fn def_has_ty_params(def: ast::def) -> bool {
match def {
ast::def_fn(_, _) | ast::def_variant(_, _) | ast::def_class(_, _)
ast::def_fn(_, _) | ast::def_variant(_, _) | ast::def_class(_)
=> true,
_ => false
}
@ -3492,9 +3492,6 @@ fn item_path(cx: ctxt, id: ast::def_id) -> ast_map::path {
ast_map::path_name(variant.node.name))
}
ast_map::node_ctor(nm, _, _, _, path) => {
vec::append_one(*path, ast_map::path_name(nm))
}
ast_map::node_dtor(_, _, _, path) => {
vec::append_one(*path, ast_map::path_name(
syntax::parse::token::special_idents::literally_dtor))

View File

@ -323,7 +323,7 @@ fn check_path_args(tcx: ty::ctxt,
Some(d) => d
};
match a_def {
ast::def_ty(did) | ast::def_class(did, _) => {
ast::def_ty(did) | ast::def_class(did) => {
ast_path_to_ty(self, rscope, did, path, id).ty
}
ast::def_prim_ty(nty) => {

View File

@ -451,18 +451,6 @@ fn check_struct(ccx: @crate_ctxt, struct_def: @ast::struct_def,
let tcx = ccx.tcx;
let self_ty = ty::node_id_to_type(tcx, id);
do option::iter(&struct_def.ctor) |ctor| {
let class_t = {self_ty: self_ty,
self_id: ctor.node.self_id,
def_id: local_def(id),
explicit_self: {node: ast::sty_by_ref,
span: ast_util::dummy_sp()}};
// typecheck the ctor
check_bare_fn(ccx, ctor.node.dec,
ctor.node.body, ctor.node.id,
Some(class_t));
}
do option::iter(&struct_def.dtor) |dtor| {
let class_t = {self_ty: self_ty,
self_id: dtor.node.self_id,
@ -1925,7 +1913,7 @@ fn get_node(f: &spanned<field>) -> field { f.node }
// Resolve the path.
let class_id;
match tcx.def_map.find(id) {
Some(ast::def_class(type_def_id, _)) => {
Some(ast::def_class(type_def_id)) => {
class_id = type_def_id;
}
_ => {
@ -2411,7 +2399,7 @@ fn ty_param_bounds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) ->
ast::def_fn(id, _) | ast::def_static_method(id, _, _) |
ast::def_const(id) | ast::def_variant(_, id) |
ast::def_class(id, _) => {
ast::def_class(id) => {
return ty::lookup_item_type(fcx.ccx.tcx, id);
}
ast::def_upvar(_, inner, _, _) => {

View File

@ -325,7 +325,7 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
// Check to ensure that the struct is the one specified.
match tcx.def_map.get(pat.id) {
ast::def_class(supplied_def_id, _)
ast::def_class(supplied_def_id)
if supplied_def_id == class_id => {
// OK.
}

View File

@ -497,30 +497,6 @@ fn convert_struct(ccx: @crate_ctxt,
tpt: ty::ty_param_bounds_and_ty,
id: ast::node_id) {
let tcx = ccx.tcx;
do option::iter(&struct_def.ctor) |ctor| {
// Write the ctor type
let t_args = ctor.node.dec.inputs.map(
|a| ty_of_arg(ccx, type_rscope(rp), *a, None) );
let t_res = ty::mk_class(
tcx, local_def(id),
{self_r: rscope::bound_self_region(rp),
self_ty: None,
tps: ty::ty_params_to_tys(tcx, tps)});
let proto = ty::proto_vstore(ty::vstore_slice(ty::re_static));
let t_ctor = ty::mk_fn(tcx, FnTyBase {
meta: FnMeta {purity: ast::impure_fn,
proto: proto,
bounds: @~[],
ret_style: ast::return_val},
sig: FnSig {inputs: t_args,
output: t_res}
});
write_ty_to_tcx(tcx, ctor.node.id, t_ctor);
tcx.tcache.insert(local_def(ctor.node.id),
{bounds: tpt.bounds,
region_param: rp,
ty: t_ctor});
}
do option::iter(&struct_def.dtor) |dtor| {
// Write the dtor type

View File

@ -1,7 +1,5 @@
// error-pattern:Unsatisfied precondition constraint
fn main() {
let x = 5;
let _y = fn~(move x) { };
let _z = x; //< error: Unsatisfied precondition constraint
let _y = fn~(move x) { }; //~ WARNING captured variable `x` not used in closure
let _z = x; //~ ERROR use of moved variable: `x`
}

View File

@ -10,7 +10,7 @@ trait parse {
impl parser: parse {
fn parse() -> ~[int] {
dvec::unwrap(move self.tokens) //~ ERROR illegal move from self
dvec::unwrap(move self.tokens) //~ ERROR moving out of immutable field
}
}

View File

@ -19,7 +19,7 @@ impl Flag {
fn set_desc(self, s: &str) -> Flag {
Flag { //~ ERROR cannot infer an appropriate lifetime
name: self.name,
desc: s,
desc: s, //~ ERROR cannot infer an appropriate lifetime
max_count: self.max_count,
value: self.value
}