remove ctor from ast (take 2) (no review: just dead code removal)
This commit is contained in:
parent
cb55e246ba
commit
98887cc7ee
@ -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 */)
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
})
|
||||
}
|
||||
|
@ -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
|
||||
};
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
};
|
||||
|
@ -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",
|
||||
|
@ -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();
|
||||
|
@ -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) => {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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))
|
||||
|
@ -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};
|
||||
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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, _, _) => {
|
||||
|
@ -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)
|
||||
|
@ -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)) {
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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))
|
||||
|
@ -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) => {
|
||||
|
@ -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, _, _) => {
|
||||
|
@ -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.
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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`
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user