From 96254b4090a86767d1a3b387158464ece44160fa Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 11 Aug 2013 13:23:40 -0400 Subject: [PATCH 01/12] libsyntax: Update from `@Object` to `@mut Object` as required --- src/libsyntax/ast_map.rs | 50 +++++++-------- src/libsyntax/ast_util.rs | 50 +++++++-------- src/libsyntax/attr.rs | 2 +- src/libsyntax/diagnostic.rs | 18 +++--- src/libsyntax/ext/expand.rs | 40 ++++++------ src/libsyntax/ext/trace_macros.rs | 2 +- src/libsyntax/ext/tt/macro_parser.rs | 4 +- src/libsyntax/ext/tt/macro_rules.rs | 6 +- src/libsyntax/ext/tt/transcribe.rs | 4 +- src/libsyntax/parse/comments.rs | 4 +- src/libsyntax/parse/lexer.rs | 21 +++--- src/libsyntax/parse/mod.rs | 8 +-- src/libsyntax/parse/parser.rs | 4 +- src/libsyntax/print/pprust.rs | 2 +- src/libsyntax/visit.rs | 96 ++++++++++++++-------------- 15 files changed, 156 insertions(+), 155 deletions(-) diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs index 6b4da9671a963..1fea0c2e6f92d 100644 --- a/src/libsyntax/ast_map.rs +++ b/src/libsyntax/ast_map.rs @@ -85,7 +85,7 @@ pub type map = @mut HashMap; pub struct Ctx { map: map, path: path, - diag: @span_handler, + diag: @mut span_handler, } impl Ctx { @@ -141,7 +141,7 @@ impl Ctx { } } - visit::visit_expr(self as @Visitor<()>, ex, ()); + visit::visit_expr(self as @mut Visitor<()>, ex, ()); } fn map_fn(@mut self, @@ -153,18 +153,18 @@ impl Ctx { for a in decl.inputs.iter() { self.map.insert(a.id, node_arg); } - visit::visit_fn(self as @Visitor<()>, fk, decl, body, sp, id, ()); + visit::visit_fn(self as @mut Visitor<()>, fk, decl, body, sp, id, ()); } fn map_stmt(@mut self, stmt: @stmt) { self.map.insert(stmt_id(stmt), node_stmt(stmt)); - visit::visit_stmt(self as @Visitor<()>, stmt, ()); + visit::visit_stmt(self as @mut Visitor<()>, stmt, ()); } fn map_block(@mut self, b: &Block) { // clone is FIXME #2543 self.map.insert(b.id, node_block((*b).clone())); - visit::visit_block(self as @Visitor<()>, b, ()); + visit::visit_block(self as @mut Visitor<()>, b, ()); } fn map_pat(@mut self, pat: @pat) { @@ -177,7 +177,7 @@ impl Ctx { _ => () } - visit::visit_pat(self as @Visitor<()>, pat, ()); + visit::visit_pat(self as @mut Visitor<()>, pat, ()); } } @@ -254,13 +254,13 @@ impl Visitor<()> for Ctx { } _ => self.path.push(path_name(i.ident)) } - visit::visit_item(self as @Visitor<()>, i, ()); + visit::visit_item(self as @mut Visitor<()>, i, ()); self.path.pop(); } fn visit_pat(@mut self, pat: @pat, _: ()) { self.map_pat(pat); - visit::visit_pat(self as @Visitor<()>, pat, ()) + visit::visit_pat(self as @mut Visitor<()>, pat, ()) } fn visit_expr(@mut self, expr: @expr, _: ()) { @@ -288,27 +288,27 @@ impl Visitor<()> for Ctx { // XXX: Methods below can become default methods. fn visit_mod(@mut self, module: &_mod, _: span, _: NodeId, _: ()) { - visit::visit_mod(self as @Visitor<()>, module, ()) + visit::visit_mod(self as @mut Visitor<()>, module, ()) } fn visit_view_item(@mut self, view_item: &view_item, _: ()) { - visit::visit_view_item(self as @Visitor<()>, view_item, ()) + visit::visit_view_item(self as @mut Visitor<()>, view_item, ()) } fn visit_foreign_item(@mut self, foreign_item: @foreign_item, _: ()) { - visit::visit_foreign_item(self as @Visitor<()>, foreign_item, ()) + visit::visit_foreign_item(self as @mut Visitor<()>, foreign_item, ()) } fn visit_local(@mut self, local: @Local, _: ()) { - visit::visit_local(self as @Visitor<()>, local, ()) + visit::visit_local(self as @mut Visitor<()>, local, ()) } fn visit_arm(@mut self, arm: &arm, _: ()) { - visit::visit_arm(self as @Visitor<()>, arm, ()) + visit::visit_arm(self as @mut Visitor<()>, arm, ()) } fn visit_decl(@mut self, decl: @decl, _: ()) { - visit::visit_decl(self as @Visitor<()>, decl, ()) + visit::visit_decl(self as @mut Visitor<()>, decl, ()) } fn visit_expr_post(@mut self, _: @expr, _: ()) { @@ -316,11 +316,11 @@ impl Visitor<()> for Ctx { } fn visit_ty(@mut self, typ: &Ty, _: ()) { - visit::visit_ty(self as @Visitor<()>, typ, ()) + visit::visit_ty(self as @mut Visitor<()>, typ, ()) } fn visit_generics(@mut self, generics: &Generics, _: ()) { - visit::visit_generics(self as @Visitor<()>, generics, ()) + visit::visit_generics(self as @mut Visitor<()>, generics, ()) } fn visit_fn(@mut self, @@ -330,7 +330,7 @@ impl Visitor<()> for Ctx { span: span, node_id: NodeId, _: ()) { - visit::visit_fn(self as @Visitor<()>, + visit::visit_fn(self as @mut Visitor<()>, function_kind, function_declaration, block, @@ -340,11 +340,11 @@ impl Visitor<()> for Ctx { } fn visit_ty_method(@mut self, ty_method: &TypeMethod, _: ()) { - visit::visit_ty_method(self as @Visitor<()>, ty_method, ()) + visit::visit_ty_method(self as @mut Visitor<()>, ty_method, ()) } fn visit_trait_method(@mut self, trait_method: &trait_method, _: ()) { - visit::visit_trait_method(self as @Visitor<()>, trait_method, ()) + visit::visit_trait_method(self as @mut Visitor<()>, trait_method, ()) } fn visit_struct_def(@mut self, @@ -353,7 +353,7 @@ impl Visitor<()> for Ctx { generics: &Generics, node_id: NodeId, _: ()) { - visit::visit_struct_def(self as @Visitor<()>, + visit::visit_struct_def(self as @mut Visitor<()>, struct_def, ident, generics, @@ -362,24 +362,24 @@ impl Visitor<()> for Ctx { } fn visit_struct_field(@mut self, struct_field: @struct_field, _: ()) { - visit::visit_struct_field(self as @Visitor<()>, struct_field, ()) + visit::visit_struct_field(self as @mut Visitor<()>, struct_field, ()) } } -pub fn map_crate(diag: @span_handler, c: &Crate) -> map { +pub fn map_crate(diag: @mut span_handler, c: &Crate) -> map { let cx = @mut Ctx { map: @mut HashMap::new(), path: ~[], diag: diag, }; - visit::visit_crate(cx as @Visitor<()>, c, ()); + visit::visit_crate(cx as @mut Visitor<()>, c, ()); cx.map } // Used for items loaded from external crate that are being inlined into this // crate. The `path` should be the path to the item but should not include // the item itself. -pub fn map_decoded_item(diag: @span_handler, +pub fn map_decoded_item(diag: @mut span_handler, map: map, path: path, ii: &inlined_item) { @@ -409,7 +409,7 @@ pub fn map_decoded_item(diag: @span_handler, } // visit the item / method contents and add those to the map: - ii.accept((), cx as @Visitor<()>); + ii.accept((), cx as @mut Visitor<()>); } pub fn node_id_to_str(map: map, id: NodeId, itr: @ident_interner) -> ~str { diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 0005180ef50ff..d99f8cab4937f 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -298,7 +298,7 @@ pub fn struct_field_visibility(field: ast::struct_field) -> visibility { pub trait inlined_item_utils { fn ident(&self) -> ident; fn id(&self) -> ast::NodeId; - fn accept(&self, e: E, v: @Visitor); + fn accept(&self, e: E, v: @mut Visitor); } impl inlined_item_utils for inlined_item { @@ -318,7 +318,7 @@ impl inlined_item_utils for inlined_item { } } - fn accept(&self, e: E, v: @Visitor) { + fn accept(&self, e: E, v: @mut Visitor) { match *self { ii_item(i) => v.visit_item(i, e), ii_foreign(i) => v.visit_foreign_item(i, e), @@ -414,7 +414,7 @@ impl Visitor<()> for IdVisitor { node_id: NodeId, env: ()) { (self.visit_callback)(node_id); - visit::visit_mod(self as @Visitor<()>, module, env) + visit::visit_mod(self as @mut Visitor<()>, module, env) } fn visit_view_item(@mut self, view_item: &view_item, env: ()) { @@ -439,12 +439,12 @@ impl Visitor<()> for IdVisitor { } } } - visit::visit_view_item(self as @Visitor<()>, view_item, env) + visit::visit_view_item(self as @mut Visitor<()>, view_item, env) } fn visit_foreign_item(@mut self, foreign_item: @foreign_item, env: ()) { (self.visit_callback)(foreign_item.id); - visit::visit_foreign_item(self as @Visitor<()>, foreign_item, env) + visit::visit_foreign_item(self as @mut Visitor<()>, foreign_item, env) } fn visit_item(@mut self, item: @item, env: ()) { @@ -466,39 +466,39 @@ impl Visitor<()> for IdVisitor { _ => {} } - visit::visit_item(self as @Visitor<()>, item, env); + visit::visit_item(self as @mut Visitor<()>, item, env); self.visited_outermost = false } fn visit_local(@mut self, local: @Local, env: ()) { (self.visit_callback)(local.id); - visit::visit_local(self as @Visitor<()>, local, env) + visit::visit_local(self as @mut Visitor<()>, local, env) } fn visit_block(@mut self, block: &Block, env: ()) { (self.visit_callback)(block.id); - visit::visit_block(self as @Visitor<()>, block, env) + visit::visit_block(self as @mut Visitor<()>, block, env) } fn visit_stmt(@mut self, statement: @stmt, env: ()) { (self.visit_callback)(ast_util::stmt_id(statement)); - visit::visit_stmt(self as @Visitor<()>, statement, env) + visit::visit_stmt(self as @mut Visitor<()>, statement, env) } // XXX: Default fn visit_arm(@mut self, arm: &arm, env: ()) { - visit::visit_arm(self as @Visitor<()>, arm, env) + visit::visit_arm(self as @mut Visitor<()>, arm, env) } fn visit_pat(@mut self, pattern: @pat, env: ()) { (self.visit_callback)(pattern.id); - visit::visit_pat(self as @Visitor<()>, pattern, env) + visit::visit_pat(self as @mut Visitor<()>, pattern, env) } // XXX: Default fn visit_decl(@mut self, declaration: @decl, env: ()) { - visit::visit_decl(self as @Visitor<()>, declaration, env) + visit::visit_decl(self as @mut Visitor<()>, declaration, env) } fn visit_expr(@mut self, expression: @expr, env: ()) { @@ -509,7 +509,7 @@ impl Visitor<()> for IdVisitor { } } (self.visit_callback)(expression.id); - visit::visit_expr(self as @Visitor<()>, expression, env) + visit::visit_expr(self as @mut Visitor<()>, expression, env) } // XXX: Default @@ -523,12 +523,12 @@ impl Visitor<()> for IdVisitor { ty_path(_, _, id) => (self.visit_callback)(id), _ => {} } - visit::visit_ty(self as @Visitor<()>, typ, env) + visit::visit_ty(self as @mut Visitor<()>, typ, env) } fn visit_generics(@mut self, generics: &Generics, env: ()) { self.visit_generics_helper(generics); - visit::visit_generics(self as @Visitor<()>, generics, env) + visit::visit_generics(self as @mut Visitor<()>, generics, env) } fn visit_fn(@mut self, @@ -563,7 +563,7 @@ impl Visitor<()> for IdVisitor { (self.visit_callback)(argument.id) } - visit::visit_fn(self as @Visitor<()>, + visit::visit_fn(self as @mut Visitor<()>, function_kind, function_declaration, block, @@ -581,12 +581,12 @@ impl Visitor<()> for IdVisitor { // XXX: Default fn visit_ty_method(@mut self, type_method: &TypeMethod, env: ()) { - visit::visit_ty_method(self as @Visitor<()>, type_method, env) + visit::visit_ty_method(self as @mut Visitor<()>, type_method, env) } // XXX: Default fn visit_trait_method(@mut self, trait_method: &trait_method, env: ()) { - visit::visit_trait_method(self as @Visitor<()>, trait_method, env) + visit::visit_trait_method(self as @mut Visitor<()>, trait_method, env) } // XXX: Default @@ -596,7 +596,7 @@ impl Visitor<()> for IdVisitor { generics: &Generics, node_id: NodeId, env: ()) { - visit::visit_struct_def(self as @Visitor<()>, + visit::visit_struct_def(self as @mut Visitor<()>, struct_definition, identifier, generics, @@ -606,18 +606,18 @@ impl Visitor<()> for IdVisitor { fn visit_struct_field(@mut self, struct_field: @struct_field, env: ()) { (self.visit_callback)(struct_field.node.id); - visit::visit_struct_field(self as @Visitor<()>, struct_field, env) + visit::visit_struct_field(self as @mut Visitor<()>, struct_field, env) } } pub fn id_visitor(vfn: @fn(NodeId), pass_through_items: bool) - -> @Visitor<()> { - let visitor = @IdVisitor { + -> @mut Visitor<()> { + let visitor = @mut IdVisitor { visit_callback: vfn, pass_through_items: pass_through_items, visited_outermost: false, }; - visitor as @Visitor<()> + visitor as @mut Visitor<()> } pub fn visit_ids_for_inlined_item(item: &inlined_item, vfn: @fn(NodeId)) { @@ -757,9 +757,9 @@ impl EachViewItem for ast::Crate { callback: f, }; let visitor = @mut SimpleVisitorVisitor { - simple_visitor: data as @SimpleVisitor, + simple_visitor: data as @mut SimpleVisitor, }; - visit::visit_crate(visitor as @Visitor<()>, self, ()); + visit::visit_crate(visitor as @mut Visitor<()>, self, ()); true } } diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index b0dda2b7dc89f..47d8ebecca06a 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -313,7 +313,7 @@ pub fn test_cfg> no_cfgs || some_cfg_matches } -pub fn require_unique_names(diagnostic: @span_handler, +pub fn require_unique_names(diagnostic: @mut span_handler, metas: &[@MetaItem]) { let mut set = HashSet::new(); for meta in metas.iter() { diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 2b6cb91a5df17..5cdfe8e0f110b 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -50,7 +50,7 @@ pub trait span_handler { fn span_note(@mut self, sp: span, msg: &str); fn span_bug(@mut self, sp: span, msg: &str) -> !; fn span_unimpl(@mut self, sp: span, msg: &str) -> !; - fn handler(@mut self) -> @handler; + fn handler(@mut self) -> @mut handler; } struct HandlerT { @@ -59,7 +59,7 @@ struct HandlerT { } struct CodemapT { - handler: @handler, + handler: @mut handler, cm: @codemap::CodeMap, } @@ -84,7 +84,7 @@ impl span_handler for CodemapT { fn span_unimpl(@mut self, sp: span, msg: &str) -> ! { self.span_bug(sp, ~"unimplemented " + msg); } - fn handler(@mut self) -> @handler { + fn handler(@mut self) -> @mut handler { self.handler } } @@ -143,12 +143,12 @@ pub fn ice_msg(msg: &str) -> ~str { fmt!("internal compiler error: %s", msg) } -pub fn mk_span_handler(handler: @handler, cm: @codemap::CodeMap) - -> @span_handler { - @mut CodemapT { handler: handler, cm: cm } as @span_handler +pub fn mk_span_handler(handler: @mut handler, cm: @codemap::CodeMap) + -> @mut span_handler { + @mut CodemapT { handler: handler, cm: cm } as @mut span_handler } -pub fn mk_handler(emitter: Option) -> @handler { +pub fn mk_handler(emitter: Option) -> @mut handler { let emit: Emitter = match emitter { Some(e) => e, None => { @@ -157,7 +157,7 @@ pub fn mk_handler(emitter: Option) -> @handler { } }; - @mut HandlerT { err_count: 0, emit: emit } as @handler + @mut HandlerT { err_count: 0, emit: emit } as @mut handler } #[deriving(Eq)] @@ -341,7 +341,7 @@ fn print_macro_backtrace(cm: @codemap::CodeMap, sp: span) { } } -pub fn expect(diag: @span_handler, +pub fn expect(diag: @mut span_handler, opt: Option, msg: &fn() -> ~str) -> T { match opt { diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 1963f3aef49c1..1547446957ed4 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -548,52 +548,52 @@ impl Visitor<()> for NewNameFinderContext { } } // use the default traversal for non-pat_idents - _ => visit::visit_pat(self as @Visitor<()>, pattern, ()) + _ => visit::visit_pat(self as @mut Visitor<()>, pattern, ()) } } // XXX: Methods below can become default methods. fn visit_mod(@mut self, module: &ast::_mod, _: span, _: NodeId, _: ()) { - visit::visit_mod(self as @Visitor<()>, module, ()) + visit::visit_mod(self as @mut Visitor<()>, module, ()) } fn visit_view_item(@mut self, view_item: &ast::view_item, _: ()) { - visit::visit_view_item(self as @Visitor<()>, view_item, ()) + visit::visit_view_item(self as @mut Visitor<()>, view_item, ()) } fn visit_item(@mut self, item: @ast::item, _: ()) { - visit::visit_item(self as @Visitor<()>, item, ()) + visit::visit_item(self as @mut Visitor<()>, item, ()) } fn visit_foreign_item(@mut self, foreign_item: @ast::foreign_item, _: ()) { - visit::visit_foreign_item(self as @Visitor<()>, foreign_item, ()) + visit::visit_foreign_item(self as @mut Visitor<()>, foreign_item, ()) } fn visit_local(@mut self, local: @ast::Local, _: ()) { - visit::visit_local(self as @Visitor<()>, local, ()) + visit::visit_local(self as @mut Visitor<()>, local, ()) } fn visit_block(@mut self, block: &ast::Block, _: ()) { - visit::visit_block(self as @Visitor<()>, block, ()) + visit::visit_block(self as @mut Visitor<()>, block, ()) } fn visit_stmt(@mut self, stmt: @ast::stmt, _: ()) { - visit::visit_stmt(self as @Visitor<()>, stmt, ()) + visit::visit_stmt(self as @mut Visitor<()>, stmt, ()) } fn visit_arm(@mut self, arm: &ast::arm, _: ()) { - visit::visit_arm(self as @Visitor<()>, arm, ()) + visit::visit_arm(self as @mut Visitor<()>, arm, ()) } fn visit_decl(@mut self, decl: @ast::decl, _: ()) { - visit::visit_decl(self as @Visitor<()>, decl, ()) + visit::visit_decl(self as @mut Visitor<()>, decl, ()) } fn visit_expr(@mut self, expr: @ast::expr, _: ()) { - visit::visit_expr(self as @Visitor<()>, expr, ()) + visit::visit_expr(self as @mut Visitor<()>, expr, ()) } fn visit_expr_post(@mut self, _: @ast::expr, _: ()) { @@ -601,11 +601,11 @@ impl Visitor<()> for NewNameFinderContext { } fn visit_ty(@mut self, typ: &ast::Ty, _: ()) { - visit::visit_ty(self as @Visitor<()>, typ, ()) + visit::visit_ty(self as @mut Visitor<()>, typ, ()) } fn visit_generics(@mut self, generics: &ast::Generics, _: ()) { - visit::visit_generics(self as @Visitor<()>, generics, ()) + visit::visit_generics(self as @mut Visitor<()>, generics, ()) } fn visit_fn(@mut self, @@ -615,7 +615,7 @@ impl Visitor<()> for NewNameFinderContext { span: span, node_id: NodeId, _: ()) { - visit::visit_fn(self as @Visitor<()>, + visit::visit_fn(self as @mut Visitor<()>, function_kind, function_declaration, block, @@ -625,13 +625,13 @@ impl Visitor<()> for NewNameFinderContext { } fn visit_ty_method(@mut self, ty_method: &ast::TypeMethod, _: ()) { - visit::visit_ty_method(self as @Visitor<()>, ty_method, ()) + visit::visit_ty_method(self as @mut Visitor<()>, ty_method, ()) } fn visit_trait_method(@mut self, trait_method: &ast::trait_method, _: ()) { - visit::visit_trait_method(self as @Visitor<()>, trait_method, ()) + visit::visit_trait_method(self as @mut Visitor<()>, trait_method, ()) } fn visit_struct_def(@mut self, @@ -640,7 +640,7 @@ impl Visitor<()> for NewNameFinderContext { generics: &ast::Generics, node_id: NodeId, _: ()) { - visit::visit_struct_def(self as @Visitor<()>, + visit::visit_struct_def(self as @mut Visitor<()>, struct_def, ident, generics, @@ -651,18 +651,18 @@ impl Visitor<()> for NewNameFinderContext { fn visit_struct_field(@mut self, struct_field: @ast::struct_field, _: ()) { - visit::visit_struct_field(self as @Visitor<()>, struct_field, ()) + visit::visit_struct_field(self as @mut Visitor<()>, struct_field, ()) } } // return a visitor that extracts the pat_ident paths // from a given pattern and puts them in a mutable // array (passed in to the traversal) -pub fn new_name_finder(idents: @mut ~[ast::ident]) -> @Visitor<()> { +pub fn new_name_finder(idents: @mut ~[ast::ident]) -> @mut Visitor<()> { let context = @mut NewNameFinderContext { ident_accumulator: idents, }; - context as @Visitor<()> + context as @mut Visitor<()> } pub fn expand_block(extsbox: @mut SyntaxEnv, diff --git a/src/libsyntax/ext/trace_macros.rs b/src/libsyntax/ext/trace_macros.rs index f7f17d3ba64ac..f3e7613d96a34 100644 --- a/src/libsyntax/ext/trace_macros.rs +++ b/src/libsyntax/ext/trace_macros.rs @@ -25,7 +25,7 @@ pub fn expand_trace_macros(cx: @ExtCtxt, let tt_rdr = new_tt_reader(cx.parse_sess().span_diagnostic, None, tt.to_owned()); - let rdr = tt_rdr as @reader; + let rdr = tt_rdr as @mut reader; let rust_parser = Parser(sess, cfg.clone(), rdr.dup()); if rust_parser.is_keyword(keywords::True) { diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 918949113ad0c..c4a19a0daca16 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -224,7 +224,7 @@ pub enum parse_result { pub fn parse_or_else( sess: @mut ParseSess, cfg: ast::CrateConfig, - rdr: @reader, + rdr: @mut reader, ms: ~[matcher] ) -> HashMap { match parse(sess, cfg, rdr, ms) { @@ -237,7 +237,7 @@ pub fn parse_or_else( pub fn parse( sess: @mut ParseSess, cfg: ast::CrateConfig, - rdr: @reader, + rdr: @mut reader, ms: &[matcher] ) -> parse_result { let mut cur_eis = ~[]; diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 10735dad32f00..54ac1f1e48f44 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -59,7 +59,7 @@ pub fn add_new_extension(cx: @ExtCtxt, arg.clone()); let argument_map = parse_or_else(cx.parse_sess(), cx.cfg(), - arg_reader as @reader, + arg_reader as @mut reader, argument_gram); // Extract the arguments: @@ -101,7 +101,7 @@ pub fn add_new_extension(cx: @ExtCtxt, s_d, None, arg.to_owned() - ) as @reader; + ) as @mut reader; match parse(cx.parse_sess(), cx.cfg(), arg_rdr, *mtcs) { success(named_matches) => { let rhs = match rhses[i] { @@ -123,7 +123,7 @@ pub fn add_new_extension(cx: @ExtCtxt, rhs); let p = @Parser(cx.parse_sess(), cx.cfg(), - trncbr as @reader); + trncbr as @mut reader); // Let the context choose how to interpret the result. // Weird, but useful for X-macros. diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 16019b2144833..ba0c0e33e832c 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -30,7 +30,7 @@ struct TtFrame { } pub struct TtReader { - sp_diag: @span_handler, + sp_diag: @mut span_handler, // the unzipped tree: stack: @mut TtFrame, /* for MBE-style macro transcription */ @@ -45,7 +45,7 @@ pub struct TtReader { /** This can do Macro-By-Example transcription. On the other hand, if * `src` contains no `tt_seq`s and `tt_nonterminal`s, `interp` can (and * should) be none. */ -pub fn new_tt_reader(sp_diag: @span_handler, +pub fn new_tt_reader(sp_diag: @mut span_handler, interp: Option>, src: ~[ast::token_tree]) -> @mut TtReader { diff --git a/src/libsyntax/parse/comments.rs b/src/libsyntax/parse/comments.rs index 5b9725ec6a042..9a9164f510210 100644 --- a/src/libsyntax/parse/comments.rs +++ b/src/libsyntax/parse/comments.rs @@ -267,7 +267,7 @@ fn read_block_comment(rdr: @mut StringReader, while level > 0 { debug!("=== block comment level %d", level); if is_eof(rdr) { - (rdr as @reader).fatal(~"unterminated block comment"); + (rdr as @mut reader).fatal(~"unterminated block comment"); } if rdr.curr == '\n' { trim_whitespace_prefix_and_push_line(&mut lines, curr_line, @@ -334,7 +334,7 @@ pub struct lit { // it appears this function is called only from pprust... that's // probably not a good thing. pub fn gather_comments_and_literals(span_diagnostic: - @diagnostic::span_handler, + @mut diagnostic::span_handler, path: @str, srdr: @io::Reader) -> (~[cmnt], ~[lit]) { diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs index bde568b2610c2..d0041021f7cc7 100644 --- a/src/libsyntax/parse/lexer.rs +++ b/src/libsyntax/parse/lexer.rs @@ -28,9 +28,9 @@ pub trait reader { fn is_eof(@mut self) -> bool; fn next_token(@mut self) -> TokenAndSpan; fn fatal(@mut self, ~str) -> !; - fn span_diag(@mut self) -> @span_handler; + fn span_diag(@mut self) -> @mut span_handler; fn peek(@mut self) -> TokenAndSpan; - fn dup(@mut self) -> @reader; + fn dup(@mut self) -> @mut reader; } #[deriving(Clone, Eq)] @@ -40,7 +40,7 @@ pub struct TokenAndSpan { } pub struct StringReader { - span_diagnostic: @span_handler, + span_diagnostic: @mut span_handler, src: @str, // The absolute offset within the codemap of the next character to read pos: BytePos, @@ -56,7 +56,7 @@ pub struct StringReader { peek_span: span } -pub fn new_string_reader(span_diagnostic: @span_handler, +pub fn new_string_reader(span_diagnostic: @mut span_handler, filemap: @codemap::FileMap) -> @mut StringReader { let r = new_low_level_string_reader(span_diagnostic, filemap); @@ -65,13 +65,14 @@ pub fn new_string_reader(span_diagnostic: @span_handler, } /* For comments.rs, which hackily pokes into 'pos' and 'curr' */ -pub fn new_low_level_string_reader(span_diagnostic: @span_handler, +pub fn new_low_level_string_reader(span_diagnostic: @mut span_handler, filemap: @codemap::FileMap) -> @mut StringReader { // Force the initial reader bump to start on a fresh line let initial_char = '\n'; let r = @mut StringReader { - span_diagnostic: span_diagnostic, src: filemap.src, + span_diagnostic: span_diagnostic, + src: filemap.src, pos: filemap.start_pos, last_pos: filemap.start_pos, col: CharPos(0), @@ -116,7 +117,7 @@ impl reader for StringReader { fn fatal(@mut self, m: ~str) -> ! { self.span_diagnostic.span_fatal(self.peek_span, m) } - fn span_diag(@mut self) -> @span_handler { self.span_diagnostic } + fn span_diag(@mut self) -> @mut span_handler { self.span_diagnostic } fn peek(@mut self) -> TokenAndSpan { // XXX(pcwalton): Bad copy! TokenAndSpan { @@ -124,7 +125,7 @@ impl reader for StringReader { sp: self.peek_span, } } - fn dup(@mut self) -> @reader { dup_string_reader(self) as @reader } + fn dup(@mut self) -> @mut reader { dup_string_reader(self) as @mut reader } } impl reader for TtReader { @@ -137,14 +138,14 @@ impl reader for TtReader { fn fatal(@mut self, m: ~str) -> ! { self.sp_diag.span_fatal(self.cur_span, m); } - fn span_diag(@mut self) -> @span_handler { self.sp_diag } + fn span_diag(@mut self) -> @mut span_handler { self.sp_diag } fn peek(@mut self) -> TokenAndSpan { TokenAndSpan { tok: self.cur_tok.clone(), sp: self.cur_span, } } - fn dup(@mut self) -> @reader { dup_tt_reader(self) as @reader } + fn dup(@mut self) -> @mut reader { dup_tt_reader(self) as @mut reader } } // EFFECT: advance peek_tok and peek_span to refer to the next token. diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 1731a587a8efa..23c6a8b97208b 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -43,7 +43,7 @@ pub mod obsolete; pub struct ParseSess { cm: @codemap::CodeMap, // better be the same as the one in the reader! next_id: NodeId, - span_diagnostic: @span_handler, // better be the same as the one in the reader! + span_diagnostic: @mut span_handler, // better be the same as the one in the reader! /// Used to determine and report recursive mod inclusions included_mod_stack: ~[Path], } @@ -58,7 +58,7 @@ pub fn new_parse_sess(demitter: Option) -> @mut ParseSess { } } -pub fn new_parse_sess_special_handler(sh: @span_handler, +pub fn new_parse_sess_special_handler(sh: @mut span_handler, cm: @codemap::CodeMap) -> @mut ParseSess { @mut ParseSess { @@ -306,7 +306,7 @@ pub fn filemap_to_tts(sess: @mut ParseSess, filemap: @FileMap) // parsing tt's probably shouldn't require a parser at all. let cfg = ~[]; let srdr = lexer::new_string_reader(sess.span_diagnostic, filemap); - let p1 = Parser(sess, cfg, srdr as @reader); + let p1 = Parser(sess, cfg, srdr as @mut reader); p1.parse_all_token_trees() } @@ -315,7 +315,7 @@ pub fn tts_to_parser(sess: @mut ParseSess, tts: ~[ast::token_tree], cfg: ast::CrateConfig) -> Parser { let trdr = lexer::new_tt_reader(sess.span_diagnostic, None, tts); - Parser(sess, cfg, trdr as @reader) + Parser(sess, cfg, trdr as @mut reader) } // abort if necessary diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 77c50a779c03f..557249f1f664f 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -265,7 +265,7 @@ struct ParsedItemsAndViewItems { pub fn Parser(sess: @mut ParseSess, cfg: ast::CrateConfig, - rdr: @reader) + rdr: @mut reader) -> Parser { let tok0 = rdr.next_token(); let interner = get_ident_interner(); @@ -315,7 +315,7 @@ pub struct Parser { tokens_consumed: @mut uint, restriction: @mut restriction, quote_depth: @mut uint, // not (yet) related to the quasiquoter - reader: @reader, + reader: @mut reader, interner: @token::ident_interner, /// The set of seen errors about obsolete syntax. Used to suppress /// extra detail when the same error is seen twice diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index ffe9575a8644e..6a3d829aca0b0 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -104,7 +104,7 @@ pub static default_columns: uint = 78u; // copy forward. pub fn print_crate(cm: @CodeMap, intr: @ident_interner, - span_diagnostic: @diagnostic::span_handler, + span_diagnostic: @mut diagnostic::span_handler, crate: &ast::Crate, filename: @str, input: @io::Reader, diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 7aa52bc13e341..c3a5ba7116d91 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -88,11 +88,11 @@ pub trait Visitor { fn visit_struct_field(@mut self, @struct_field, E); } -pub fn visit_crate(visitor: @Visitor, crate: &Crate, env: E) { +pub fn visit_crate(visitor: @mut Visitor, crate: &Crate, env: E) { visitor.visit_mod(&crate.module, crate.span, CRATE_NODE_ID, env) } -pub fn visit_mod(visitor: @Visitor, module: &_mod, env: E) { +pub fn visit_mod(visitor: @mut Visitor, module: &_mod, env: E) { for view_item in module.view_items.iter() { visitor.visit_view_item(view_item, env.clone()) } @@ -101,11 +101,11 @@ pub fn visit_mod(visitor: @Visitor, module: &_mod, env: E) { } } -pub fn visit_view_item(_: @Visitor, _: &view_item, _: E) { +pub fn visit_view_item(_: @mut Visitor, _: &view_item, _: E) { // Empty! } -pub fn visit_local(visitor: @Visitor, local: &Local, env: E) { +pub fn visit_local(visitor: @mut Visitor, local: &Local, env: E) { visitor.visit_pat(local.pat, env.clone()); visitor.visit_ty(&local.ty, env.clone()); match local.init { @@ -114,13 +114,13 @@ pub fn visit_local(visitor: @Visitor, local: &Local, env: E) { } } -fn visit_trait_ref(visitor: @Visitor, +fn visit_trait_ref(visitor: @mut Visitor, trait_ref: &ast::trait_ref, env: E) { visit_path(visitor, &trait_ref.path, env) } -pub fn visit_item(visitor: @Visitor, item: &item, env: E) { +pub fn visit_item(visitor: @mut Visitor, item: &item, env: E) { match item.node { item_static(ref typ, _, expr) => { visitor.visit_ty(typ, env.clone()); @@ -187,7 +187,7 @@ pub fn visit_item(visitor: @Visitor, item: &item, env: E) { } } -pub fn visit_enum_def(visitor: @Visitor, +pub fn visit_enum_def(visitor: @mut Visitor, enum_definition: &ast::enum_def, generics: &Generics, env: E) { @@ -209,11 +209,11 @@ pub fn visit_enum_def(visitor: @Visitor, } } -pub fn skip_ty(_: @Visitor, _: &Ty, _: E) { +pub fn skip_ty(_: @mut Visitor, _: &Ty, _: E) { // Empty! } -pub fn visit_ty(visitor: @Visitor, typ: &Ty, env: E) { +pub fn visit_ty(visitor: @mut Visitor, typ: &Ty, env: E) { match typ.node { ty_box(ref mutable_type) | ty_uniq(ref mutable_type) | ty_vec(ref mutable_type) | ty_ptr(ref mutable_type) | @@ -254,13 +254,13 @@ pub fn visit_ty(visitor: @Visitor, typ: &Ty, env: E) { } } -pub fn visit_path(visitor: @Visitor, path: &Path, env: E) { +pub fn visit_path(visitor: @mut Visitor, path: &Path, env: E) { for typ in path.types.iter() { visitor.visit_ty(typ, env.clone()) } } -pub fn visit_pat(visitor: @Visitor, pattern: &pat, env: E) { +pub fn visit_pat(visitor: @mut Visitor, pattern: &pat, env: E) { match pattern.node { pat_enum(ref path, ref children) => { visit_path(visitor, path, env.clone()); @@ -313,7 +313,7 @@ pub fn visit_pat(visitor: @Visitor, pattern: &pat, env: E) { } } -pub fn visit_foreign_item(visitor: @Visitor, +pub fn visit_foreign_item(visitor: @mut Visitor, foreign_item: &foreign_item, env: E) { match foreign_item.node { @@ -325,7 +325,7 @@ pub fn visit_foreign_item(visitor: @Visitor, } } -pub fn visit_ty_param_bounds(visitor: @Visitor, +pub fn visit_ty_param_bounds(visitor: @mut Visitor, bounds: &OptVec, env: E) { for bound in bounds.iter() { @@ -338,7 +338,7 @@ pub fn visit_ty_param_bounds(visitor: @Visitor, } } -pub fn visit_generics(visitor: @Visitor, +pub fn visit_generics(visitor: @mut Visitor, generics: &Generics, env: E) { for type_parameter in generics.ty_params.iter() { @@ -346,7 +346,7 @@ pub fn visit_generics(visitor: @Visitor, } } -pub fn visit_fn_decl(visitor: @Visitor, +pub fn visit_fn_decl(visitor: @mut Visitor, function_declaration: &fn_decl, env: E) { for argument in function_declaration.inputs.iter() { @@ -360,7 +360,7 @@ pub fn visit_fn_decl(visitor: @Visitor, // visit_fn() and check for fk_method(). I named this visit_method_helper() // because it is not a default impl of any method, though I doubt that really // clarifies anything. - Niko -pub fn visit_method_helper(visitor: @Visitor, +pub fn visit_method_helper(visitor: @mut Visitor, method: &method, env: E) { visitor.visit_fn(&fk_method(method.ident, &method.generics, method), @@ -371,7 +371,7 @@ pub fn visit_method_helper(visitor: @Visitor, env) } -pub fn visit_fn(visitor: @Visitor, +pub fn visit_fn(visitor: @mut Visitor, function_kind: &fn_kind, function_declaration: &fn_decl, function_body: &Block, @@ -384,7 +384,7 @@ pub fn visit_fn(visitor: @Visitor, visitor.visit_block(function_body, env) } -pub fn visit_ty_method(visitor: @Visitor, +pub fn visit_ty_method(visitor: @mut Visitor, method_type: &TypeMethod, env: E) { for argument_type in method_type.decl.inputs.iter() { @@ -394,7 +394,7 @@ pub fn visit_ty_method(visitor: @Visitor, visitor.visit_ty(&method_type.decl.output, env.clone()) } -pub fn visit_trait_method(visitor: @Visitor, +pub fn visit_trait_method(visitor: @mut Visitor, trait_method: &trait_method, env: E) { match *trait_method { @@ -405,7 +405,7 @@ pub fn visit_trait_method(visitor: @Visitor, } } -pub fn visit_struct_def(visitor: @Visitor, +pub fn visit_struct_def(visitor: @mut Visitor, struct_definition: @struct_def, _: ast::ident, _: &Generics, @@ -416,13 +416,13 @@ pub fn visit_struct_def(visitor: @Visitor, } } -pub fn visit_struct_field(visitor: @Visitor, +pub fn visit_struct_field(visitor: @mut Visitor, struct_field: &struct_field, env: E) { visitor.visit_ty(&struct_field.node.ty, env) } -pub fn visit_block(visitor: @Visitor, block: &Block, env: E) { +pub fn visit_block(visitor: @mut Visitor, block: &Block, env: E) { for view_item in block.view_items.iter() { visitor.visit_view_item(view_item, env.clone()) } @@ -432,7 +432,7 @@ pub fn visit_block(visitor: @Visitor, block: &Block, env: E) { visit_expr_opt(visitor, block.expr, env) } -pub fn visit_stmt(visitor: @Visitor, statement: &stmt, env: E) { +pub fn visit_stmt(visitor: @mut Visitor, statement: &stmt, env: E) { match statement.node { stmt_decl(declaration, _) => visitor.visit_decl(declaration, env), stmt_expr(expression, _) | stmt_semi(expression, _) => { @@ -442,14 +442,14 @@ pub fn visit_stmt(visitor: @Visitor, statement: &stmt, env: E) { } } -pub fn visit_decl(visitor: @Visitor, declaration: &decl, env: E) { +pub fn visit_decl(visitor: @mut Visitor, declaration: &decl, env: E) { match declaration.node { decl_local(ref local) => visitor.visit_local(*local, env), decl_item(item) => visitor.visit_item(item, env), } } -pub fn visit_expr_opt(visitor: @Visitor, +pub fn visit_expr_opt(visitor: @mut Visitor, optional_expression: Option<@expr>, env: E) { match optional_expression { @@ -458,7 +458,7 @@ pub fn visit_expr_opt(visitor: @Visitor, } } -pub fn visit_exprs(visitor: @Visitor, +pub fn visit_exprs(visitor: @mut Visitor, expressions: &[@expr], env: E) { for expression in expressions.iter() { @@ -466,11 +466,11 @@ pub fn visit_exprs(visitor: @Visitor, } } -pub fn visit_mac(_: @Visitor, _: &mac, _: E) { +pub fn visit_mac(_: @mut Visitor, _: &mac, _: E) { // Empty! } -pub fn visit_expr(visitor: @Visitor, expression: @expr, env: E) { +pub fn visit_expr(visitor: @mut Visitor, expression: @expr, env: E) { match expression.node { expr_vstore(subexpression, _) => { visitor.visit_expr(subexpression, env.clone()) @@ -595,7 +595,7 @@ pub fn visit_expr(visitor: @Visitor, expression: @expr, env: E) { visitor.visit_expr_post(expression, env.clone()) } -pub fn visit_arm(visitor: @Visitor, arm: &arm, env: E) { +pub fn visit_arm(visitor: @mut Visitor, arm: &arm, env: E) { for pattern in arm.pats.iter() { visitor.visit_pat(*pattern, env.clone()) } @@ -630,7 +630,7 @@ pub trait SimpleVisitor { } pub struct SimpleVisitorVisitor { - simple_visitor: @SimpleVisitor, + simple_visitor: @mut SimpleVisitor, } impl Visitor<()> for SimpleVisitorVisitor { @@ -640,58 +640,58 @@ impl Visitor<()> for SimpleVisitorVisitor { node_id: NodeId, env: ()) { self.simple_visitor.visit_mod(module, span, node_id); - visit_mod(self as @Visitor<()>, module, env) + visit_mod(self as @mut Visitor<()>, module, env) } fn visit_view_item(@mut self, view_item: &view_item, env: ()) { self.simple_visitor.visit_view_item(view_item); - visit_view_item(self as @Visitor<()>, view_item, env) + visit_view_item(self as @mut Visitor<()>, view_item, env) } fn visit_foreign_item(@mut self, foreign_item: @foreign_item, env: ()) { self.simple_visitor.visit_foreign_item(foreign_item); - visit_foreign_item(self as @Visitor<()>, foreign_item, env) + visit_foreign_item(self as @mut Visitor<()>, foreign_item, env) } fn visit_item(@mut self, item: @item, env: ()) { self.simple_visitor.visit_item(item); - visit_item(self as @Visitor<()>, item, env) + visit_item(self as @mut Visitor<()>, item, env) } fn visit_local(@mut self, local: @Local, env: ()) { self.simple_visitor.visit_local(local); - visit_local(self as @Visitor<()>, local, env) + visit_local(self as @mut Visitor<()>, local, env) } fn visit_block(@mut self, block: &Block, env: ()) { self.simple_visitor.visit_block(block); - visit_block(self as @Visitor<()>, block, env) + visit_block(self as @mut Visitor<()>, block, env) } fn visit_stmt(@mut self, statement: @stmt, env: ()) { self.simple_visitor.visit_stmt(statement); - visit_stmt(self as @Visitor<()>, statement, env) + visit_stmt(self as @mut Visitor<()>, statement, env) } fn visit_arm(@mut self, arm: &arm, env: ()) { self.simple_visitor.visit_arm(arm); - visit_arm(self as @Visitor<()>, arm, env) + visit_arm(self as @mut Visitor<()>, arm, env) } fn visit_pat(@mut self, pattern: @pat, env: ()) { self.simple_visitor.visit_pat(pattern); - visit_pat(self as @Visitor<()>, pattern, env) + visit_pat(self as @mut Visitor<()>, pattern, env) } fn visit_decl(@mut self, declaration: @decl, env: ()) { self.simple_visitor.visit_decl(declaration); - visit_decl(self as @Visitor<()>, declaration, env) + visit_decl(self as @mut Visitor<()>, declaration, env) } fn visit_expr(@mut self, expression: @expr, env: ()) { self.simple_visitor.visit_expr(expression); - visit_expr(self as @Visitor<()>, expression, env) + visit_expr(self as @mut Visitor<()>, expression, env) } fn visit_expr_post(@mut self, expression: @expr, _: ()) { self.simple_visitor.visit_expr_post(expression) } fn visit_ty(@mut self, typ: &Ty, env: ()) { self.simple_visitor.visit_ty(typ); - visit_ty(self as @Visitor<()>, typ, env) + visit_ty(self as @mut Visitor<()>, typ, env) } fn visit_generics(@mut self, generics: &Generics, env: ()) { self.simple_visitor.visit_generics(generics); - visit_generics(self as @Visitor<()>, generics, env) + visit_generics(self as @mut Visitor<()>, generics, env) } fn visit_fn(@mut self, function_kind: &fn_kind, @@ -705,7 +705,7 @@ impl Visitor<()> for SimpleVisitorVisitor { block, span, node_id); - visit_fn(self as @Visitor<()>, + visit_fn(self as @mut Visitor<()>, function_kind, function_declaration, block, @@ -715,11 +715,11 @@ impl Visitor<()> for SimpleVisitorVisitor { } fn visit_ty_method(@mut self, method_type: &TypeMethod, env: ()) { self.simple_visitor.visit_ty_method(method_type); - visit_ty_method(self as @Visitor<()>, method_type, env) + visit_ty_method(self as @mut Visitor<()>, method_type, env) } fn visit_trait_method(@mut self, trait_method: &trait_method, env: ()) { self.simple_visitor.visit_trait_method(trait_method); - visit_trait_method(self as @Visitor<()>, trait_method, env) + visit_trait_method(self as @mut Visitor<()>, trait_method, env) } fn visit_struct_def(@mut self, struct_definition: @struct_def, @@ -731,7 +731,7 @@ impl Visitor<()> for SimpleVisitorVisitor { identifier, generics, node_id); - visit_struct_def(self as @Visitor<()>, + visit_struct_def(self as @mut Visitor<()>, struct_definition, identifier, generics, @@ -740,7 +740,7 @@ impl Visitor<()> for SimpleVisitorVisitor { } fn visit_struct_field(@mut self, struct_field: @struct_field, env: ()) { self.simple_visitor.visit_struct_field(struct_field); - visit_struct_field(self as @Visitor<()>, struct_field, env) + visit_struct_field(self as @mut Visitor<()>, struct_field, env) } } From 3aefb9649d15c16acef4eb465b06b598b3a1f179 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 11 Aug 2013 13:26:59 -0400 Subject: [PATCH 02/12] librustc: Convert from `@Object` to `@mut Object` as needed --- src/librustc/driver/driver.rs | 2 +- src/librustc/driver/session.rs | 4 ++-- src/librustc/metadata/creader.rs | 6 +++--- src/librustc/metadata/encoder.rs | 4 ++-- src/librustc/metadata/loader.rs | 4 ++-- src/librustc/metadata/tyencode.rs | 2 +- src/librustc/middle/lint.rs | 6 +++--- src/librustc/middle/ty.rs | 7 +++++-- 8 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index fdf887574695f..0e7dc3b2fcd91 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -785,7 +785,7 @@ pub fn build_session(sopts: @session::options, pub fn build_session_(sopts: @session::options, cm: @codemap::CodeMap, demitter: diagnostic::Emitter, - span_diagnostic_handler: @diagnostic::span_handler) + span_diagnostic_handler: @mut diagnostic::span_handler) -> Session { let target_cfg = build_target_config(sopts, demitter); let p_s = parse::new_parse_sess_special_handler(span_diagnostic_handler, diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index d725e2db1eba1..cf62e35488b1f 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -192,7 +192,7 @@ pub struct Session_ { // For a library crate, this is always none entry_fn: @mut Option<(NodeId, codemap::span)>, entry_type: @mut Option, - span_diagnostic: @diagnostic::span_handler, + span_diagnostic: @mut diagnostic::span_handler, filesearch: @filesearch::FileSearch, building_library: @mut bool, working_dir: Path, @@ -261,7 +261,7 @@ impl Session_ { pub fn next_node_id(@self) -> ast::NodeId { return syntax::parse::next_node_id(self.parse_sess); } - pub fn diagnostic(@self) -> @diagnostic::span_handler { + pub fn diagnostic(@self) -> @mut diagnostic::span_handler { self.span_diagnostic } pub fn debugging_opt(@self, opt: uint) -> bool { diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 82f5c4f88435a..eaf01241c8165 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -29,7 +29,7 @@ use syntax::oldvisit; // Traverses an AST, reading all the information about use'd crates and extern // libraries necessary for later resolving, typechecking, linking, etc. -pub fn read_crates(diag: @span_handler, +pub fn read_crates(diag: @mut span_handler, crate: &ast::Crate, cstore: @mut cstore::CStore, filesearch: @FileSearch, @@ -74,7 +74,7 @@ fn dump_crates(crate_cache: &[cache_entry]) { } fn warn_if_multiple_versions(e: @mut Env, - diag: @span_handler, + diag: @mut span_handler, crate_cache: &[cache_entry]) { use std::either::*; @@ -113,7 +113,7 @@ fn warn_if_multiple_versions(e: @mut Env, } struct Env { - diag: @span_handler, + diag: @mut span_handler, filesearch: @FileSearch, cstore: @mut cstore::CStore, os: loader::os, diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index c4919e7f26321..9366d757dd476 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -55,7 +55,7 @@ pub type encode_inlined_item<'self> = &'self fn(ecx: &EncodeContext, ii: ast::inlined_item); pub struct EncodeParams<'self> { - diag: @span_handler, + diag: @mut span_handler, tcx: ty::ctxt, reexports2: middle::resolve::ExportMap2, item_symbols: &'self HashMap, @@ -82,7 +82,7 @@ struct Stats { } pub struct EncodeContext<'self> { - diag: @span_handler, + diag: @mut span_handler, tcx: ty::ctxt, stats: @mut Stats, reexports2: middle::resolve::ExportMap2, diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index 704a22ec97925..554cdf4b2b4fe 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -43,7 +43,7 @@ pub enum os { } pub struct Context { - diag: @span_handler, + diag: @mut span_handler, filesearch: @FileSearch, span: span, ident: @str, @@ -163,7 +163,7 @@ pub fn package_id_from_metas(metas: &[@ast::MetaItem]) -> Option<@str> { } pub fn note_linkage_attrs(intr: @ident_interner, - diag: @span_handler, + diag: @mut span_handler, attrs: ~[ast::Attribute]) { let r = attr::find_linkage_metas(attrs); for mi in r.iter() { diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index ffd79433b7693..915729d254f94 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -25,7 +25,7 @@ use syntax::diagnostic::span_handler; use syntax::print::pprust::*; pub struct ctxt { - diag: @span_handler, + diag: @mut span_handler, // Def -> str Callback: ds: @fn(def_id) -> ~str, // The type context. diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 3a15cbe0f5221..76532b5cd22d6 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -301,7 +301,7 @@ enum AnyVisitor { // recursive call can use the original visitor's method, although the // recursing visitor supplied to the method is the item stopping visitor. OldVisitor(oldvisit::vt<@mut Context>, oldvisit::vt<@mut Context>), - NewVisitor(@visit::Visitor<()>), + NewVisitor(@mut visit::Visitor<()>), } struct Context { @@ -465,7 +465,7 @@ impl Context { self.visitors.push(OldVisitor(v, item_stopping_visitor(v))); } - fn add_lint(&mut self, v: @visit::Visitor<()>) { + fn add_lint(&mut self, v: @mut visit::Visitor<()>) { self.visitors.push(NewVisitor(v)); } @@ -989,7 +989,7 @@ fn lint_unused_mut() -> oldvisit::vt<@mut Context> { }) } -fn lint_session(cx: @mut Context) -> @visit::Visitor<()> { +fn lint_session(cx: @mut Context) -> @mut visit::Visitor<()> { ast_util::id_visitor(|id| { match cx.tcx.sess.lints.pop(&id) { None => {}, diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index bba5d85083b70..5685af2b74e81 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -226,13 +226,16 @@ pub enum AutoRef { AutoBorrowFn(Region), /// Convert from T to *T - AutoUnsafe(ast::mutability) + AutoUnsafe(ast::mutability), + + /// Convert from @Trait/~Trait/&Trait to &Trait + AutoBorrowObj(Region, ast::mutability), } pub type ctxt = @ctxt_; struct ctxt_ { - diag: @syntax::diagnostic::span_handler, + diag: @mut syntax::diagnostic::span_handler, interner: @mut HashMap, next_id: @mut uint, cstore: @mut metadata::cstore::CStore, From 6fe59bf8776f8913aacfb00a2281c94a117b95d1 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 11 Aug 2013 13:29:14 -0400 Subject: [PATCH 03/12] Add a field `borrow_offset` to the type descriptor indicating what amount a T* pointer must be adjusted to reach the contents of the box. For `~T` types, this requires knowing the type `T`, which is not known in the case of objects. --- src/librustc/back/abi.rs | 3 ++- src/librustc/middle/trans/common.rs | 1 + src/librustc/middle/trans/context.rs | 30 ++++++++++++++++++++++++++++ src/librustc/middle/trans/glue.rs | 27 ++++++++++++++++++++----- src/librustc/middle/trans/type_.rs | 22 +++++++++++++++----- src/librustc/middle/ty.rs | 5 +---- src/libstd/unstable/intrinsics.rs | 20 ++++++++++++++++++- src/rt/rust_type.h | 1 + src/rt/rust_util.cpp | 1 + 9 files changed, 94 insertions(+), 16 deletions(-) diff --git a/src/librustc/back/abi.rs b/src/librustc/back/abi.rs index 05b6e90c682f0..dae0ceed22d9d 100644 --- a/src/librustc/back/abi.rs +++ b/src/librustc/back/abi.rs @@ -46,7 +46,8 @@ pub static tydesc_field_take_glue: uint = 2u; pub static tydesc_field_drop_glue: uint = 3u; pub static tydesc_field_free_glue: uint = 4u; pub static tydesc_field_visit_glue: uint = 5u; -pub static n_tydesc_fields: uint = 6u; +pub static tydesc_field_borrow_offset: uint = 6u; +pub static n_tydesc_fields: uint = 7u; // The two halves of a closure: code and environment. pub static fn_field_code: uint = 0u; diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 40a83eb977078..61ec4b2fedbb7 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -54,6 +54,7 @@ pub struct tydesc_info { tydesc: ValueRef, size: ValueRef, align: ValueRef, + borrow_offset: ValueRef, take_glue: Option, drop_glue: Option, free_glue: Option, diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs index a644174731ab4..0a69f25c42cd0 100644 --- a/src/librustc/middle/trans/context.rs +++ b/src/librustc/middle/trans/context.rs @@ -236,6 +236,36 @@ impl CrateContext { pub fn builder(@mut self) -> Builder { Builder::new(self) } + + pub fn const_inbounds_gepi(&self, + pointer: ValueRef, + indices: &[uint]) -> ValueRef { + debug!("const_inbounds_gepi: pointer=%s indices=%?", + self.tn.val_to_str(pointer), indices); + let v: ~[ValueRef] = + indices.iter().transform(|i| C_i32(*i as i32)).collect(); + unsafe { + llvm::LLVMConstInBoundsGEP(pointer, + vec::raw::to_ptr(v), + indices.len() as c_uint) + } + } + + pub fn offsetof_gep(&self, + llptr_ty: Type, + indices: &[uint]) -> ValueRef { + /*! + * Returns the offset of applying the given GEP indices + * to an instance of `llptr_ty`. Similar to `offsetof` in C, + * except that `llptr_ty` must be a pointer type. + */ + + unsafe { + let null = C_null(llptr_ty); + llvm::LLVMConstPtrToInt(self.const_inbounds_gepi(null, indices), + self.int_type.to_ref()) + } + } } #[unsafe_destructor] diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index a70b907f2628c..c65d8d31b741b 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -655,6 +655,18 @@ pub fn declare_tydesc(ccx: &mut CrateContext, t: ty::t) -> @mut tydesc_info { ppaux::ty_to_str(ccx.tcx, t)); } + let has_header = match ty::get(t).sty { + ty::ty_box(*) => true, + ty::ty_uniq(*) => ty::type_contents(ccx.tcx, t).contains_managed(), + _ => false + }; + + let borrow_offset = if has_header { + ccx.offsetof_gep(llty, [0u, abi::box_field_body]) + } else { + C_uint(ccx, 0) + }; + let llsize = llsize_of(ccx, llty); let llalign = llalign_of(ccx, llty); let name = mangle_internal_name_by_type_and_seq(ccx, t, "tydesc").to_managed(); @@ -670,6 +682,7 @@ pub fn declare_tydesc(ccx: &mut CrateContext, t: ty::t) -> @mut tydesc_info { tydesc: gvar, size: llsize, align: llalign, + borrow_offset: borrow_offset, take_glue: None, drop_glue: None, free_glue: None, @@ -785,13 +798,17 @@ pub fn emit_tydescs(ccx: &mut CrateContext) { } }; + debug!("ti.borrow_offset: %s", + ccx.tn.val_to_str(ti.borrow_offset)); + let tydesc = C_named_struct(ccx.tydesc_type, [ti.size, // size - ti.align, // align - take_glue, // take_glue - drop_glue, // drop_glue - free_glue, // free_glue - visit_glue]); // visit_glue + ti.align, // align + take_glue, // take_glue + drop_glue, // drop_glue + free_glue, // free_glue + visit_glue, // visit_glue + ti.borrow_offset]); // borrow_offset unsafe { let gvar = ti.tydesc; diff --git a/src/librustc/middle/trans/type_.rs b/src/librustc/middle/trans/type_.rs index 110febfcc9f57..8d94a0d10d6fa 100644 --- a/src/librustc/middle/trans/type_.rs +++ b/src/librustc/middle/trans/type_.rs @@ -205,10 +205,18 @@ impl Type { let int_ty = Type::int(arch); - let elems = [ - int_ty, int_ty, - glue_fn_ty, glue_fn_ty, glue_fn_ty, glue_fn_ty - ]; + // Must mirror: + // + // std::unstable::intrinsics::TyDesc + // type_desc in rt + + let elems = [int_ty, // size + int_ty, // align + glue_fn_ty, // take + glue_fn_ty, // drop + glue_fn_ty, // free + glue_fn_ty, // visit + int_ty]; // borrow_offset tydesc.set_struct_body(elems, false); @@ -249,8 +257,12 @@ impl Type { Type::struct_(Type::box_header_fields(ctx) + &[*ty], false) } + pub fn opaque() -> Type { + Type::i8() + } + pub fn opaque_box(ctx: &CrateContext) -> Type { - Type::box(ctx, &Type::i8()) + Type::box(ctx, &Type::opaque()) } pub fn unique(ctx: &CrateContext, ty: &Type) -> Type { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 5685af2b74e81..b91984f9b21b8 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -226,10 +226,7 @@ pub enum AutoRef { AutoBorrowFn(Region), /// Convert from T to *T - AutoUnsafe(ast::mutability), - - /// Convert from @Trait/~Trait/&Trait to &Trait - AutoBorrowObj(Region, ast::mutability), + AutoUnsafe(ast::mutability) } pub type ctxt = @ctxt_; diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs index c60edad3dbd56..d2807303fb21c 100644 --- a/src/libstd/unstable/intrinsics.rs +++ b/src/libstd/unstable/intrinsics.rs @@ -38,16 +38,34 @@ pub use realstd::unstable::intrinsics::{TyDesc, Opaque, TyVisitor}; pub type GlueFn = extern "Rust" fn(*i8); -// NB: this has to be kept in sync with the Rust ABI. +// NB: this has to be kept in sync with `type_desc` in `rt` #[lang="ty_desc"] #[cfg(not(test))] pub struct TyDesc { + // sizeof(T) size: uint, + + // alignof(T) align: uint, + + // Called on a copy of a value of type `T` *after* memcpy take_glue: GlueFn, + + // Called when a value of type `T` is no longer needed drop_glue: GlueFn, + + // Called by drop glue when a value of type `T` can be freed free_glue: GlueFn, + + // Called by reflection visitor to visit a value of type `T` visit_glue: GlueFn, + + // If T represents a box pointer (`@U` or `~U`), then + // `borrow_offset` is the amount that the pointer must be adjusted + // to find the payload. This is always derivable from the type + // `U`, but in the case of `@Trait` or `~Trait` objects, the type + // `U` is unknown. + borrow_offset: uint, } #[lang="opaque"] diff --git a/src/rt/rust_type.h b/src/rt/rust_type.h index 60ca5674b0163..57538f1ec75db 100644 --- a/src/rt/rust_type.h +++ b/src/rt/rust_type.h @@ -58,6 +58,7 @@ struct type_desc { glue_fn *drop_glue; glue_fn *free_glue; glue_fn *visit_glue; + size_t borrow_offset; }; extern "C" type_desc *rust_clone_type_desc(type_desc*); diff --git a/src/rt/rust_util.cpp b/src/rt/rust_util.cpp index 4a15830e529a0..28c69af427a32 100644 --- a/src/rt/rust_util.cpp +++ b/src/rt/rust_util.cpp @@ -21,6 +21,7 @@ struct type_desc str_body_tydesc = { NULL, // drop_glue NULL, // free_glue NULL, // visit_glue + 0, // borrow_offset }; // From 38b2e2980e6e30eca28d059428cd6eec3182ef9b Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 11 Aug 2013 13:34:18 -0400 Subject: [PATCH 04/12] Misc small cleanups --- src/librustc/middle/trans/base.rs | 7 +------ src/librustc/middle/trans/common.rs | 1 - src/librustc/middle/trans/foreign.rs | 2 -- 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 762f6953bb222..659872be25e69 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2406,12 +2406,7 @@ pub fn fill_fn_pair(bcx: @mut Block, pair: ValueRef, llfn: ValueRef, } pub fn item_path(ccx: &CrateContext, id: &ast::NodeId) -> path { - match ccx.tcx.items.get_copy(id) { - ast_map::node_item(i, p) => - vec::append((*p).clone(), [path_name(i.ident)]), - // separate map for paths? - _ => fail!("item_path") - } + ty::item_path(ccx.tcx, ast_util::local_def(*id)) } fn exported_name(ccx: @mut CrateContext, path: path, ty: ty::t, attrs: &[ast::Attribute]) -> ~str { diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 61ec4b2fedbb7..bf3dea06ee260 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -687,7 +687,6 @@ pub fn tuplify_box_ty(tcx: ty::ctxt, t: ty::t) -> ty::t { t]); } - // LLVM constant constructors. pub fn C_null(t: Type) -> ValueRef { unsafe { diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index b1e600b9d7376..76d97daceb6ba 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -839,8 +839,6 @@ pub fn trans_intrinsic(ccx: @mut CrateContext, "visit_tydesc" => { let td = get_param(decl, first_real_arg); let visitor = get_param(decl, first_real_arg + 1u); - //let llvisitorptr = alloca(bcx, val_ty(visitor)); - //Store(bcx, visitor, llvisitorptr); let td = PointerCast(bcx, td, ccx.tydesc_type.ptr_to()); glue::call_tydesc_glue_full(bcx, visitor, td, abi::tydesc_field_visit_glue, None); From 38357ebef48aba5ac134dbc32adb445a08db1e20 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 11 Aug 2013 13:36:36 -0400 Subject: [PATCH 05/12] typeck/check/method: Remove `pub` from most methods --- src/librustc/middle/typeck/check/method.rs | 62 ++++++++++++---------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index 84e5d8f9bf743..408f5989d60a9 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -247,7 +247,7 @@ impl<'self> LookupContext<'self> { self.search_for_autosliced_method(self_ty, autoderefs) } - pub fn deref(&self, ty: ty::t) + fn deref(&self, ty: ty::t) -> Option { match ty::deref(self.tcx(), ty, false) { None => None, @@ -262,7 +262,12 @@ impl<'self> LookupContext<'self> { // ______________________________________________________________________ // Candidate collection (see comment at start of file) - pub fn push_inherent_candidates(&self, self_ty: ty::t) { + fn reset_candidates(&self) { + *self.inherent_candidates = ~[]; + *self.extension_candidates = ~[]; + } + + fn push_inherent_candidates(&self, self_ty: ty::t) { /*! * Collect all inherent candidates into * `self.inherent_candidates`. See comment at the start of @@ -403,7 +408,7 @@ impl<'self> LookupContext<'self> { } - pub fn push_inherent_candidates_from_self(&self, + fn push_inherent_candidates_from_self(&self, self_ty: ty::t, did: def_id) { let tcx = self.tcx(); @@ -413,7 +418,7 @@ impl<'self> LookupContext<'self> { self_ty, &[trait_ref], param_self); } - pub fn push_inherent_candidates_from_bounds(&self, + fn push_inherent_candidates_from_bounds(&self, self_ty: ty::t, bounds: &[@TraitRef], param: param_index) { @@ -459,7 +464,7 @@ impl<'self> LookupContext<'self> { } - pub fn push_inherent_impl_candidates_for_type(&self, did: def_id) { + fn push_inherent_impl_candidates_for_type(&self, did: def_id) { let opt_impl_infos = self.tcx().inherent_impls.find(&did); for impl_infos in opt_impl_infos.iter() { for impl_info in impl_infos.iter() { @@ -469,7 +474,7 @@ impl<'self> LookupContext<'self> { } } - pub fn push_candidates_from_impl(&self, + fn push_candidates_from_impl(&self, candidates: &mut ~[Candidate], impl_info: &ty::Impl) { if !self.impl_dups.insert(impl_info.did) { @@ -512,7 +517,7 @@ impl<'self> LookupContext<'self> { // ______________________________________________________________________ // Candidate selection (see comment at start of file) - pub fn search_for_autoderefd_method(&self, + fn search_for_autoderefd_method(&self, self_ty: ty::t, autoderefs: uint) -> Option { @@ -531,12 +536,11 @@ impl<'self> LookupContext<'self> { } } - pub fn consider_reborrow(&self, + fn consider_reborrow(&self, self_ty: ty::t, autoderefs: uint) -> (ty::t, ty::AutoAdjustment) { /*! - * * In the event that we are invoking a method with a receiver * of a borrowed type like `&T`, `&mut T`, or `&mut [T]`, * we will "reborrow" the receiver implicitly. For example, if @@ -598,7 +602,7 @@ impl<'self> LookupContext<'self> { } } - pub fn search_for_autosliced_method(&self, + fn search_for_autosliced_method(&self, self_ty: ty::t, autoderefs: uint) -> Option { @@ -664,7 +668,7 @@ impl<'self> LookupContext<'self> { } } - pub fn search_for_autoptrd_method(&self, self_ty: ty::t, autoderefs: uint) + fn search_for_autoptrd_method(&self, self_ty: ty::t, autoderefs: uint) -> Option { /*! * @@ -696,7 +700,7 @@ impl<'self> LookupContext<'self> { } } - pub fn search_for_some_kind_of_autorefd_method( + fn search_for_some_kind_of_autorefd_method( &self, kind: &fn(Region, ast::mutability) -> ty::AutoRef, autoderefs: uint, @@ -725,7 +729,7 @@ impl<'self> LookupContext<'self> { return None; } - pub fn search_for_method(&self, rcvr_ty: ty::t) + fn search_for_method(&self, rcvr_ty: ty::t) -> Option { debug!("search_for_method(rcvr_ty=%s)", self.ty_to_str(rcvr_ty)); let _indenter = indenter(); @@ -753,7 +757,7 @@ impl<'self> LookupContext<'self> { } } - pub fn consider_candidates(&self, + fn consider_candidates(&self, rcvr_ty: ty::t, candidates: &mut ~[Candidate]) -> Option { @@ -780,7 +784,7 @@ impl<'self> LookupContext<'self> { Some(self.confirm_candidate(rcvr_ty, &relevant_candidates[0])) } - pub fn merge_candidates(&self, candidates: &[Candidate]) -> ~[Candidate] { + fn merge_candidates(&self, candidates: &[Candidate]) -> ~[Candidate] { let mut merged = ~[]; let mut i = 0; while i < candidates.len() { @@ -826,7 +830,7 @@ impl<'self> LookupContext<'self> { return merged; } - pub fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate) + fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate) -> method_map_entry { let tcx = self.tcx(); let fty = self.fn_ty_from_origin(&candidate.origin); @@ -1108,7 +1112,7 @@ impl<'self> LookupContext<'self> { } } - pub fn fn_ty_from_origin(&self, origin: &method_origin) -> ty::t { + fn fn_ty_from_origin(&self, origin: &method_origin) -> ty::t { return match *origin { method_static(did) => { ty::lookup_item_type(self.tcx(), did).ty @@ -1129,7 +1133,7 @@ impl<'self> LookupContext<'self> { } } - pub fn report_candidate(&self, idx: uint, origin: &method_origin) { + fn report_candidate(&self, idx: uint, origin: &method_origin) { match *origin { method_static(impl_did) => { self.report_static_candidate(idx, impl_did) @@ -1143,7 +1147,7 @@ impl<'self> LookupContext<'self> { } } - pub fn report_static_candidate(&self, idx: uint, did: def_id) { + fn report_static_candidate(&self, idx: uint, did: def_id) { let span = if did.crate == ast::LOCAL_CRATE { match self.tcx().items.find(&did.node) { Some(&ast_map::node_method(m, _, _)) => m.span, @@ -1159,7 +1163,7 @@ impl<'self> LookupContext<'self> { ty::item_path_str(self.tcx(), did))); } - pub fn report_param_candidate(&self, idx: uint, did: def_id) { + fn report_param_candidate(&self, idx: uint, did: def_id) { self.tcx().sess.span_note( self.expr.span, fmt!("candidate #%u derives from the bound `%s`", @@ -1167,7 +1171,7 @@ impl<'self> LookupContext<'self> { ty::item_path_str(self.tcx(), did))); } - pub fn report_trait_candidate(&self, idx: uint, did: def_id) { + fn report_trait_candidate(&self, idx: uint, did: def_id) { self.tcx().sess.span_note( self.expr.span, fmt!("candidate #%u derives from the type of the receiver, \ @@ -1176,31 +1180,31 @@ impl<'self> LookupContext<'self> { ty::item_path_str(self.tcx(), did))); } - pub fn infcx(&self) -> @mut infer::InferCtxt { + fn infcx(&self) -> @mut infer::InferCtxt { self.fcx.inh.infcx } - pub fn tcx(&self) -> ty::ctxt { + fn tcx(&self) -> ty::ctxt { self.fcx.tcx() } - pub fn ty_to_str(&self, t: ty::t) -> ~str { + fn ty_to_str(&self, t: ty::t) -> ~str { self.fcx.infcx().ty_to_str(t) } - pub fn cand_to_str(&self, cand: &Candidate) -> ~str { + fn cand_to_str(&self, cand: &Candidate) -> ~str { fmt!("Candidate(rcvr_ty=%s, rcvr_substs=%s, origin=%?)", - self.ty_to_str(cand.rcvr_ty), + cand.rcvr_match_condition.repr(self.tcx()), ty::substs_to_str(self.tcx(), &cand.rcvr_substs), cand.origin) } - pub fn did_to_str(&self, did: def_id) -> ~str { + fn did_to_str(&self, did: def_id) -> ~str { ty::item_path_str(self.tcx(), did) } - pub fn bug(&self, s: ~str) -> ! { - self.tcx().sess.bug(s) + fn bug(&self, s: ~str) -> ! { + self.tcx().sess.span_bug(self.self_expr.span, s) } } From 6f319812d602fb1d6558b583b80a9326f1cc14b3 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 11 Aug 2013 13:39:05 -0400 Subject: [PATCH 06/12] ty: Add (but do not yet use) AutoBorrowObject option to adjustments Note: some portions of this commit written by @Sodel-the-Vociferous (Daniel Ralston) --- src/librustc/middle/ty.rs | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index b91984f9b21b8..720c6ab96b655 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -226,7 +226,10 @@ pub enum AutoRef { AutoBorrowFn(Region), /// Convert from T to *T - AutoUnsafe(ast::mutability) + AutoUnsafe(ast::mutability), + + /// Convert from @Trait/~Trait/&Trait to &Trait + AutoBorrowObj(Region, ast::mutability), } pub type ctxt = @ctxt_; @@ -1004,7 +1007,13 @@ fn mk_t(cx: ctxt, st: sty) -> t { &ty_self(_) => flags |= has_self as uint, &ty_enum(_, ref substs) | &ty_struct(_, ref substs) | &ty_trait(_, ref substs, _, _, _) => { - flags |= sflags(substs); + flags |= sflags(substs); + match st { + ty_trait(_, _, RegionTraitStore(r), _, _) => { + flags |= rflags(r); + } + _ => {} + } } &ty_box(ref m) | &ty_uniq(ref m) | &ty_evec(ref m, _) | &ty_ptr(ref m) | &ty_unboxed_vec(ref m) => { @@ -3009,6 +3018,10 @@ pub fn adjust_ty(cx: ctxt, AutoUnsafe(m) => { mk_ptr(cx, mt {ty: adjusted_ty, mutbl: m}) } + + AutoBorrowObj(r, m) => { + borrow_obj(cx, span, r, m, adjusted_ty) + } } } } @@ -3054,6 +3067,22 @@ pub fn adjust_ty(cx: ctxt, } } } + + fn borrow_obj(cx: ctxt, span: span, r: Region, + m: ast::mutability, ty: ty::t) -> ty::t { + match get(ty).sty { + ty_trait(trt_did, ref trt_substs, _, _, b) => { + ty::mk_trait(cx, trt_did, trt_substs.clone(), + RegionTraitStore(r), m, b) + } + ref s => { + cx.sess.span_bug( + span, + fmt!("borrow-trait-obj associated with bad sty: %?", + s)); + } + } + } } impl AutoRef { @@ -3064,6 +3093,7 @@ impl AutoRef { ty::AutoBorrowVecRef(r, m) => ty::AutoBorrowVecRef(f(r), m), ty::AutoBorrowFn(r) => ty::AutoBorrowFn(f(r)), ty::AutoUnsafe(m) => ty::AutoUnsafe(m), + ty::AutoBorrowObj(r, m) => ty::AutoBorrowObj(f(r), m), } } } From 006c6b6be4499fd999ef3f52996b944263baa220 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 11 Aug 2013 13:42:26 -0400 Subject: [PATCH 07/12] trans: Rely on new AutoBorrowObj adjustment to match up object receivers Note: some portions of this commit written by @Sodel-the-Vociferous (Daniel Ralston) --- src/librustc/middle/trans/callee.rs | 1 - src/librustc/middle/trans/context.rs | 5 +- src/librustc/middle/trans/expr.rs | 101 +++++++++++++++++- src/librustc/middle/trans/meth.rs | 146 +++++++-------------------- 4 files changed, 141 insertions(+), 112 deletions(-) diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index a0e71bc227279..4caaf38487351 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -60,7 +60,6 @@ pub struct MethodData { llfn: ValueRef, llself: ValueRef, temp_cleanup: Option, - self_ty: ty::t, self_mode: ty::SelfMode, } diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs index 0a69f25c42cd0..aa56ff3d26e80 100644 --- a/src/librustc/middle/trans/context.rs +++ b/src/librustc/middle/trans/context.rs @@ -13,7 +13,7 @@ use back::{upcall}; use driver::session; use lib::llvm::{ContextRef, ModuleRef, ValueRef}; use lib::llvm::{llvm, TargetData, TypeNames}; -use lib::llvm::{mk_target_data}; +use lib::llvm::{mk_target_data, False}; use metadata::common::LinkMeta; use middle::astencode; use middle::resolve; @@ -22,6 +22,7 @@ use middle::trans::base; use middle::trans::builder::Builder; use middle::trans::debuginfo; use middle::trans::type_use; +use middle::trans::common::{C_i32, C_null}; use middle::ty; use middle::trans::type_::Type; @@ -30,6 +31,8 @@ use std::c_str::ToCStr; use std::hash; use std::hashmap::{HashMap, HashSet}; use std::local_data; +use std::vec; +use std::libc::c_uint; use syntax::ast; use middle::trans::common::{mono_id,ExternMap,tydesc_info,BuilderRef_res,Stats}; diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 5931b54342f33..cb4a7f364dac6 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -137,9 +137,8 @@ use middle::trans::meth; use middle::trans::tvec; use middle::trans::type_of; use middle::ty::struct_fields; -use middle::ty::{AutoDerefRef, AutoAddEnv}; -use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowVecRef, AutoBorrowFn, - AutoUnsafe}; +use middle::ty::{AutoBorrowObj, AutoDerefRef, AutoAddEnv, AutoUnsafe}; +use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowVecRef, AutoBorrowFn}; use middle::ty; use util::common::indenter; use util::ppaux::Repr; @@ -223,6 +222,10 @@ pub fn trans_to_datum(bcx: @mut Block, expr: @ast::expr) -> DatumBlock { datum.ty, Some(adjustment)); unpack_datum!(bcx, auto_borrow_fn(bcx, adjusted_ty, datum)) } + Some(AutoBorrowObj(*)) => { + unpack_datum!(bcx, auto_borrow_obj( + bcx, adj.autoderefs, expr, datum)) + } }; } } @@ -298,6 +301,98 @@ pub fn trans_to_datum(bcx: @mut Block, expr: @ast::expr) -> DatumBlock { let DatumBlock { bcx, datum } = auto_slice(bcx, autoderefs, expr, datum); auto_ref(bcx, datum) } + + fn auto_borrow_obj(mut bcx: @mut Block, + autoderefs: uint, + expr: @ast::expr, + source_datum: Datum) -> DatumBlock { + let tcx = bcx.tcx(); + let target_obj_ty = expr_ty_adjusted(bcx, expr); + debug!("auto_borrow_obj(target=%s)", + target_obj_ty.repr(tcx)); + let scratch = scratch_datum(bcx, target_obj_ty, + "__auto_borrow_obj", false); + + // Convert a @Object, ~Object, or &Object pair into an &Object pair. + + // Get a pointer to the source object, which is represented as + // a (vtable, data) pair. + let source_llval = source_datum.to_ref_llval(bcx); + + // Set the vtable field of the new pair + let vtable_ptr = GEPi(bcx, source_llval, [0u, abi::trt_field_vtable]); + let vtable = Load(bcx, vtable_ptr); + Store(bcx, vtable, GEPi(bcx, scratch.val, [0u, abi::trt_field_vtable])); + + // Load the data for the source, which is either an @T, + // ~T, or &T, depending on source_obj_ty. + let source_data_ptr = GEPi(bcx, source_llval, [0u, abi::trt_field_box]); + let source_data = Load(bcx, source_data_ptr); // always a ptr + let (source_store, source_mutbl) = match ty::get(source_datum.ty).sty { + ty::ty_trait(_, _, s, m, _) => (s, m), + _ => { + bcx.sess().span_bug( + expr.span, + fmt!("auto_borrow_trait_obj expected a trait, found %s", + source_datum.ty.repr(bcx.tcx()))); + } + }; + let target_data = match source_store { + ty::BoxTraitStore(*) => { + // For deref of @T or @mut T, create a dummy datum and + // use the datum's deref method. This is more work + // than just calling GEPi ourselves, but it ensures + // that any write guards will be appropriate + // processed. Note that we don't know the type T, so + // just substitute `i8`-- it doesn't really matter for + // our purposes right now. + let source_ty = + ty::mk_box(tcx, + ty::mt { + ty: ty::mk_i8(), + mutbl: source_mutbl}); + let source_datum = + Datum {val: source_data, + ty: source_ty, + mode: ByValue}; + let derefd_datum = + unpack_datum!(bcx, + source_datum.deref(bcx, + expr, + autoderefs)); + derefd_datum.to_rptr(bcx).to_value_llval(bcx) + } + ty::UniqTraitStore(*) => { + // For a ~T box, there may or may not be a header, + // depending on whether the type T references managed + // boxes. However, since we do not *know* the type T + // for objects, this presents a hurdle. Our solution is + // to load the "borrow offset" from the type descriptor; + // this value will either be 0 or sizeof(BoxHeader), depending + // on the type T. + let llopaque = + PointerCast(bcx, source_data, Type::opaque().ptr_to()); + let lltydesc_ptr_ptr = + PointerCast(bcx, vtable, + bcx.ccx().tydesc_type.ptr_to().ptr_to()); + let lltydesc_ptr = + Load(bcx, lltydesc_ptr_ptr); + let borrow_offset_ptr = + GEPi(bcx, lltydesc_ptr, + [0, abi::tydesc_field_borrow_offset]); + let borrow_offset = + Load(bcx, borrow_offset_ptr); + InBoundsGEP(bcx, llopaque, [borrow_offset]) + } + ty::RegionTraitStore(*) => { + source_data + } + }; + Store(bcx, target_data, + GEPi(bcx, scratch.val, [0u, abi::trt_field_box])); + + DatumBlock { bcx: bcx, datum: scratch } + } } pub fn trans_into(bcx: @mut Block, expr: @ast::expr, dest: Dest) -> @mut Block { diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index 4cc4f8fa696d0..f5b2ff755966e 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -164,7 +164,6 @@ pub fn trans_method_callee(bcx: @mut Block, llfn: callee_fn.llfn, llself: val, temp_cleanup: temp_cleanups.head_opt().map_move(|v| *v), - self_ty: node_id_type(bcx, this.id), self_mode: mentry.self_mode, }) } @@ -187,13 +186,11 @@ pub fn trans_method_callee(bcx: @mut Block, } } - typeck::method_trait(_, off, store) => { + typeck::method_trait(_, off) => { trans_trait_callee(bcx, callee_id, off, - this, - store, - mentry.explicit_self) + this) } } } @@ -341,7 +338,6 @@ pub fn trans_monomorphized_callee(bcx: @mut Block, llfn: llfn_val, llself: llself_val, temp_cleanup: temp_cleanups.head_opt().map_move(|v| *v), - self_ty: node_id_type(bcx, base.id), self_mode: mentry.self_mode, }) } @@ -406,142 +402,78 @@ pub fn combine_impl_and_methods_tps(bcx: @mut Block, pub fn trans_trait_callee(bcx: @mut Block, callee_id: ast::NodeId, n_method: uint, - self_expr: @ast::expr, - store: ty::TraitStore, - explicit_self: ast::explicit_self_) + self_expr: @ast::expr) -> Callee { - //! - // - // Create a method callee where the method is coming from a trait - // instance (e.g., @Trait type). In this case, we must pull the - // fn pointer out of the vtable that is packaged up with the - // @/~/&Trait instance. @/~/&Traits are represented as a pair, so we - // first evaluate the self expression (expected a by-ref result) and then - // extract the self data and vtable out of the pair. + /*! + * Create a method callee where the method is coming from a trait + * object (e.g., @Trait type). In this case, we must pull the fn + * pointer out of the vtable that is packaged up with the object. + * Objects are represented as a pair, so we first evaluate the self + * expression and then extract the self data and vtable out of the + * pair. + */ let _icx = push_ctxt("impl::trans_trait_callee"); let mut bcx = bcx; - let self_datum = unpack_datum!(bcx, - expr::trans_to_datum(bcx, self_expr)); - let llpair = self_datum.to_ref_llval(bcx); - - let llpair = match explicit_self { - ast::sty_region(*) => Load(bcx, llpair), - ast::sty_static | ast::sty_value | - ast::sty_box(_) | ast::sty_uniq => llpair - }; + + let self_ty = expr_ty_adjusted(bcx, self_expr); + let self_scratch = scratch_datum(bcx, self_ty, "__trait_callee", false); + bcx = expr::trans_into(bcx, self_expr, expr::SaveIn(self_scratch.val)); + + // Arrange a temporary cleanup for the object in case something + // should go wrong before the method is actually *invoked*. + self_scratch.add_clean(bcx); let callee_ty = node_id_type(bcx, callee_id); trans_trait_callee_from_llval(bcx, callee_ty, n_method, - llpair, - store, - explicit_self) + self_scratch.val, + Some(self_scratch.val)) } pub fn trans_trait_callee_from_llval(bcx: @mut Block, callee_ty: ty::t, n_method: uint, llpair: ValueRef, - store: ty::TraitStore, - explicit_self: ast::explicit_self_) + temp_cleanup: Option) -> Callee { - //! - // - // Same as `trans_trait_callee()` above, except that it is given - // a by-ref pointer to the @Trait pair. + /*! + * Same as `trans_trait_callee()` above, except that it is given + * a by-ref pointer to the object pair. + */ let _icx = push_ctxt("impl::trans_trait_callee"); let ccx = bcx.ccx(); - // Load the vtable from the @Trait pair - debug!("(translating trait callee) loading vtable from pair %s", - bcx.val_to_str(llpair)); - let llvtable = Load(bcx, - PointerCast(bcx, - GEPi(bcx, llpair, - [0u, abi::trt_field_vtable]), - Type::vtable().ptr_to().ptr_to())); - - // Load the box from the @Trait pair and GEP over the box header if - // necessary: - let mut llself; + // Load the data pointer from the object. debug!("(translating trait callee) loading second index from pair"); let llboxptr = GEPi(bcx, llpair, [0u, abi::trt_field_box]); let llbox = Load(bcx, llboxptr); - - // Munge `llself` appropriately for the type of `self` in the method. - match explicit_self { - ast::sty_static => { - bcx.tcx().sess.bug("shouldn't see static method here"); - } - ast::sty_value => { - bcx.tcx().sess.bug("methods with by-value self should not be \ - called on objects"); - } - ast::sty_region(*) => { - match store { - ty::UniqTraitStore - if !ty::type_contents(bcx.tcx(), callee_ty).contains_managed() => { - llself = llbox; - } - ty::BoxTraitStore | - ty::UniqTraitStore => { - llself = GEPi(bcx, llbox, [0u, abi::box_field_body]); - } - ty::RegionTraitStore(_) => { - llself = llbox; - } - } - } - ast::sty_box(_) => { - // Bump the reference count on the box. - debug!("(translating trait callee) callee type is `%s`", - bcx.ty_to_str(callee_ty)); - glue::incr_refcnt_of_boxed(bcx, llbox); - - // Pass a pointer to the box. - match store { - ty::BoxTraitStore => llself = llbox, - _ => bcx.tcx().sess.bug("@self receiver with non-@Trait") - } - } - ast::sty_uniq => { - // Pass the unique pointer. - match store { - ty::UniqTraitStore => llself = llbox, - _ => bcx.tcx().sess.bug("~self receiver with non-~Trait") - } - - zero_mem(bcx, llboxptr, ty::mk_opaque_box(bcx.tcx())); - } - } - - llself = PointerCast(bcx, llself, Type::opaque_box(ccx).ptr_to()); - let scratch = scratch_datum(bcx, ty::mk_opaque_box(bcx.tcx()), - "__trait_callee", false); - Store(bcx, llself, scratch.val); - scratch.add_clean(bcx); + let llself = PointerCast(bcx, llbox, Type::opaque_box(ccx).ptr_to()); // Load the function from the vtable and cast it to the expected type. debug!("(translating trait callee) loading method"); let llcallee_ty = type_of_fn_from_ty(ccx, callee_ty); - - // Plus one in order to skip past the type descriptor. + let llvtable = Load(bcx, + PointerCast(bcx, + GEPi(bcx, llpair, + [0u, abi::trt_field_vtable]), + Type::vtable().ptr_to().ptr_to())); let mptr = Load(bcx, GEPi(bcx, llvtable, [0u, n_method + 1])); - let mptr = PointerCast(bcx, mptr, llcallee_ty.ptr_to()); return Callee { bcx: bcx, data: Method(MethodData { llfn: mptr, - llself: scratch.to_value_llval(bcx), - temp_cleanup: Some(scratch.val), - self_ty: scratch.ty, + llself: llself, + temp_cleanup: temp_cleanup, + + // We know that the func declaration is &self, ~self, + // or @self, and such functions are always by-copy + // (right now, at least). self_mode: ty::ByCopy, - /* XXX: Some(llbox) */ }) }; } From 1bceb98084b0e1010d123f48785a89bc7ad7e40f Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 11 Aug 2013 13:44:26 -0400 Subject: [PATCH 08/12] typeck: Modify method resolution to use new object adjustments, and to favor inherent methods over extension methods. The reason to favor inherent methods is that otherwise an impl like impl Foo for @Foo { fn method(&self) { self.method() } } causes infinite recursion. The current change to favor inherent methods is rather hacky; the method resolution code is in need of a refactoring. --- src/librustc/middle/astencode.rs | 4 +- src/librustc/middle/privacy.rs | 2 +- src/librustc/middle/ty.rs | 2 +- src/librustc/middle/typeck/check/method.rs | 394 +++++++++++++------ src/librustc/middle/typeck/check/regionck.rs | 6 +- src/librustc/middle/typeck/infer/coercion.rs | 42 +- src/librustc/middle/typeck/mod.rs | 2 +- src/librustc/util/ppaux.rs | 5 +- 8 files changed, 317 insertions(+), 140 deletions(-) diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 8a7894efb915d..d6342c582f052 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -586,8 +586,8 @@ impl tr for method_origin { } ) } - typeck::method_trait(did, m, vstore) => { - typeck::method_trait(did.tr(xcx), m, vstore) + typeck::method_trait(did, m) => { + typeck::method_trait(did.tr(xcx), m) } } } diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index a4b88870b9739..aa7b2e55cdc63 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -290,7 +290,7 @@ pub fn check_crate<'mm>(tcx: ty::ctxt, method_num: method_num, _ }) | - method_trait(trait_id, method_num, _) => { + method_trait(trait_id, method_num) => { if trait_id.crate == LOCAL_CRATE { match tcx.items.find(&trait_id.node) { Some(&node_item(item, _)) => { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 720c6ab96b655..14d3a92623110 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -3131,7 +3131,7 @@ pub fn method_call_type_param_defs(tcx: ctxt, typeck::method_param(typeck::method_param { trait_id: trt_id, method_num: n_mth, _}) | - typeck::method_trait(trt_id, n_mth, _) => { + typeck::method_trait(trt_id, n_mth) => { // ...trait methods bounds, in contrast, include only the // method bounds, so we must preprend the tps from the // trait itself. This ought to be harmonized. diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index 408f5989d60a9..352836d81e459 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -94,6 +94,7 @@ use middle::typeck::{method_static, method_trait}; use middle::typeck::{param_numbered, param_self, param_index}; use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig; use util::common::indenter; +use util::ppaux::Repr; use std::hashmap::HashSet; use std::result; @@ -147,9 +148,24 @@ pub fn lookup( check_traits: check_traits, autoderef_receiver: autoderef_receiver, }; - let mme = lcx.do_lookup(self_ty); - debug!("method lookup for %s yielded %?", expr.repr(fcx.tcx()), mme); - return mme; + + let self_ty = structurally_resolved_type(fcx, self_expr.span, self_ty); + debug!("method lookup(self_ty=%s, expr=%s, self_expr=%s)", + self_ty.repr(fcx.tcx()), expr.repr(fcx.tcx()), + self_expr.repr(fcx.tcx())); + + debug!("searching inherent candidates"); + lcx.push_inherent_candidates(self_ty); + let mme = lcx.search(self_ty); + if mme.is_some() { + return mme; + } + + debug!("searching extension candidates"); + lcx.reset_candidates(); + lcx.push_bound_candidates(self_ty); + lcx.push_extension_candidates(); + return lcx.search(self_ty); } pub struct LookupContext<'self> { @@ -173,27 +189,28 @@ pub struct LookupContext<'self> { */ #[deriving(Clone)] pub struct Candidate { - rcvr_ty: ty::t, + rcvr_match_condition: RcvrMatchCondition, rcvr_substs: ty::substs, method_ty: @ty::Method, origin: method_origin, } -impl<'self> LookupContext<'self> { - pub fn do_lookup(&self, self_ty: ty::t) -> Option { - let self_ty = structurally_resolved_type(self.fcx, - self.self_expr.span, - self_ty); - - debug!("do_lookup(self_ty=%s, expr=%s, self_expr=%s)", - self.ty_to_str(self_ty), - self.expr.repr(self.tcx()), - self.self_expr.repr(self.tcx())); - - // Prepare the list of candidates - self.push_inherent_candidates(self_ty); - self.push_extension_candidates(); +/// This type represents the conditions under which the receiver is +/// considered to "match" a given method candidate. Typically the test +/// is whether the receiver is of a particular type. However, this +/// type is the type of the receiver *after accounting for the +/// method's self type* (e.g., if the method is an `@self` method, we +/// have *already verified* that the receiver is of some type `@T` and +/// now we must check that the type `T` is correct). Unfortunately, +/// because traits are not types, this is a pain to do. +#[deriving(Clone)] +enum RcvrMatchCondition { + RcvrMatchesIfObject(ast::def_id), + RcvrMatchesIfSubtype(ty::t) +} +impl<'self> LookupContext<'self> { + fn search(&self, self_ty: ty::t) -> Option { let mut self_ty = self_ty; let mut autoderefs = 0; loop { @@ -280,20 +297,10 @@ impl<'self> LookupContext<'self> { let mut self_ty = self_ty; loop { match get(self_ty).sty { - ty_param(p) => { - self.push_inherent_candidates_from_param(self_ty, p); - } - ty_trait(did, ref substs, store, _, _) => { - self.push_inherent_candidates_from_trait( - self_ty, did, substs, store); + ty_trait(did, ref substs, _, _, _) => { + self.push_inherent_candidates_from_trait(did, substs); self.push_inherent_impl_candidates_for_type(did); } - ty_self(self_did) => { - // Call is of the form "self.foo()" and appears in one - // of a trait's default method implementations. - self.push_inherent_candidates_from_self( - self_ty, self_did); - } ty_enum(did, _) | ty_struct(did, _) => { if self.check_traits == CheckTraitsAndInherentMethods { self.push_inherent_impl_candidates_for_type(did); @@ -312,7 +319,30 @@ impl<'self> LookupContext<'self> { } } - pub fn push_extension_candidates(&self) { + fn push_bound_candidates(&self, self_ty: ty::t) { + let mut self_ty = self_ty; + loop { + match get(self_ty).sty { + ty_param(p) => { + self.push_inherent_candidates_from_param(self_ty, p); + } + ty_self(self_did) => { + // Call is of the form "self.foo()" and appears in one + // of a trait's default method implementations. + self.push_inherent_candidates_from_self( + self_ty, self_did); + } + _ => { /* No bound methods in these types */ } + } + + self_ty = match self.deref(self_ty) { + None => { return; } + Some(ty) => { ty } + } + } + } + + fn push_extension_candidates(&self) { // If the method being called is associated with a trait, then // find all the impls of that trait. Each of those are // candidates. @@ -333,11 +363,9 @@ impl<'self> LookupContext<'self> { } } - pub fn push_inherent_candidates_from_trait(&self, - self_ty: ty::t, + fn push_inherent_candidates_from_trait(&self, did: def_id, - substs: &ty::substs, - store: ty::TraitStore) { + substs: &ty::substs) { debug!("push_inherent_candidates_from_trait(did=%s, substs=%s)", self.did_to_str(did), substs_to_str(self.tcx(), substs)); @@ -351,41 +379,35 @@ impl<'self> LookupContext<'self> { }; let method = ms[index]; - /* FIXME(#5762) we should transform the vstore in accordance - with the self type - - match method.self_type { - ast::sty_region(_) => { - return; // inapplicable + match method.explicit_self { + ast::sty_static => { + return; // not a method we can call with dot notation } - ast::sty_region(_) => vstore_slice(r) - ast::sty_box(_) => vstore_box, // NDM mutability, as per #5762 - ast::sty_uniq(_) => vstore_uniq + _ => {} } - */ // It is illegal to invoke a method on a trait instance that - // refers to the `self` type. Nonetheless, we substitute - // `trait_ty` for `self` here, because it allows the compiler - // to soldier on. An error will be reported should this - // candidate be selected if the method refers to `self`. + // refers to the `self` type. An error will be reported by + // `enforce_object_limitations()` if the method refers + // to the `Self` type. Substituting ty_err here allows + // compiler to soldier on. // - // NB: `confirm_candidate()` also relies upon this substitution - // for Self. + // NOTE: `confirm_candidate()` also relies upon this substitution + // for Self. (fix) let rcvr_substs = substs { - self_ty: Some(self_ty), + self_ty: Some(ty::mk_err()), ..(*substs).clone() }; self.inherent_candidates.push(Candidate { - rcvr_ty: self_ty, + rcvr_match_condition: RcvrMatchesIfObject(did), rcvr_substs: rcvr_substs, method_ty: method, - origin: method_trait(did, index, store) + origin: method_trait(did, index) }); } - pub fn push_inherent_candidates_from_param(&self, + fn push_inherent_candidates_from_param(&self, rcvr_ty: ty::t, param_ty: param_ty) { debug!("push_inherent_candidates_from_param(param_ty=%?)", @@ -438,11 +460,11 @@ impl<'self> LookupContext<'self> { let method = trait_methods[pos]; let cand = Candidate { - rcvr_ty: self_ty, + rcvr_match_condition: RcvrMatchesIfSubtype(self_ty), rcvr_substs: bound_trait_ref.substs.clone(), method_ty: method, origin: method_param( - method_param { + method_param { trait_id: bound_trait_ref.def_id, method_num: pos, param_num: param, @@ -507,7 +529,7 @@ impl<'self> LookupContext<'self> { } = impl_self_ty(&vcx, location_info, impl_info.did); candidates.push(Candidate { - rcvr_ty: impl_ty, + rcvr_match_condition: RcvrMatchesIfSubtype(impl_ty), rcvr_substs: impl_substs, method_ty: method, origin: method_static(method.def_id) @@ -583,6 +605,17 @@ impl<'self> LookupContext<'self> { autoderefs: autoderefs, autoref: Some(ty::AutoBorrowVec(region, self_mt.mutbl))})) } + ty_trait(did, ref substs, ty::RegionTraitStore(_), mutbl, bounds) => { + let region = + self.infcx().next_region_var( + infer::Autoref(self.expr.span)); + (ty::mk_trait(tcx, did, substs.clone(), + ty::RegionTraitStore(region), + mutbl, bounds), + ty::AutoDerefRef(ty::AutoDerefRef { + autoderefs: autoderefs, + autoref: Some(ty::AutoBorrowObj(region, mutbl))})) + } _ => { (self_ty, ty::AutoDerefRef(ty::AutoDerefRef { @@ -612,7 +645,8 @@ impl<'self> LookupContext<'self> { * `~[]` to `&[]`. */ let tcx = self.tcx(); - match ty::get(self_ty).sty { + let sty = ty::get(self_ty).sty.clone(); + match sty { ty_evec(mt, vstore_box) | ty_evec(mt, vstore_uniq) | ty_evec(mt, vstore_slice(_)) | // NDM(#3148) @@ -659,8 +693,20 @@ impl<'self> LookupContext<'self> { }) } - ty_trait(*) | ty_closure(*) => { - // NDM---eventually these should be some variant of autoref + ty_trait(trt_did, trt_substs, _, _, b) => { + // Coerce ~/@/&Trait instances to &Trait. + + self.search_for_some_kind_of_autorefd_method( + AutoBorrowObj, autoderefs, [m_const, m_imm, m_mutbl], + |trt_mut, reg| { + ty::mk_trait(tcx, trt_did, trt_substs.clone(), + RegionTraitStore(reg), trt_mut, b) + }) + } + + ty_closure(*) => { + // This case should probably be handled similarly to + // Trait instances. None } @@ -840,31 +886,16 @@ impl<'self> LookupContext<'self> { self.cand_to_str(candidate), self.ty_to_str(fty)); - self.enforce_trait_instance_limitations(fty, candidate); + self.enforce_object_limitations(fty, candidate); self.enforce_drop_trait_limitations(candidate); // static methods should never have gotten this far: assert!(candidate.method_ty.explicit_self != sty_static); let transformed_self_ty = match candidate.origin { - method_trait(*) => { - match candidate.method_ty.explicit_self { - sty_region(*) => { - // FIXME(#5762) again, preserving existing - // behavior here which (for &self) desires - // &@Trait where @Trait is the type of the - // receiver. Here we fetch the method's - // transformed_self_ty which will be something - // like &'a Self. We then perform a - // substitution which will replace Self with - // @Trait. - let t = candidate.method_ty.transformed_self_ty.unwrap(); - ty::subst(tcx, &candidate.rcvr_substs, t) - } - _ => { - candidate.rcvr_ty - } - } + method_trait(trait_def_id, _) => { + self.construct_transformed_self_ty_for_object( + trait_def_id, candidate) } _ => { let t = candidate.method_ty.transformed_self_ty.unwrap(); @@ -954,23 +985,88 @@ impl<'self> LookupContext<'self> { self.fcx.write_ty(self.callee_id, fty); self.fcx.write_substs(self.callee_id, all_substs); method_map_entry { - self_ty: rcvr_ty, + self_ty: transformed_self_ty, self_mode: self_mode, explicit_self: candidate.method_ty.explicit_self, origin: candidate.origin, } } - pub fn enforce_trait_instance_limitations(&self, - method_fty: ty::t, - candidate: &Candidate) { + fn construct_transformed_self_ty_for_object(&self, + trait_def_id: ast::def_id, + candidate: &Candidate) -> ty::t + { /*! + * This is a bit tricky. We have a match against a trait method + * being invoked on an object, and we want to generate the + * self-type. As an example, consider a trait + * + * trait Foo { + * fn r_method<'a>(&'a self); + * fn m_method(@mut self); + * } * - * There are some limitations to calling functions through a - * trait instance, because (a) the self type is not known + * Now, assuming that `r_method` is being called, we want the + * result to be `&'a Foo`. Assuming that `m_method` is being + * called, we want the result to be `@mut Foo`. Of course, + * this transformation has already been done as part of + * `candidate.method_ty.transformed_self_ty`, but there the + * type is expressed in terms of `Self` (i.e., `&'a Self`, `@mut Self`). + * Because objects are not standalone types, we can't just substitute + * `s/Self/Foo/`, so we must instead perform this kind of hokey + * match below. + */ + + let substs = ty::substs {regions: candidate.rcvr_substs.regions.clone(), + self_ty: None, + tps: candidate.rcvr_substs.tps.clone()}; + match candidate.method_ty.explicit_self { + ast::sty_static => { + self.bug(~"static method for object type receiver"); + } + ast::sty_value => { + ty::mk_err() // error reported in `enforce_object_limitations()` + } + ast::sty_region(*) | ast::sty_box(*) | ast::sty_uniq(*) => { + let transformed_self_ty = + candidate.method_ty.transformed_self_ty.clone().unwrap(); + match ty::get(transformed_self_ty).sty { + ty::ty_rptr(r, mt) => { // must be sty_region + ty::mk_trait(self.tcx(), trait_def_id, + substs, RegionTraitStore(r), mt.mutbl, + ty::EmptyBuiltinBounds()) + } + ty::ty_box(mt) => { // must be sty_box + ty::mk_trait(self.tcx(), trait_def_id, + substs, BoxTraitStore, mt.mutbl, + ty::EmptyBuiltinBounds()) + } + ty::ty_uniq(mt) => { // must be sty_uniq + ty::mk_trait(self.tcx(), trait_def_id, + substs, UniqTraitStore, mt.mutbl, + ty::EmptyBuiltinBounds()) + } + _ => { + self.bug( + fmt!("'impossible' transformed_self_ty: %s", + transformed_self_ty.repr(self.tcx()))); + } + } + } + } + } + + fn enforce_object_limitations(&self, + method_fty: ty::t, + candidate: &Candidate) + { + /*! + * There are some limitations to calling functions through an + * object, because (a) the self type is not known * (that's the whole point of a trait instance, after all, to * obscure the self type) and (b) the call must go through a - * vtable and hence cannot be monomorphized. */ + * vtable and hence cannot be monomorphized. + */ match candidate.origin { method_static(*) | method_param(*) => { @@ -979,21 +1075,39 @@ impl<'self> LookupContext<'self> { method_trait(*) => {} } - if ty::type_has_self(method_fty) { + match candidate.method_ty.explicit_self { + ast::sty_static => { // reason (a) above + self.tcx().sess.span_err( + self.expr.span, + "cannot call a method without a receiver \ + through an object"); + } + + ast::sty_value => { // reason (a) above + self.tcx().sess.span_err( + self.expr.span, + "cannot call a method with a by-value receiver \ + through an object"); + } + + ast::sty_region(*) | ast::sty_box(*) | ast::sty_uniq(*) => {} + } + + if ty::type_has_self(method_fty) { // reason (a) above self.tcx().sess.span_err( self.expr.span, "cannot call a method whose type contains a \ - self-type through a boxed trait"); + self-type through an object"); } - if candidate.method_ty.generics.has_type_params() { + if candidate.method_ty.generics.has_type_params() { // reason (b) above self.tcx().sess.span_err( self.expr.span, - "cannot call a generic method through a boxed trait"); + "cannot call a generic method through an object"); } } - pub fn enforce_drop_trait_limitations(&self, candidate: &Candidate) { + fn enforce_drop_trait_limitations(&self, candidate: &Candidate) { // No code can call the finalize method explicitly. let bad; match candidate.origin { @@ -1003,7 +1117,7 @@ impl<'self> LookupContext<'self> { // XXX: does this properly enforce this on everything now // that self has been merged in? -sully method_param(method_param { trait_id: trait_id, _ }) | - method_trait(trait_id, _, _) => { + method_trait(trait_id, _) => { bad = self.tcx().destructor_for_type.contains_key(&trait_id); } } @@ -1016,43 +1130,18 @@ impl<'self> LookupContext<'self> { // `rcvr_ty` is the type of the expression. It may be a subtype of a // candidate method's `self_ty`. - pub fn is_relevant(&self, rcvr_ty: ty::t, candidate: &Candidate) -> bool { + fn is_relevant(&self, rcvr_ty: ty::t, candidate: &Candidate) -> bool { debug!("is_relevant(rcvr_ty=%s, candidate=%s)", self.ty_to_str(rcvr_ty), self.cand_to_str(candidate)); - // Check for calls to object methods. We resolve these differently. - // - // FIXME(#5762)---we don't check that an @self method is only called - // on an @Trait object here and so forth - match candidate.origin { - method_trait(*) => { - match candidate.method_ty.explicit_self { - sty_static | sty_value => { - return false; - } - sty_region(*) => { - // just echoing current behavior here, which treats - // an &self method on an @Trait object as requiring - // an &@Trait receiver (wacky) - } - sty_box(*) | sty_uniq(*) => { - return self.fcx.can_mk_subty(rcvr_ty, - candidate.rcvr_ty).is_ok(); - } - }; - } - _ => {} - } - - let result = match candidate.method_ty.explicit_self { + return match candidate.method_ty.explicit_self { sty_static => { debug!("(is relevant?) explicit self is static"); false } sty_value => { - debug!("(is relevant?) explicit self is by-value"); - self.fcx.can_mk_subty(rcvr_ty, candidate.rcvr_ty).is_ok() + rcvr_matches_ty(self.fcx, rcvr_ty, candidate) } sty_region(_, m) => { @@ -1060,7 +1149,12 @@ impl<'self> LookupContext<'self> { match ty::get(rcvr_ty).sty { ty::ty_rptr(_, mt) => { mutability_matches(mt.mutbl, m) && - self.fcx.can_mk_subty(mt.ty, candidate.rcvr_ty).is_ok() + rcvr_matches_ty(self.fcx, mt.ty, candidate) + } + + ty::ty_trait(self_did, _, RegionTraitStore(_), self_m, _) => { + mutability_matches(self_m, m) && + rcvr_matches_object(self_did, candidate) } _ => false @@ -1072,7 +1166,12 @@ impl<'self> LookupContext<'self> { match ty::get(rcvr_ty).sty { ty::ty_box(mt) => { mutability_matches(mt.mutbl, m) && - self.fcx.can_mk_subty(mt.ty, candidate.rcvr_ty).is_ok() + rcvr_matches_ty(self.fcx, mt.ty, candidate) + } + + ty::ty_trait(self_did, _, BoxTraitStore, self_m, _) => { + mutability_matches(self_m, m) && + rcvr_matches_object(self_did, candidate) } _ => false @@ -1083,8 +1182,11 @@ impl<'self> LookupContext<'self> { debug!("(is relevant?) explicit self is a unique pointer"); match ty::get(rcvr_ty).sty { ty::ty_uniq(mt) => { - mutability_matches(mt.mutbl, ast::m_imm) && - self.fcx.can_mk_subty(mt.ty, candidate.rcvr_ty).is_ok() + rcvr_matches_ty(self.fcx, mt.ty, candidate) + } + + ty::ty_trait(self_did, _, UniqTraitStore, _, _) => { + rcvr_matches_object(self_did, candidate) } _ => false @@ -1092,9 +1194,30 @@ impl<'self> LookupContext<'self> { } }; - debug!("(is relevant?) %s", if result { "yes" } else { "no" }); + fn rcvr_matches_object(self_did: ast::def_id, + candidate: &Candidate) -> bool { + match candidate.rcvr_match_condition { + RcvrMatchesIfObject(desired_did) => { + self_did == desired_did + } + RcvrMatchesIfSubtype(_) => { + false + } + } + } - return result; + fn rcvr_matches_ty(fcx: @mut FnCtxt, + rcvr_ty: ty::t, + candidate: &Candidate) -> bool { + match candidate.rcvr_match_condition { + RcvrMatchesIfObject(_) => { + false + } + RcvrMatchesIfSubtype(of_type) => { + fcx.can_mk_subty(rcvr_ty, of_type).is_ok() + } + } + } fn mutability_matches(self_mutbl: ast::mutability, candidate_mutbl: ast::mutability) -> bool { @@ -1120,7 +1243,7 @@ impl<'self> LookupContext<'self> { method_param(ref mp) => { type_of_trait_method(self.tcx(), mp.trait_id, mp.method_num) } - method_trait(did, idx, _) => { + method_trait(did, idx) => { type_of_trait_method(self.tcx(), did, idx) } }; @@ -1141,7 +1264,7 @@ impl<'self> LookupContext<'self> { method_param(ref mp) => { self.report_param_candidate(idx, (*mp).trait_id) } - method_trait(trait_did, _, _) => { + method_trait(trait_did, _) => { self.report_trait_candidate(idx, trait_did) } } @@ -1214,3 +1337,16 @@ pub fn get_mode_from_explicit_self(explicit_self: ast::explicit_self_) -> SelfMo _ => ty::ByCopy, } } + +impl Repr for RcvrMatchCondition { + fn repr(&self, tcx: ty::ctxt) -> ~str { + match *self { + RcvrMatchesIfObject(d) => { + fmt!("RcvrMatchesIfObject(%s)", d.repr(tcx)) + } + RcvrMatchesIfSubtype(t) => { + fmt!("RcvrMatchesIfSubtype(%s)", t.repr(tcx)) + } + } + } +} diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index 18e7295d61a05..d034277d44af8 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -863,7 +863,8 @@ pub mod guarantor { ty::AutoBorrowVec(r, _) | ty::AutoBorrowVecRef(r, _) | - ty::AutoBorrowFn(r) => { + ty::AutoBorrowFn(r) | + ty::AutoBorrowObj(r, _) => { // In each of these cases, what is being borrowed is // not the (autoderef'd) expr itself but rather the // contents of the autoderef'd expression (i.e., what @@ -1072,7 +1073,8 @@ pub mod guarantor { Some(ty::AutoPtr(r, _)) | Some(ty::AutoBorrowVec(r, _)) | Some(ty::AutoBorrowVecRef(r, _)) | - Some(ty::AutoBorrowFn(r)) => { + Some(ty::AutoBorrowFn(r)) | + Some(ty::AutoBorrowObj(r, _)) => { // If there is an autoref, then the result of this // expression will be some sort of borrowed pointer. expr_ct.cat.guarantor = None; diff --git a/src/librustc/middle/typeck/infer/coercion.rs b/src/librustc/middle/typeck/infer/coercion.rs index a6899d7150e08..f2bde146ea79c 100644 --- a/src/librustc/middle/typeck/infer/coercion.rs +++ b/src/librustc/middle/typeck/infer/coercion.rs @@ -65,7 +65,7 @@ we may want to adjust precisely when coercions occur. */ -use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowFn}; +use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowFn, AutoBorrowObj}; use middle::ty::{AutoDerefRef}; use middle::ty::{vstore_slice, vstore_box, vstore_uniq}; use middle::ty::{mt}; @@ -121,6 +121,12 @@ impl Coerce { }; } + ty::ty_trait(_, _, ty::RegionTraitStore(*), _, _) => { + return do self.unpack_actual_value(a) |sty_a| { + self.coerce_borrowed_object(a, sty_a, b) + }; + } + ty::ty_ptr(mt_b) => { return do self.unpack_actual_value(a) |sty_a| { self.coerce_unsafe_ptr(a, sty_a, b, mt_b) @@ -265,6 +271,40 @@ impl Coerce { }))) } + fn coerce_borrowed_object(&self, + a: ty::t, + sty_a: &ty::sty, + b: ty::t) -> CoerceResult + { + debug!("coerce_borrowed_object(a=%s, sty_a=%?, b=%s)", + a.inf_str(self.infcx), sty_a, + b.inf_str(self.infcx)); + + let tcx = self.infcx.tcx; + let r_a = self.infcx.next_region_var(Coercion(self.trace)); + let trt_mut; + + let a_borrowed = match *sty_a { + ty::ty_trait(_, _, ty::RegionTraitStore(_), _, _) => { + return self.subtype(a, b); + } + ty::ty_trait(did, ref substs, _, m, b) => { + trt_mut = m; + ty::mk_trait(tcx, did, substs.clone(), + ty::RegionTraitStore(r_a), m, b) + } + _ => { + return self.subtype(a, b); + } + }; + + if_ok!(self.tys(a_borrowed, b)); + Ok(Some(@AutoDerefRef(AutoDerefRef { + autoderefs: 0, + autoref: Some(AutoBorrowObj(r_a, trt_mut)) + }))) + } + pub fn coerce_borrowed_fn(&self, a: ty::t, sty_a: &ty::sty, diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs index b1356ffb2d5e9..53ae80f19facc 100644 --- a/src/librustc/middle/typeck/mod.rs +++ b/src/librustc/middle/typeck/mod.rs @@ -88,7 +88,7 @@ pub enum method_origin { method_param(method_param), // method invoked on a trait instance - method_trait(ast::def_id, uint, ty::TraitStore), + method_trait(ast::def_id, uint), } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 1bea3003c63d2..3bc0a7167e9bd 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -747,9 +747,8 @@ impl Repr for typeck::method_origin { &typeck::method_param(ref p) => { p.repr(tcx) } - &typeck::method_trait(def_id, n, st) => { - fmt!("method_trait(%s, %?, %s)", def_id.repr(tcx), n, - st.repr(tcx)) + &typeck::method_trait(def_id, n) => { + fmt!("method_trait(%s, %?)", def_id.repr(tcx), n) } } } From 66b8ad58671ef174c5051cc662d4e956be374f2f Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 11 Aug 2013 13:56:30 -0400 Subject: [PATCH 09/12] borrowck: Integrate AutoBorrowObj into borrowck / mem_categorization Also cleanup the treatment of mutability in mem_categorization, which still included the concept of interior mutability. At some point, we should refactor the types to exclude the possibility of interior mutability rather than just ignoring the mutability value in those cases. --- src/librustc/middle/borrowck/check_loans.rs | 2 +- .../borrowck/gather_loans/gather_moves.rs | 2 +- .../middle/borrowck/gather_loans/lifetime.rs | 6 +- .../middle/borrowck/gather_loans/mod.rs | 10 +- .../borrowck/gather_loans/restrictions.rs | 4 +- src/librustc/middle/mem_categorization.rs | 93 ++++++++++--------- 6 files changed, 65 insertions(+), 52 deletions(-) diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index 88e168db5584f..620a1e9efe33f 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -362,7 +362,7 @@ impl<'self> CheckLoanCtxt<'self> { } mc::cat_discr(b, _) | - mc::cat_deref(b, _, mc::uniq_ptr(*)) => { + mc::cat_deref(b, _, mc::uniq_ptr) => { assert_eq!(cmt.mutbl, mc::McInherited); cmt = b; } diff --git a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs index 54a5c09a0e979..24a6e5b6e0b2b 100644 --- a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs +++ b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs @@ -173,7 +173,7 @@ fn check_is_legal_to_move_from(bccx: @BorrowckCtxt, } } - mc::cat_deref(b, _, mc::uniq_ptr(*)) | + mc::cat_deref(b, _, mc::uniq_ptr) | mc::cat_discr(b, _) => { check_is_legal_to_move_from(bccx, cmt0, b) } diff --git a/src/librustc/middle/borrowck/gather_loans/lifetime.rs b/src/librustc/middle/borrowck/gather_loans/lifetime.rs index ddcc5fe56d043..b315a7a2e7290 100644 --- a/src/librustc/middle/borrowck/gather_loans/lifetime.rs +++ b/src/librustc/middle/borrowck/gather_loans/lifetime.rs @@ -74,7 +74,7 @@ impl GuaranteeLifetimeContext { mc::cat_arg(*) | // L-Local mc::cat_self(*) | // L-Local mc::cat_deref(_, _, mc::region_ptr(*)) | // L-Deref-Borrowed - mc::cat_deref(_, _, mc::unsafe_ptr) => { + mc::cat_deref(_, _, mc::unsafe_ptr(*)) => { let scope = self.scope(cmt); self.check_scope(scope) } @@ -108,7 +108,7 @@ impl GuaranteeLifetimeContext { } mc::cat_downcast(base) | - mc::cat_deref(base, _, mc::uniq_ptr(*)) | // L-Deref-Send + mc::cat_deref(base, _, mc::uniq_ptr) | // L-Deref-Send mc::cat_interior(base, _) => { // L-Field self.check(base, discr_scope) } @@ -347,7 +347,7 @@ impl GuaranteeLifetimeContext { r } mc::cat_downcast(cmt) | - mc::cat_deref(cmt, _, mc::uniq_ptr(*)) | + mc::cat_deref(cmt, _, mc::uniq_ptr) | mc::cat_deref(cmt, _, mc::gc_ptr(*)) | mc::cat_interior(cmt, _) | mc::cat_stack_upvar(cmt) | diff --git a/src/librustc/middle/borrowck/gather_loans/mod.rs b/src/librustc/middle/borrowck/gather_loans/mod.rs index b970a6585f6cd..6ebc4b49b3779 100644 --- a/src/librustc/middle/borrowck/gather_loans/mod.rs +++ b/src/librustc/middle/borrowck/gather_loans/mod.rs @@ -352,13 +352,21 @@ impl GatherLoanCtxt { r) } ty::AutoBorrowFn(r) => { - let cmt_deref = mcx.cat_deref_fn(expr, cmt, 0); + let cmt_deref = mcx.cat_deref_fn_or_obj(expr, cmt, 0); self.guarantee_valid(expr.id, expr.span, cmt_deref, m_imm, r) } + ty::AutoBorrowObj(r, m) => { + let cmt_deref = mcx.cat_deref_fn_or_obj(expr, cmt, 0); + self.guarantee_valid(expr.id, + expr.span, + cmt_deref, + m, + r) + } ty::AutoUnsafe(_) => {} } } diff --git a/src/librustc/middle/borrowck/gather_loans/restrictions.rs b/src/librustc/middle/borrowck/gather_loans/restrictions.rs index ad32eb0c805e4..46bb23e400ee5 100644 --- a/src/librustc/middle/borrowck/gather_loans/restrictions.rs +++ b/src/librustc/middle/borrowck/gather_loans/restrictions.rs @@ -101,7 +101,7 @@ impl RestrictionsContext { self.extend(result, cmt.mutbl, LpInterior(i), restrictions) } - mc::cat_deref(cmt_base, _, mc::uniq_ptr(*)) => { + mc::cat_deref(cmt_base, _, mc::uniq_ptr) => { // R-Deref-Send-Pointer // // When we borrow the interior of an owned pointer, we @@ -194,7 +194,7 @@ impl RestrictionsContext { } } - mc::cat_deref(_, _, mc::unsafe_ptr) => { + mc::cat_deref(_, _, mc::unsafe_ptr(*)) => { // We are very trusting when working with unsafe pointers. Safe } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 6c5209cf504a6..283724447f831 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -84,10 +84,10 @@ pub struct CopiedUpvar { // different kinds of pointers: #[deriving(Eq)] pub enum ptr_kind { - uniq_ptr(ast::mutability), + uniq_ptr, gc_ptr(ast::mutability), region_ptr(ast::mutability, ty::Region), - unsafe_ptr + unsafe_ptr(ast::mutability) } // We use the term "interior" to mean "something reachable from the @@ -156,14 +156,12 @@ pub enum deref_kind { // pointer adjustment). pub fn opt_deref_kind(t: ty::t) -> Option { match ty::get(t).sty { - ty::ty_uniq(mt) => { - Some(deref_ptr(uniq_ptr(mt.mutbl))) - } - + ty::ty_uniq(_) | + ty::ty_trait(_, _, ty::UniqTraitStore, _, _) | ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) | ty::ty_closure(ty::ClosureTy {sigil: ast::OwnedSigil, _}) => { - Some(deref_ptr(uniq_ptr(m_imm))) + Some(deref_ptr(uniq_ptr)) } ty::ty_rptr(r, mt) | @@ -171,24 +169,32 @@ pub fn opt_deref_kind(t: ty::t) -> Option { Some(deref_ptr(region_ptr(mt.mutbl, r))) } + ty::ty_trait(_, _, ty::RegionTraitStore(r), m, _) => { + Some(deref_ptr(region_ptr(m, r))) + } + ty::ty_estr(ty::vstore_slice(r)) | ty::ty_closure(ty::ClosureTy {sigil: ast::BorrowedSigil, region: r, _}) => { Some(deref_ptr(region_ptr(ast::m_imm, r))) } - ty::ty_box(mt) | - ty::ty_evec(mt, ty::vstore_box) => { + ty::ty_box(ref mt) | + ty::ty_evec(ref mt, ty::vstore_box) => { Some(deref_ptr(gc_ptr(mt.mutbl))) } + ty::ty_trait(_, _, ty::BoxTraitStore, m, _) => { + Some(deref_ptr(gc_ptr(m))) + } + ty::ty_estr(ty::vstore_box) | ty::ty_closure(ty::ClosureTy {sigil: ast::ManagedSigil, _}) => { Some(deref_ptr(gc_ptr(ast::m_imm))) } - ty::ty_ptr(*) => { - Some(deref_ptr(unsafe_ptr)) + ty::ty_ptr(ref mt) => { + Some(deref_ptr(unsafe_ptr(mt.mutbl))) } ty::ty_enum(*) | @@ -631,20 +637,19 @@ impl mem_categorization_ctxt { } } - pub fn cat_deref_fn(&self, - node: N, - base_cmt: cmt, - deref_cnt: uint) - -> cmt { + pub fn cat_deref_fn_or_obj(&self, + node: N, + base_cmt: cmt, + deref_cnt: uint) + -> cmt { // Bit of a hack: the "dereference" of a function pointer like // `@fn()` is a mere logical concept. We interpret it as // dereferencing the environment pointer; of course, we don't // know what type lies at the other end, so we just call it // `()` (the empty tuple). - let mt = ty::mt {ty: ty::mk_tup(self.tcx, ~[]), - mutbl: m_imm}; - return self.cat_deref_common(node, base_cmt, deref_cnt, mt); + let opaque_ty = ty::mk_tup(self.tcx, ~[]); + return self.cat_deref_common(node, base_cmt, deref_cnt, opaque_ty); } pub fn cat_deref(&self, @@ -662,25 +667,25 @@ impl mem_categorization_ctxt { } }; - return self.cat_deref_common(node, base_cmt, deref_cnt, mt); + return self.cat_deref_common(node, base_cmt, deref_cnt, mt.ty); } pub fn cat_deref_common(&self, node: N, base_cmt: cmt, deref_cnt: uint, - mt: ty::mt) + deref_ty: ty::t) -> cmt { match deref_kind(self.tcx, base_cmt.ty) { deref_ptr(ptr) => { // for unique ptrs, we inherit mutability from the // owning reference. let m = match ptr { - uniq_ptr(*) => { - self.inherited_mutability(base_cmt.mutbl, mt.mutbl) + uniq_ptr => { + base_cmt.mutbl.inherit() } - gc_ptr(*) | region_ptr(_, _) | unsafe_ptr => { - MutabilityCategory::from_mutbl(mt.mutbl) + gc_ptr(m) | region_ptr(m, _) | unsafe_ptr(m) => { + MutabilityCategory::from_mutbl(m) } }; @@ -689,18 +694,18 @@ impl mem_categorization_ctxt { span:node.span(), cat:cat_deref(base_cmt, deref_cnt, ptr), mutbl:m, - ty:mt.ty + ty:deref_ty } } deref_interior(interior) => { - let m = self.inherited_mutability(base_cmt.mutbl, mt.mutbl); + let m = base_cmt.mutbl.inherit(); @cmt_ { id:node.id(), span:node.span(), cat:cat_interior(base_cmt, interior), mutbl:m, - ty:mt.ty + ty:deref_ty } } } @@ -742,8 +747,8 @@ impl mem_categorization_ctxt { //! - `derefs`: the deref number to be used for //! the implicit index deref, if any (see above) - let mt = match ty::index(base_cmt.ty) { - Some(mt) => mt, + let element_ty = match ty::index(base_cmt.ty) { + Some(ref mt) => mt.ty, None => { self.tcx.sess.span_bug( elt.span(), @@ -757,11 +762,11 @@ impl mem_categorization_ctxt { // for unique ptrs, we inherit mutability from the // owning reference. let m = match ptr { - uniq_ptr(*) => { - self.inherited_mutability(base_cmt.mutbl, mt.mutbl) + uniq_ptr => { + base_cmt.mutbl.inherit() } - gc_ptr(_) | region_ptr(_, _) | unsafe_ptr => { - MutabilityCategory::from_mutbl(mt.mutbl) + gc_ptr(m) | region_ptr(m, _) | unsafe_ptr(m) => { + MutabilityCategory::from_mutbl(m) } }; @@ -771,16 +776,16 @@ impl mem_categorization_ctxt { span:elt.span(), cat:cat_deref(base_cmt, derefs, ptr), mutbl:m, - ty:mt.ty + ty:element_ty }; - interior(elt, deref_cmt, base_cmt.ty, m, mt) + interior(elt, deref_cmt, base_cmt.ty, m, element_ty) } deref_interior(_) => { // fixed-length vectors have no deref - let m = self.inherited_mutability(base_cmt.mutbl, mt.mutbl); - interior(elt, base_cmt, base_cmt.ty, m, mt) + let m = base_cmt.mutbl.inherit(); + interior(elt, base_cmt, base_cmt.ty, m, element_ty) } }; @@ -788,14 +793,14 @@ impl mem_categorization_ctxt { of_cmt: cmt, vec_ty: ty::t, mutbl: MutabilityCategory, - mt: ty::mt) -> cmt + element_ty: ty::t) -> cmt { @cmt_ { id:elt.id(), span:elt.span(), cat:cat_interior(of_cmt, InteriorElement(element_kind(vec_ty))), mutbl:mutbl, - ty:mt.ty + ty:element_ty } } } @@ -1130,7 +1135,7 @@ impl cmt_ { cat_stack_upvar(b) | cat_discr(b, _) | cat_interior(b, _) | - cat_deref(b, _, uniq_ptr(*)) => { + cat_deref(b, _, uniq_ptr) => { b.guarantor() } } @@ -1177,7 +1182,7 @@ impl cmt_ { cat_downcast(b) | cat_stack_upvar(b) | - cat_deref(b, _, uniq_ptr(*)) | + cat_deref(b, _, uniq_ptr) | cat_interior(b, _) | cat_discr(b, _) => { b.freely_aliasable() @@ -1230,10 +1235,10 @@ impl Repr for categorization { pub fn ptr_sigil(ptr: ptr_kind) -> ~str { match ptr { - uniq_ptr(_) => ~"~", + uniq_ptr => ~"~", gc_ptr(_) => ~"@", region_ptr(_, _) => ~"&", - unsafe_ptr => ~"*" + unsafe_ptr(_) => ~"*" } } From df016dc4bf2efd3f4e0f9d67dda1875453c705b2 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 11 Aug 2013 13:58:01 -0400 Subject: [PATCH 10/12] Update type visitor to use &Visitor and not @Visitor --- src/librustc/middle/trans/glue.rs | 3 ++- src/librustc/middle/trans/reflect.rs | 6 +----- src/librustc/middle/ty.rs | 9 ++++----- src/librustc/middle/typeck/check/mod.rs | 3 ++- src/libstd/repr.rs | 24 ++++++++++++++++++++++++ src/libstd/unstable/intrinsics.rs | 4 ++++ 6 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index c65d8d31b741b..4f894deb1a1c1 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -348,7 +348,8 @@ pub fn make_visit_glue(bcx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block { let _icx = push_ctxt("make_visit_glue"); do with_scope(bcx, None, "visitor cleanup") |bcx| { let mut bcx = bcx; - let (visitor_trait, object_ty) = match ty::visitor_object_ty(bcx.tcx()){ + let (visitor_trait, object_ty) = match ty::visitor_object_ty(bcx.tcx(), + ty::re_static) { Ok(pair) => pair, Err(s) => { bcx.tcx().sess.fatal(s); diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index e0403ac9ad7a8..fe5f8cd70ef19 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -100,17 +100,13 @@ impl Reflector { debug!("arg %u: %s", i, bcx.val_to_str(*a)); } let bool_ty = ty::mk_bool(); - // XXX: Should not be BoxTraitStore! let result = unpack_result!(bcx, callee::trans_call_inner( self.bcx, None, mth_ty, bool_ty, |bcx| meth::trans_trait_callee_from_llval(bcx, mth_ty, mth_idx, v, - ty::BoxTraitStore, - ast::sty_region( - None, - ast::m_imm)), + None), ArgVals(args), None, DontAutorefArg)); let result = bool_to_i1(bcx, result); let next_bcx = sub_block(bcx, "next"); diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 14d3a92623110..2ba6930d9c5ea 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -4487,7 +4487,8 @@ pub fn get_opaque_ty(tcx: ctxt) -> Result { } } -pub fn visitor_object_ty(tcx: ctxt) -> Result<(@TraitRef, t), ~str> { +pub fn visitor_object_ty(tcx: ctxt, + region: ty::Region) -> Result<(@TraitRef, t), ~str> { let trait_lang_item = match tcx.lang_items.require(TyVisitorTraitLangItem) { Ok(id) => id, Err(s) => { return Err(s); } @@ -4498,13 +4499,11 @@ pub fn visitor_object_ty(tcx: ctxt) -> Result<(@TraitRef, t), ~str> { tps: ~[] }; let trait_ref = @TraitRef { def_id: trait_lang_item, substs: substs }; - let mut static_trait_bound = EmptyBuiltinBounds(); - static_trait_bound.add(BoundStatic); Ok((trait_ref, mk_trait(tcx, trait_ref.def_id, trait_ref.substs.clone(), - BoxTraitStore, + RegionTraitStore(region), ast::m_imm, - static_trait_bound))) + EmptyBuiltinBounds()))) } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 8bc3241256875..a125dd2777743 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -3437,7 +3437,8 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) { Ok(t) => t, Err(s) => { tcx.sess.span_fatal(it.span, s); } }; - let visitor_object_ty = match ty::visitor_object_ty(tcx) { + let region = ty::re_bound(ty::br_anon(0)); + let visitor_object_ty = match ty::visitor_object_ty(tcx, region) { Ok((_, vot)) => vot, Err(s) => { tcx.sess.span_fatal(it.span, s); } }; diff --git a/src/libstd/repr.rs b/src/libstd/repr.rs index a53e3e796a790..d0970f1b6b7ad 100644 --- a/src/libstd/repr.rs +++ b/src/libstd/repr.rs @@ -158,6 +158,7 @@ impl ReprVisitor { } #[inline] + #[cfg(stage0)] pub fn visit_ptr_inner(&self, ptr: *c_void, inner: *TyDesc) -> bool { unsafe { let u = ReprVisitor(ptr, self.writer); @@ -167,6 +168,17 @@ impl ReprVisitor { } } + #[inline] + #[cfg(not(stage0))] + pub fn visit_ptr_inner(&self, ptr: *c_void, inner: *TyDesc) -> bool { + unsafe { + let u = ReprVisitor(ptr, self.writer); + let v = reflect::MovePtrAdaptor(u); + visit_tydesc(inner, &v as &TyVisitor); + true + } + } + #[inline] pub fn write(&self) -> bool { do self.get |v:&T| { @@ -556,6 +568,7 @@ impl TyVisitor for ReprVisitor { fn visit_closure_ptr(&self, _ck: uint) -> bool { true } } +#[cfg(stage0)] pub fn write_repr(writer: @Writer, object: &T) { unsafe { let ptr = ptr::to_unsafe_ptr(object) as *c_void; @@ -566,6 +579,17 @@ pub fn write_repr(writer: @Writer, object: &T) { } } +#[cfg(not(stage0))] +pub fn write_repr(writer: @Writer, object: &T) { + unsafe { + let ptr = ptr::to_unsafe_ptr(object) as *c_void; + let tydesc = get_tydesc::(); + let u = ReprVisitor(ptr, writer); + let v = reflect::MovePtrAdaptor(u); + visit_tydesc(tydesc, &v as &TyVisitor) + } +} + #[cfg(test)] struct P {a: int, b: float} diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs index d2807303fb21c..1b7b240f01aa2 100644 --- a/src/libstd/unstable/intrinsics.rs +++ b/src/libstd/unstable/intrinsics.rs @@ -328,8 +328,12 @@ extern "rust-intrinsic" { /// Returns `true` if a type is managed (will be allocated on the local heap) pub fn contains_managed() -> bool; + #[cfg(stage0)] pub fn visit_tydesc(td: *TyDesc, tv: @TyVisitor); + #[cfg(not(stage0))] + pub fn visit_tydesc(td: *TyDesc, tv: &TyVisitor); + pub fn frame_address(f: &once fn(*u8)); /// Get the address of the `__morestack` stack growth function. From b402e343e4976d0993d8735e8b1c678f7da11f75 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 11 Aug 2013 13:58:48 -0400 Subject: [PATCH 11/12] tests: Add new tests for borrowck/objects and update some existing tests --- .../borrowck-borrow-mut-object-twice.rs} | 23 +++---- .../compile-fail/borrowck-object-lifetime.rs | 42 ++++++++++++ .../borrowck-object-mutability.rs | 47 ++++++++++++++ .../kindck-owned-trait-contains.rs | 1 - src/test/compile-fail/object-pointer-types.rs | 64 +++++++++++++++++++ src/test/compile-fail/selftype-traittype.rs | 2 +- src/test/run-fail/borrowck-wg-fail-object.rs | 21 ++++++ src/test/run-pass/class-cast-to-trait.rs | 2 +- ...cts-owned-object-borrowed-method-header.rs | 39 +++++++++++ ...wned-object-borrowed-method-headerless.rs} | 4 ++ .../objects-owned-object-owned-method.rs | 32 ++++++++++ src/test/run-pass/reflect-visit-data.rs | 4 +- src/test/run-pass/reflect-visit-type.rs | 6 +- 13 files changed, 265 insertions(+), 22 deletions(-) rename src/test/{run-pass/unique-object.rs => compile-fail/borrowck-borrow-mut-object-twice.rs} (62%) create mode 100644 src/test/compile-fail/borrowck-object-lifetime.rs create mode 100644 src/test/compile-fail/borrowck-object-mutability.rs create mode 100644 src/test/compile-fail/object-pointer-types.rs create mode 100644 src/test/run-fail/borrowck-wg-fail-object.rs create mode 100644 src/test/run-pass/objects-owned-object-borrowed-method-header.rs rename src/test/run-pass/{owned-trait-objects.rs => objects-owned-object-borrowed-method-headerless.rs} (84%) create mode 100644 src/test/run-pass/objects-owned-object-owned-method.rs diff --git a/src/test/run-pass/unique-object.rs b/src/test/compile-fail/borrowck-borrow-mut-object-twice.rs similarity index 62% rename from src/test/run-pass/unique-object.rs rename to src/test/compile-fail/borrowck-borrow-mut-object-twice.rs index e645f13cd4c51..502d7e017b5b1 100644 --- a/src/test/run-pass/unique-object.rs +++ b/src/test/compile-fail/borrowck-borrow-mut-object-twice.rs @@ -8,22 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Foo { - fn f(&self) -> int; -} +// Check that `&mut` objects cannot be borrowed twice, just like +// other `&mut` pointers. -struct Bar { - x: int +trait Foo { + fn f1<'a>(&'a mut self) -> &'a (); + fn f2(&mut self); } -impl Foo for Bar { - fn f(&self) -> int { - self.x - } +fn test(x: &mut Foo) { + let _y = x.f1(); + x.f2(); //~ ERROR cannot borrow `*x` as mutable more than once at a time } -pub fn main() { - let x = ~Bar { x: 10 }; - let y = x as ~Foo; - assert_eq!(y.f(), 10); -} +fn main() {} diff --git a/src/test/compile-fail/borrowck-object-lifetime.rs b/src/test/compile-fail/borrowck-object-lifetime.rs new file mode 100644 index 0000000000000..25d5be7ed55d3 --- /dev/null +++ b/src/test/compile-fail/borrowck-object-lifetime.rs @@ -0,0 +1,42 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Foo { + fn borrowed<'a>(&'a self) -> &'a (); +} + +fn borrowed_receiver<'a>(x: &'a Foo) -> &'a () { + x.borrowed() +} + +fn managed_receiver(x: @Foo) -> &() { + x.borrowed() //~ ERROR cannot root managed value long enough +} + +fn managed_receiver_1(x: @Foo) { + *x.borrowed() +} + +fn owned_receiver(x: ~Foo) -> &() { + x.borrowed() //~ ERROR borrowed value does not live long enough +} + +fn mut_owned_receiver(mut x: ~Foo) { + let _y = x.borrowed(); + let _z = &mut x; //~ ERROR cannot borrow +} + +fn imm_owned_receiver(mut x: ~Foo) { + let _y = x.borrowed(); + let _z = &x; +} + +fn main() {} + diff --git a/src/test/compile-fail/borrowck-object-mutability.rs b/src/test/compile-fail/borrowck-object-mutability.rs new file mode 100644 index 0000000000000..1ea9e3c8815a8 --- /dev/null +++ b/src/test/compile-fail/borrowck-object-mutability.rs @@ -0,0 +1,47 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Foo { + fn borrowed(&self); + fn borrowed_mut(&mut self); +} + +fn borrowed_receiver(x: &Foo) { + x.borrowed(); + x.borrowed_mut(); //~ ERROR cannot borrow +} + +fn borrowed_mut_receiver(x: &mut Foo) { + x.borrowed(); + x.borrowed_mut(); +} + +fn managed_receiver(x: @Foo) { + x.borrowed(); + x.borrowed_mut(); //~ ERROR cannot borrow +} + +fn managed_mut_receiver(x: @mut Foo) { + x.borrowed(); + x.borrowed_mut(); +} + +fn owned_receiver(x: ~Foo) { + x.borrowed(); + x.borrowed_mut(); //~ ERROR cannot borrow +} + +fn mut_owned_receiver(mut x: ~Foo) { + x.borrowed(); + x.borrowed_mut(); +} + +fn main() {} + diff --git a/src/test/compile-fail/kindck-owned-trait-contains.rs b/src/test/compile-fail/kindck-owned-trait-contains.rs index 19b38769d9569..cf047674cd6c8 100644 --- a/src/test/compile-fail/kindck-owned-trait-contains.rs +++ b/src/test/compile-fail/kindck-owned-trait-contains.rs @@ -31,5 +31,4 @@ fn main() { //~^ ERROR dereference of reference outside its lifetime //~^^ ERROR automatically borrowed pointer is not valid at the time of borrow //~^^^ ERROR lifetime of return value does not outlive the function call - //~^^^^ ERROR cannot infer an appropriate lifetime } diff --git a/src/test/compile-fail/object-pointer-types.rs b/src/test/compile-fail/object-pointer-types.rs new file mode 100644 index 0000000000000..b7d320fbab0ca --- /dev/null +++ b/src/test/compile-fail/object-pointer-types.rs @@ -0,0 +1,64 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Foo { + fn borrowed(&self); + fn borrowed_mut(&mut self); + + fn managed(@self); + fn managed_mut(@mut self); + + fn owned(~self); +} + +fn borrowed_receiver(x: &Foo) { + x.borrowed(); + x.borrowed_mut(); // See [1] + x.managed(); //~ ERROR does not implement any method + x.managed_mut(); //~ ERROR does not implement any method + x.owned(); //~ ERROR does not implement any method +} + +fn borrowed_mut_receiver(x: &mut Foo) { + x.borrowed(); + x.borrowed_mut(); + x.managed(); //~ ERROR does not implement any method + x.managed_mut(); //~ ERROR does not implement any method + x.owned(); //~ ERROR does not implement any method +} + +fn managed_receiver(x: @Foo) { + x.borrowed(); + x.borrowed_mut(); // See [1] + x.managed(); + x.managed_mut(); //~ ERROR does not implement any method + x.owned(); //~ ERROR does not implement any method +} + +fn managed_mut_receiver(x: @mut Foo) { + x.borrowed(); + x.borrowed_mut(); + x.managed(); //~ ERROR does not implement any method + x.managed_mut(); + x.owned(); //~ ERROR does not implement any method +} + +fn owned_receiver(x: ~Foo) { + x.borrowed(); + x.borrowed_mut(); // See [1] + x.managed(); //~ ERROR does not implement any method + x.managed_mut(); //~ ERROR does not implement any method + x.owned(); +} + +fn main() {} + +// [1]: These cases are illegal, but the error is not detected +// until borrowck, so see the test borrowck-object-mutability.rs diff --git a/src/test/compile-fail/selftype-traittype.rs b/src/test/compile-fail/selftype-traittype.rs index 220573660c5b0..b5484b786a022 100644 --- a/src/test/compile-fail/selftype-traittype.rs +++ b/src/test/compile-fail/selftype-traittype.rs @@ -13,7 +13,7 @@ trait add { } fn do_add(x: @add, y: @add) -> @add { - x.plus(y) //~ ERROR cannot call a method whose type contains a self-type through a boxed trait + x.plus(y) //~ ERROR cannot call a method whose type contains a self-type through an object } fn main() {} diff --git a/src/test/run-fail/borrowck-wg-fail-object.rs b/src/test/run-fail/borrowck-wg-fail-object.rs new file mode 100644 index 0000000000000..73f2cf0955228 --- /dev/null +++ b/src/test/run-fail/borrowck-wg-fail-object.rs @@ -0,0 +1,21 @@ +// error-pattern:borrowed + +trait Foo { + fn foo(&self, @mut int); +} + +impl Foo for int { + fn foo(&self, x: @mut int) { + *x += *self; + } +} + +fn main() { + let x = @mut 3_i; + let y = x as @mut Foo; + + // The call to `y.foo(...)` should freeze `y` (and thus also `x`, + // since `x === y`). It is thus an error when `foo` tries to + // mutate `x`. + y.foo(x); +} diff --git a/src/test/run-pass/class-cast-to-trait.rs b/src/test/run-pass/class-cast-to-trait.rs index a8ff906121687..737253a956fc0 100644 --- a/src/test/run-pass/class-cast-to-trait.rs +++ b/src/test/run-pass/class-cast-to-trait.rs @@ -56,6 +56,6 @@ fn cat(in_x : uint, in_y : int, in_name: ~str) -> cat { pub fn main() { - let mut nyan: @noisy = @cat(0u, 2, ~"nyan") as @noisy; + let nyan: @mut noisy = @mut cat(0u, 2, ~"nyan") as @mut noisy; nyan.speak(); } diff --git a/src/test/run-pass/objects-owned-object-borrowed-method-header.rs b/src/test/run-pass/objects-owned-object-borrowed-method-header.rs new file mode 100644 index 0000000000000..23c271f53cac8 --- /dev/null +++ b/src/test/run-pass/objects-owned-object-borrowed-method-header.rs @@ -0,0 +1,39 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test invoked `&self` methods on owned objects where the values +// closed over contain managed values. This implies that the ~ boxes +// will have headers that must be skipped over. + +trait FooTrait { + fn foo(&self) -> uint; +} + +struct BarStruct { + x: @uint +} + +impl FooTrait for BarStruct { + fn foo(&self) -> uint { + *self.x + } +} + +pub fn main() { + let foos: ~[ ~FooTrait: ] = ~[ + ~BarStruct{ x: @0 } as ~FooTrait:, + ~BarStruct{ x: @1 } as ~FooTrait:, + ~BarStruct{ x: @2 } as ~FooTrait: + ]; + + for i in range(0u, foos.len()) { + assert_eq!(i, foos[i].foo()); + } +} diff --git a/src/test/run-pass/owned-trait-objects.rs b/src/test/run-pass/objects-owned-object-borrowed-method-headerless.rs similarity index 84% rename from src/test/run-pass/owned-trait-objects.rs rename to src/test/run-pass/objects-owned-object-borrowed-method-headerless.rs index c9d0fde6d3c2f..72ae7cf9bb993 100644 --- a/src/test/run-pass/owned-trait-objects.rs +++ b/src/test/run-pass/objects-owned-object-borrowed-method-headerless.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Test invoked `&self` methods on owned objects where the values +// closed over do not contain managed values, and thus the ~ boxes do +// not have headers. + trait FooTrait { fn foo(&self) -> uint; } diff --git a/src/test/run-pass/objects-owned-object-owned-method.rs b/src/test/run-pass/objects-owned-object-owned-method.rs new file mode 100644 index 0000000000000..0d675c16d1aad --- /dev/null +++ b/src/test/run-pass/objects-owned-object-owned-method.rs @@ -0,0 +1,32 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test invoked `&self` methods on owned objects where the values +// closed over contain managed values. This implies that the ~ boxes +// will have headers that must be skipped over. + +trait FooTrait { + fn foo(~self) -> uint; +} + +struct BarStruct { + x: uint +} + +impl FooTrait for BarStruct { + fn foo(~self) -> uint { + self.x + } +} + +pub fn main() { + let foo = ~BarStruct{ x: 22 } as ~FooTrait; + assert_eq!(22, foo.foo()); +} diff --git a/src/test/run-pass/reflect-visit-data.rs b/src/test/run-pass/reflect-visit-data.rs index 2a91d1fc8b5ca..8ab1bef286c0c 100644 --- a/src/test/run-pass/reflect-visit-data.rs +++ b/src/test/run-pass/reflect-visit-data.rs @@ -502,7 +502,7 @@ impl my_visitor { unsafe { let u = my_visitor(**self); let v = ptr_visit_adaptor::(Inner {inner: u}); - visit_tydesc(inner, @v as @TyVisitor); + visit_tydesc(inner, &v as &TyVisitor); true } } @@ -662,7 +662,7 @@ pub fn main() { let td = get_tydesc_for(r); error!("tydesc sz: %u, align: %u", (*td).size, (*td).align); - let v = @v as @TyVisitor; + let v = &v as &TyVisitor; visit_tydesc(td, v); let r = u.vals.clone(); diff --git a/src/test/run-pass/reflect-visit-type.rs b/src/test/run-pass/reflect-visit-type.rs index 3ea597e0d59e3..544f42eb69f5e 100644 --- a/src/test/run-pass/reflect-visit-type.rs +++ b/src/test/run-pass/reflect-visit-type.rs @@ -79,7 +79,7 @@ impl TyVisitor for MyVisitor { fn visit_evec_uniq(&self, _mtbl: uint, inner: *TyDesc) -> bool { self.types.push(~"["); unsafe { - visit_tydesc(inner, (@*self) as @TyVisitor); + visit_tydesc(inner, (&*self) as &TyVisitor); } self.types.push(~"]"); true @@ -87,7 +87,7 @@ impl TyVisitor for MyVisitor { fn visit_evec_uniq_managed(&self, _mtbl: uint, inner: *TyDesc) -> bool { self.types.push(~"["); unsafe { - visit_tydesc(inner, (@*self) as @TyVisitor); + visit_tydesc(inner, (&*self) as &TyVisitor); } self.types.push(~"]"); true @@ -154,7 +154,7 @@ impl TyVisitor for MyVisitor { fn visit_closure_ptr(&self, _ck: uint) -> bool { true } } -fn visit_ty(v: @TyVisitor) { +fn visit_ty(v: &TyVisitor) { unsafe { visit_tydesc(get_tydesc::(), v); } From 7343478d67ba3eb0c62dcc37db65d82d12b8e140 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 11 Aug 2013 14:56:43 -0400 Subject: [PATCH 12/12] Convert from transform to map --- src/librustc/middle/trans/context.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs index aa56ff3d26e80..187c121bbd337 100644 --- a/src/librustc/middle/trans/context.rs +++ b/src/librustc/middle/trans/context.rs @@ -246,7 +246,7 @@ impl CrateContext { debug!("const_inbounds_gepi: pointer=%s indices=%?", self.tn.val_to_str(pointer), indices); let v: ~[ValueRef] = - indices.iter().transform(|i| C_i32(*i as i32)).collect(); + indices.iter().map(|i| C_i32(*i as i32)).collect(); unsafe { llvm::LLVMConstInBoundsGEP(pointer, vec::raw::to_ptr(v),