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/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/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/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/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/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(_) => ~"*" } } 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/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/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/common.rs b/src/librustc/middle/trans/common.rs index 40a83eb977078..bf3dea06ee260 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, @@ -686,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/context.rs b/src/librustc/middle/trans/context.rs index a644174731ab4..187c121bbd337 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}; @@ -236,6 +239,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().map(|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/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/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); diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index a70b907f2628c..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); @@ -655,6 +656,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 +683,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 +799,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/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) */ }) }; } 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/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 bba5d85083b70..2ba6930d9c5ea 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, @@ -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), } } } @@ -3101,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. @@ -4457,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); } @@ -4468,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/method.rs b/src/librustc/middle/typeck/check/method.rs index 84e5d8f9bf743..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 { @@ -247,7 +264,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 +279,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 @@ -275,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); @@ -307,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. @@ -328,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)); @@ -346,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=%?)", @@ -403,7 +430,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 +440,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) { @@ -433,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, @@ -459,7 +486,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 +496,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) { @@ -502,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) @@ -512,7 +539,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 +558,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 @@ -579,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 { @@ -598,7 +635,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 { @@ -608,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) @@ -655,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 } @@ -664,7 +714,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 +746,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 +775,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 +803,7 @@ impl<'self> LookupContext<'self> { } } - pub fn consider_candidates(&self, + fn consider_candidates(&self, rcvr_ty: ty::t, candidates: &mut ~[Candidate]) -> Option { @@ -780,7 +830,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 +876,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); @@ -836,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(); @@ -950,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(*) => { @@ -975,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 { @@ -999,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); } } @@ -1012,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) => { @@ -1056,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 @@ -1068,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 @@ -1079,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 @@ -1088,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 { @@ -1108,7 +1235,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 @@ -1116,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) } }; @@ -1129,7 +1256,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) @@ -1137,13 +1264,13 @@ 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) } } } - 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 +1286,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 +1294,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 +1303,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) } } @@ -1210,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/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/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) } } } 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 c60edad3dbd56..1b7b240f01aa2 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"] @@ -310,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. 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) } } 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 }; // 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); }