auto merge of #8455 : nikomatsakis/rust/issue-5762-objects-dralston-d, r=graydon

Fix #5762 and various other aspects of object invocation.

r? @graydon
This commit is contained in:
bors 2013-08-11 14:17:09 -07:00
commit b285f1e6c9
65 changed files with 1154 additions and 559 deletions

View File

@ -46,7 +46,8 @@
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;

View File

@ -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,

View File

@ -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<EntryFnType>,
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 @@ pub fn add_lint(@self,
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 {

View File

@ -29,7 +29,7 @@
// 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,

View File

@ -55,7 +55,7 @@
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<ast::NodeId, ~str>,
@ -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,

View File

@ -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() {

View File

@ -25,7 +25,7 @@
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.

View File

@ -586,8 +586,8 @@ fn tr(&self, xcx: @ExtendedDecodeContext) -> 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)
}
}
}

View File

@ -362,7 +362,7 @@ fn mark_variable_as_used_mut(this: &CheckLoanCtxt,
}
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;
}

View File

@ -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)
}

View File

@ -74,7 +74,7 @@ fn check(&self, cmt: mc::cmt, discr_scope: Option<ast::NodeId>) {
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 @@ fn check(&self, cmt: mc::cmt, discr_scope: Option<ast::NodeId>) {
}
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 @@ fn scope(&self, cmt: mc::cmt) -> ty::Region {
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) |

View File

@ -352,13 +352,21 @@ pub fn guarantee_adjustments(&mut self,
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(_) => {}
}
}

View File

@ -101,7 +101,7 @@ fn restrict(&self,
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 @@ fn restrict(&self,
}
}
mc::cat_deref(_, _, mc::unsafe_ptr) => {
mc::cat_deref(_, _, mc::unsafe_ptr(*)) => {
// We are very trusting when working with unsafe pointers.
Safe
}

View File

@ -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 @@ fn add_oldvisit_lint(&mut self, v: oldvisit::vt<@mut 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 visit_fn_decl(cx: &Context, fd: &ast::fn_decl) {
})
}
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 => {},

View File

