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:
commit
b285f1e6c9
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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() {
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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) |
|
||||
|
@ -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(_) => {}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 => {},
|
||||
|
@ -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(_) => ~"*"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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, _)) => {
|
||||
|
@ -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 {
|
||||
|
@ -60,7 +60,6 @@ pub struct MethodData {
|
||||
llfn: ValueRef,
|
||||
llself: ValueRef,
|
||||
temp_cleanup: Option<ValueRef>,
|
||||
self_ty: ty::t,
|
||||
self_mode: ty::SelfMode,
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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]
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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) */
|
||||
})
|
||||
};
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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 {
|
||||
|
@ -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())))
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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); }
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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),
|
||||
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
@ -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 = ~[];
|
||||
|
@ -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.
|
||||
|
@ -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 {
|
||||
|
@ -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]) {
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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*);
|
||||
|
@ -21,6 +21,7 @@ struct type_desc str_body_tydesc = {
|
||||
NULL, // drop_glue
|
||||
NULL, // free_glue
|
||||
NULL, // visit_glue
|
||||
0, // borrow_offset
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -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() {}
|
42
src/test/compile-fail/borrowck-object-lifetime.rs
Normal file
42
src/test/compile-fail/borrowck-object-lifetime.rs
Normal 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() {}
|
||||
|
47
src/test/compile-fail/borrowck-object-mutability.rs
Normal file
47
src/test/compile-fail/borrowck-object-mutability.rs
Normal 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() {}
|
||||
|
@ -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
|
||||
}
|
||||
|
64
src/test/compile-fail/object-pointer-types.rs
Normal file
64
src/test/compile-fail/object-pointer-types.rs
Normal 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
|
@ -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() {}
|
||||
|
21
src/test/run-fail/borrowck-wg-fail-object.rs
Normal file
21
src/test/run-fail/borrowck-wg-fail-object.rs
Normal 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);
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
32
src/test/run-pass/objects-owned-object-owned-method.rs
Normal file
32
src/test/run-pass/objects-owned-object-owned-method.rs
Normal 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());
|
||||
}
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user