@ -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<deref_kind> {
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<deref_kind> {
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 @@ pub fn cat_field<N:ast_node>(&self,
}
}
pub fn cat_deref_fn<N:ast_node>(&self,
node: N,
base_cmt: cmt,
deref_cnt: uint)
-> cmt {
pub fn cat_deref_fn_or_obj<N:ast_node>(&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<N:ast_node>(&self,
@ -662,25 +667,25 @@ pub fn cat_deref<N:ast_node>(&self,
}
};
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<N:ast_node>(&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 @@ pub fn cat_deref_common<N:ast_node>(&self,
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 @@ pub fn cat_index<N:ast_node>(&self,
//! - `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 @@ pub fn cat_index<N:ast_node>(&self,
// 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 @@ pub fn cat_index<N:ast_node>(&self,
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 @@ fn interior<N: ast_node>(elt: N,
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 @@ pub fn guarantor(@self) -> 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 @@ pub fn freely_aliasable(&self) -> Option<AliasableReason> {
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 @@ fn repr(&self, tcx: ty::ctxt) -> ~str {
pub fn ptr_sigil(ptr: ptr_kind) -> ~str {
match ptr {
uniq_ptr(_) => ~"~",
uniq_ptr => ~"~",
gc_ptr(_) => ~"@",
region_ptr(_, _) => ~"&",
unsafe_ptr => ~"*"
unsafe_ptr(_) => ~"*"
}
}

View File

@ -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, _)) => {

View File

@ -2405,12 +2405,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 {

View File

@ -60,7 +60,6 @@ pub struct MethodData {
llfn: ValueRef,
llself: ValueRef,
temp_cleanup: Option<ValueRef>,
self_ty: ty::t,
self_mode: ty::SelfMode,
}

View File

@ -54,6 +54,7 @@ pub struct tydesc_info {
tydesc: ValueRef,
size: ValueRef,
align: ValueRef,
borrow_offset: ValueRef,
take_glue: Option<ValueRef>,
drop_glue: Option<ValueRef>,
free_glue: Option<ValueRef>,
@ -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 {

View File

@ -13,7 +13,7 @@
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::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::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 @@ pub fn new(sess: session::Session,
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]

View File

@ -137,9 +137,8 @@
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 @@ fn auto_slice_and_ref(bcx: @mut Block,
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 {

View File

@ -857,8 +857,6 @@ fn count_zeros_intrinsic(bcx: @mut Block, name: &'static str) {
"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);

View File

@ -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;

View File

@ -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<ValueRef>)
-> 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) */
})
};
}

View File

@ -100,17 +100,13 @@ pub fn visit(&mut self, ty_name: &str, args: &[ValueRef]) {
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");

View File

@ -205,10 +205,18 @@ pub fn tydesc(arch: Architecture) -> 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 @@ pub fn box(ctx: &CrateContext, ty: &Type) -> 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 {

View File

@ -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<intern_key, ~t_box_>,
next_id: @mut uint,
cstore: @mut metadata::cstore::CStore,
@ -1004,7 +1007,13 @@ fn sflags(substs: &substs) -> uint {
&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 @@ fn borrow_fn(cx: ctxt, span: span, r: Region, ty: ty::t) -> ty::t {
}
}
}
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 @@ pub fn map_region(&self, f: &fn(Region) -> Region) -> 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<t, ~str> {
}
}
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())))
}

View File

@ -94,6 +94,7 @@ trait `ToStr` imported, and I call `to_str()` on a value of type `T`,
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,
}
/// 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> {
pub fn do_lookup(&self, self_ty: ty::t) -> Option<method_map_entry> {
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();
fn search(&self, self_ty: ty::t) -> Option<method_map_entry> {
let mut self_ty = self_ty;
let mut autoderefs = 0;
loop {
@ -247,7 +264,7 @@ pub fn do_lookup(&self, self_ty: ty::t) -> Option<method_map_entry> {
self.search_for_autosliced_method(self_ty, autoderefs)
}
pub fn deref(&self, ty: ty::t)
fn deref(&self, ty: ty::t)
-> Option<ty::t> {
match ty::deref(self.tcx(), ty, false) {
None => None,
@ -262,7 +279,12 @@ pub fn deref(&self, ty: ty::t)
// ______________________________________________________________________
// 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 @@ pub fn push_inherent_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_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 @@ pub fn push_inherent_candidates(&self, self_ty: ty::t) {
}
}
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 @@ pub fn push_extension_candidates(&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 @@ pub fn push_inherent_candidates_from_trait(&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 @@ pub fn push_inherent_candidates_from_param(&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 @@ pub fn push_inherent_candidates_from_self(&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 @@ pub fn push_inherent_candidates_from_bounds(&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 @@ pub fn push_inherent_candidates_from_bounds(&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 @@ pub fn push_inherent_impl_candidates_for_type(&self, did: def_id) {
}
}
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 @@ pub fn push_candidates_from_impl(&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 @@ pub fn push_candidates_from_impl(&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<method_map_entry> {
@ -531,12 +558,11 @@ pub fn search_for_autoderefd_method(&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 @@ pub fn consider_reborrow(&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 @@ fn default_method_hack(self_mt: ty::mt) -> bool {
}
}
pub fn search_for_autosliced_method(&self,
fn search_for_autosliced_method(&self,
self_ty: ty::t,
autoderefs: uint)
-> Option<method_map_entry> {
@ -608,7 +645,8 @@ pub fn search_for_autosliced_method(&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 @@ pub fn search_for_autosliced_method(&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 @@ pub fn search_for_autosliced_method(&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<method_map_entry> {
/*!
*
@ -696,7 +746,7 @@ pub fn search_for_autoptrd_method(&self, self_ty: ty::t, autoderefs: uint)
}
}
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 @@ pub fn search_for_some_kind_of_autorefd_method(
return None;
}
pub fn search_for_method(&self, rcvr_ty: ty::t)
fn search_for_method(&self, rcvr_ty: ty::t)
-> Option<method_map_entry> {
debug!("search_for_method(rcvr_ty=%s)", self.ty_to_str(rcvr_ty));
let _indenter = indenter();
@ -753,7 +803,7 @@ pub fn search_for_method(&self, rcvr_ty: ty::t)
}
}
pub fn consider_candidates(&self,
fn consider_candidates(&self,
rcvr_ty: ty::t,
candidates: &mut ~[Candidate])
-> Option<method_map_entry> {
@ -780,7 +830,7 @@ pub fn consider_candidates(&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 @@ pub fn merge_candidates(&self, candidates: &[Candidate]) -> ~[Candidate] {
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 @@ pub fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)
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 @@ pub fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)
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
*
* There are some limitations to calling functions through a
* trait instance, because (a) the self type is not known
* trait Foo {
* fn r_method<'a>(&'a self);
* fn m_method(@mut self);
* }
*
* 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 @@ pub fn enforce_trait_instance_limitations(&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 @@ pub fn enforce_drop_trait_limitations(&self, candidate: &Candidate) {
// 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 @@ pub fn enforce_drop_trait_limitations(&self, candidate: &Candidate) {
// `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 @@ pub fn is_relevant(&self, rcvr_ty: ty::t, candidate: &Candidate) -> bool {
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 @@ pub fn is_relevant(&self, rcvr_ty: ty::t, candidate: &Candidate) -> bool {
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 @@ pub fn is_relevant(&self, rcvr_ty: ty::t, candidate: &Candidate) -> bool {
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 @@ pub fn is_relevant(&self, rcvr_ty: ty::t, candidate: &Candidate) -> bool {
}
};
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 @@ fn mutability_matches(self_mutbl: ast::mutability,
}
}
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 @@ pub fn fn_ty_from_origin(&self, origin: &method_origin) -> ty::t {
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 @@ fn type_of_trait_method(tcx: ty::ctxt,
}
}
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 @@ pub fn report_candidate(&self, idx: uint, origin: &method_origin) {
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 @@ pub fn report_static_candidate(&self, idx: uint, did: def_id) {
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 @@ pub fn report_param_candidate(&self, idx: uint, did: def_id) {
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 @@ pub fn report_trait_candidate(&self, idx: uint, did: def_id) {
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))
}
}
}
}

View File

@ -3437,7 +3437,8 @@ fn param(ccx: @mut CrateCtxt, n: uint) -> ty::t {
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); }
};

View File

@ -863,7 +863,8 @@ pub fn for_autoref(rcx: @mut Rcx,
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 @@ fn categorize(rcx: @mut Rcx, expr: @ast::expr) -> ExprCategorization {
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;

View File

@ -65,7 +65,7 @@ fn foo<A>(a: A, b: A) { ... }
*/
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 @@ pub fn tys(&self, a: ty::t, b: ty::t) -> CoerceResult {
};
}
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 @@ pub fn coerce_borrowed_vector(&self,
})))
}
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,

View File

@ -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),
}

View File

@ -747,9 +747,8 @@ fn repr(&self, tcx: ctxt) -> ~str {
&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)
}
}
}

View File

@ -158,6 +158,7 @@ pub fn visit_inner(&self, inner: *TyDesc) -> bool {
}
#[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 @@ pub fn visit_ptr_inner(&self, ptr: *c_void, inner: *TyDesc) -> bool {
}
}
#[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<T:Repr>(&self) -> bool {
do self.get |v:&T| {
@ -556,6 +568,7 @@ fn visit_opaque_box(&self) -> bool {
fn visit_closure_ptr(&self, _ck: uint) -> bool { true }
}
#[cfg(stage0)]
pub fn write_repr<T>(writer: @Writer, object: &T) {
unsafe {
let ptr = ptr::to_unsafe_ptr(object) as *c_void;
@ -566,6 +579,17 @@ pub fn write_repr<T>(writer: @Writer, object: &T) {
}
}
#[cfg(not(stage0))]
pub fn write_repr<T>(writer: @Writer, object: &T) {
unsafe {
let ptr = ptr::to_unsafe_ptr(object) as *c_void;
let tydesc = get_tydesc::<T>();
let u = ReprVisitor(ptr, writer);
let v = reflect::MovePtrAdaptor(u);
visit_tydesc(tydesc, &v as &TyVisitor)
}
}
#[cfg(test)]
struct P {a: int, b: float}

View File

@ -38,16 +38,34 @@
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 @@ fn visit_leave_fn(&self, purity: uint, proto: uint,
/// Returns `true` if a type is managed (will be allocated on the local heap)
pub fn contains_managed<T>() -> 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.

View File

@ -85,7 +85,7 @@ pub enum ast_node {
pub struct Ctx {
map: map,
path: path,
diag: @span_handler,
diag: @mut span_handler,
}
impl Ctx {
@ -141,7 +141,7 @@ fn map_expr(@mut self, ex: @expr) {
}
}
visit::visit_expr(self as @Visitor<()>, ex, ());
visit::visit_expr(self as @mut Visitor<()>, ex, ());
}
fn map_fn(@mut self,
@ -153,18 +153,18 @@ fn map_fn(@mut self,
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 @@ fn map_pat(@mut self, pat: @pat) {
_ => ()
}
visit::visit_pat(self as @Visitor<()>, pat, ());
visit::visit_pat(self as @mut Visitor<()>, pat, ());
}
}
@ -254,13 +254,13 @@ fn visit_item(@mut self, i: @item, _: ()) {
}
_ => 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 @@ fn visit_block(@mut self, block: &Block, _: ()) {
// 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 @@ fn visit_expr_post(@mut self, _: @expr, _: ()) {
}
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 @@ fn visit_fn(@mut self,
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 @@ fn visit_fn(@mut self,
}
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 @@ fn visit_struct_def(@mut self,
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 @@ fn visit_struct_def(@mut self,
}
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 {

View File

@ -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<E: Clone>(&self, e: E, v: @Visitor<E>);
fn accept<E: Clone>(&self, e: E, v: @mut Visitor<E>);
}
impl inlined_item_utils for inlined_item {
@ -318,7 +318,7 @@ fn id(&self) -> ast::NodeId {
}
}
fn accept<E: Clone>(&self, e: E, v: @Visitor<E>) {
fn accept<E: Clone>(&self, e: E, v: @mut Visitor<E>) {
match *self {
ii_item(i) => v.visit_item(i, e),
ii_foreign(i) => v.visit_foreign_item(i, e),
@ -414,7 +414,7 @@ fn visit_mod(@mut self,
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 @@ fn visit_view_item(@mut self, view_item: &view_item, env: ()) {
}
}
}
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 @@ fn visit_item(@mut self, item: @item, env: ()) {
_ => {}
}
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 @@ fn visit_expr(@mut self, expression: @expr, env: ()) {
}
}
(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 @@ fn visit_ty(@mut self, typ: &Ty, env: ()) {
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 @@ fn visit_fn(@mut self,
(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 @@ fn visit_fn(@mut self,
// 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 @@ fn visit_struct_def(@mut self,
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 @@ fn visit_struct_def(@mut self,
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 @@ fn each_view_item(&self, f: @fn(&ast::view_item) -> bool) -> bool {
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
}
}

View File

@ -313,7 +313,7 @@ pub fn test_cfg<AM: AttrMetaMethods, It: Iterator<AM>>
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() {

View File

@ -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 @@ fn span_bug(@mut self, sp: span, msg: &str) -> ! {
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<Emitter>) -> @handler {
pub fn mk_handler(emitter: Option<Emitter>) -> @mut handler {
let emit: Emitter = match emitter {
Some(e) => e,
None => {
@ -157,7 +157,7 @@ pub fn mk_handler(emitter: Option<Emitter>) -> @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<T:Clone>(diag: @span_handler,
pub fn expect<T:Clone>(diag: @mut span_handler,
opt: Option<T>,
msg: &fn() -> ~str) -> T {
match opt {

View File

@ -548,52 +548,52 @@ fn visit_pat(@mut self, pattern: @ast::pat, _: ()) {
}
}
// 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 @@ fn visit_expr_post(@mut self, _: @ast::expr, _: ()) {
}
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 @@ fn visit_fn(@mut self,
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 @@ fn visit_fn(@mut self,
}
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 @@ fn visit_struct_def(@mut self,
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 @@ fn visit_struct_def(@mut self,
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,

View File

@ -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) {

View File

@ -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<ident, @named_match> {
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 = ~[];

View File

@ -59,7 +59,7 @@ fn ms(m: matcher_) -> matcher {
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 @@ fn generic_extension(cx: @ExtCtxt, sp: span, name: ident,
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 @@ fn generic_extension(cx: @ExtCtxt, sp: span, name: ident,
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.

View File

@ -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<HashMap<ident,@named_match>>,
src: ~[ast::token_tree])
-> @mut TtReader {

View File

@ -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]) {

View File

@ -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 @@ fn next_token(@mut self) -> TokenAndSpan {
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 @@ fn peek(@mut self) -> TokenAndSpan {
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 @@ fn next_token(@mut self) -> TokenAndSpan {
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.

View File

@ -43,7 +43,7 @@
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<Emitter>) -> @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

View File

@ -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

View File

@ -104,7 +104,7 @@ pub fn rust_printer_annotated(writer: @io::Writer,
// 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,

View File

@ -88,11 +88,11 @@ pub trait Visitor<E> {
fn visit_struct_field(@mut self, @struct_field, E);
}
pub fn visit_crate<E:Clone>(visitor: @Visitor<E>, crate: &Crate, env: E) {
pub fn visit_crate<E:Clone>(visitor: @mut Visitor<E>, crate: &Crate, env: E) {
visitor.visit_mod(&crate.module, crate.span, CRATE_NODE_ID, env)
}
pub fn visit_mod<E:Clone>(visitor: @Visitor<E>, module: &_mod, env: E) {
pub fn visit_mod<E:Clone>(visitor: @mut Visitor<E>, 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<E:Clone>(visitor: @Visitor<E>, module: &_mod, env: E) {
}
}
pub fn visit_view_item<E:Clone>(_: @Visitor<E>, _: &view_item, _: E) {
pub fn visit_view_item<E:Clone>(_: @mut Visitor<E>, _: &view_item, _: E) {
// Empty!
}
pub fn visit_local<E:Clone>(visitor: @Visitor<E>, local: &Local, env: E) {
pub fn visit_local<E:Clone>(visitor: @mut Visitor<E>, 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<E:Clone>(visitor: @Visitor<E>, local: &Local, env: E) {
}
}
fn visit_trait_ref<E:Clone>(visitor: @Visitor<E>,
fn visit_trait_ref<E:Clone>(visitor: @mut Visitor<E>,
trait_ref: &ast::trait_ref,
env: E) {
visit_path(visitor, &trait_ref.path, env)
}
pub fn visit_item<E:Clone>(visitor: @Visitor<E>, item: &item, env: E) {
pub fn visit_item<E:Clone>(visitor: @mut Visitor<E>, 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<E:Clone>(visitor: @Visitor<E>, item: &item, env: E) {
}
}
pub fn visit_enum_def<E:Clone>(visitor: @Visitor<E>,
pub fn visit_enum_def<E:Clone>(visitor: @mut Visitor<E>,
enum_definition: &ast::enum_def,
generics: &Generics,
env: E) {
@ -209,11 +209,11 @@ pub fn visit_enum_def<E:Clone>(visitor: @Visitor<E>,
}
}
pub fn skip_ty<E>(_: @Visitor<E>, _: &Ty, _: E) {
pub fn skip_ty<E>(_: @mut Visitor<E>, _: &Ty, _: E) {
// Empty!
}
pub fn visit_ty<E:Clone>(visitor: @Visitor<E>, typ: &Ty, env: E) {
pub fn visit_ty<E:Clone>(visitor: @mut Visitor<E>, 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<E:Clone>(visitor: @Visitor<E>, typ: &Ty, env: E) {
}
}
pub fn visit_path<E:Clone>(visitor: @Visitor<E>, path: &Path, env: E) {
pub fn visit_path<E:Clone>(visitor: @mut Visitor<E>, path: &Path, env: E) {
for typ in path.types.iter() {
visitor.visit_ty(typ, env.clone())
}
}
pub fn visit_pat<E:Clone>(visitor: @Visitor<E>, pattern: &pat, env: E) {
pub fn visit_pat<E:Clone>(visitor: @mut Visitor<E>, 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<E:Clone>(visitor: @Visitor<E>, pattern: &pat, env: E) {
}
}
pub fn visit_foreign_item<E:Clone>(visitor: @Visitor<E>,
pub fn visit_foreign_item<E:Clone>(visitor: @mut Visitor<E>,
foreign_item: &foreign_item,
env: E) {
match foreign_item.node {
@ -325,7 +325,7 @@ pub fn visit_foreign_item<E:Clone>(visitor: @Visitor<E>,
}
}
pub fn visit_ty_param_bounds<E:Clone>(visitor: @Visitor<E>,
pub fn visit_ty_param_bounds<E:Clone>(visitor: @mut Visitor<E>,
bounds: &OptVec<TyParamBound>,
env: E) {
for bound in bounds.iter() {
@ -338,7 +338,7 @@ pub fn visit_ty_param_bounds<E:Clone>(visitor: @Visitor<E>,
}
}
pub fn visit_generics<E:Clone>(visitor: @Visitor<E>,
pub fn visit_generics<E:Clone>(visitor: @mut Visitor<E>,
generics: &Generics,
env: E) {
for type_parameter in generics.ty_params.iter() {
@ -346,7 +346,7 @@ pub fn visit_generics<E:Clone>(visitor: @Visitor<E>,
}
}
pub fn visit_fn_decl<E:Clone>(visitor: @Visitor<E>,
pub fn visit_fn_decl<E:Clone>(visitor: @mut Visitor<E>,
function_declaration: &fn_decl,
env: E) {
for argument in function_declaration.inputs.iter() {
@ -360,7 +360,7 @@ pub fn visit_fn_decl<E:Clone>(visitor: @Visitor<E>,
// 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<E:Clone>(visitor: @Visitor<E>,
pub fn visit_method_helper<E:Clone>(visitor: @mut Visitor<E>,
method: &method,
env: E) {
visitor.visit_fn(&fk_method(method.ident, &method.generics, method),
@ -371,7 +371,7 @@ pub fn visit_method_helper<E:Clone>(visitor: @Visitor<E>,
env)
}
pub fn visit_fn<E:Clone>(visitor: @Visitor<E>,
pub fn visit_fn<E:Clone>(visitor: @mut Visitor<E>,
function_kind: &fn_kind,
function_declaration: &fn_decl,
function_body: &Block,
@ -384,7 +384,7 @@ pub fn visit_fn<E:Clone>(visitor: @Visitor<E>,
visitor.visit_block(function_body, env)
}
pub fn visit_ty_method<E:Clone>(visitor: @Visitor<E>,
pub fn visit_ty_method<E:Clone>(visitor: @mut Visitor<E>,
method_type: &TypeMethod,
env: E) {
for argument_type in method_type.decl.inputs.iter() {
@ -394,7 +394,7 @@ pub fn visit_ty_method<E:Clone>(visitor: @Visitor<E>,
visitor.visit_ty(&method_type.decl.output, env.clone())
}
pub fn visit_trait_method<E:Clone>(visitor: @Visitor<E>,
pub fn visit_trait_method<E:Clone>(visitor: @mut Visitor<E>,
trait_method: &trait_method,
env: E) {
match *trait_method {
@ -405,7 +405,7 @@ pub fn visit_trait_method<E:Clone>(visitor: @Visitor<E>,
}
}
pub fn visit_struct_def<E:Clone>(visitor: @Visitor<E>,
pub fn visit_struct_def<E:Clone>(visitor: @mut Visitor<E>,
struct_definition: @struct_def,
_: ast::ident,
_: &Generics,
@ -416,13 +416,13 @@ pub fn visit_struct_def<E:Clone>(visitor: @Visitor<E>,
}
}
pub fn visit_struct_field<E:Clone>(visitor: @Visitor<E>,
pub fn visit_struct_field<E:Clone>(visitor: @mut Visitor<E>,
struct_field: &struct_field,
env: E) {
visitor.visit_ty(&struct_field.node.ty, env)
}
pub fn visit_block<E:Clone>(visitor: @Visitor<E>, block: &Block, env: E) {
pub fn visit_block<E:Clone>(visitor: @mut Visitor<E>, 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<E:Clone>(visitor: @Visitor<E>, block: &Block, env: E) {
visit_expr_opt(visitor, block.expr, env)
}
pub fn visit_stmt<E>(visitor: @Visitor<E>, statement: &stmt, env: E) {
pub fn visit_stmt<E>(visitor: @mut Visitor<E>, 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<E>(visitor: @Visitor<E>, statement: &stmt, env: E) {
}
}
pub fn visit_decl<E:Clone>(visitor: @Visitor<E>, declaration: &decl, env: E) {
pub fn visit_decl<E:Clone>(visitor: @mut Visitor<E>, 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<E>(visitor: @Visitor<E>,
pub fn visit_expr_opt<E>(visitor: @mut Visitor<E>,
optional_expression: Option<@expr>,
env: E) {
match optional_expression {
@ -458,7 +458,7 @@ pub fn visit_expr_opt<E>(visitor: @Visitor<E>,
}
}
pub fn visit_exprs<E:Clone>(visitor: @Visitor<E>,
pub fn visit_exprs<E:Clone>(visitor: @mut Visitor<E>,
expressions: &[@expr],
env: E) {
for expression in expressions.iter() {
@ -466,11 +466,11 @@ pub fn visit_exprs<E:Clone>(visitor: @Visitor<E>,
}
}
pub fn visit_mac<E>(_: @Visitor<E>, _: &mac, _: E) {
pub fn visit_mac<E>(_: @mut Visitor<E>, _: &mac, _: E) {
// Empty!
}
pub fn visit_expr<E:Clone>(visitor: @Visitor<E>, expression: @expr, env: E) {
pub fn visit_expr<E:Clone>(visitor: @mut Visitor<E>, expression: @expr, env: E) {
match expression.node {
expr_vstore(subexpression, _) => {
visitor.visit_expr(subexpression, env.clone())
@ -595,7 +595,7 @@ pub fn visit_expr<E:Clone>(visitor: @Visitor<E>, expression: @expr, env: E) {
visitor.visit_expr_post(expression, env.clone())
}
pub fn visit_arm<E:Clone>(visitor: @Visitor<E>, arm: &arm, env: E) {
pub fn visit_arm<E:Clone>(visitor: @mut Visitor<E>, 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 @@ fn visit_mod(@mut self,
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 @@ fn visit_fn(@mut self,
block,
span,
node_id);
visit_fn(self as @Visitor<()>,
visit_fn(self as @mut Visitor<()>,
function_kind,
function_declaration,
block,
@ -715,11 +715,11 @@ fn visit_fn(@mut self,
}
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 @@ fn visit_struct_def(@mut self,
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 @@ fn visit_struct_def(@mut self,
}
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)
}
}

View File

@ -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*);

View File

@ -21,6 +21,7 @@ struct type_desc str_body_tydesc = {
NULL, // drop_glue
NULL, // free_glue
NULL, // visit_glue
0, // borrow_offset
};
//

View File

@ -8,22 +8,17 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Check that `&mut` objects cannot be borrowed twice, just like
// other `&mut` pointers.
trait Foo {
fn f(&self) -> int;
fn f1<'a>(&'a mut self) -> &'a ();
fn f2(&mut self);
}
struct Bar {
x: int
fn test(x: &mut Foo) {
let _y = x.f1();
x.f2(); //~ ERROR cannot borrow `*x` as mutable more than once at a time
}
impl Foo for Bar {
fn f(&self) -> int {
self.x
}
}
pub fn main() {
let x = ~Bar { x: 10 };
let y = x as ~Foo;
assert_eq!(y.f(), 10);
}
fn main() {}

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}

View File

@ -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
}

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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

View File

@ -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() {}

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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());
}
}

View File

@ -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;
}

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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());
}

View File

@ -502,7 +502,7 @@ pub fn visit_inner(&self, inner: *TyDesc) -> bool {
unsafe {
let u = my_visitor(**self);
let v = ptr_visit_adaptor::<my_visitor>(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();

View File

@ -79,7 +79,7 @@ fn visit_evec_box(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
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 @@ fn visit_evec_uniq(&self, _mtbl: uint, inner: *TyDesc) -> bool {
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 @@ fn visit_constr(&self, _inner: *TyDesc) -> bool { true }
fn visit_closure_ptr(&self, _ck: uint) -> bool { true }
}
fn visit_ty<T>(v: @TyVisitor) {
fn visit_ty<T>(v: &TyVisitor) {
unsafe {
visit_tydesc(get_tydesc::<T>(), v);
}