librustc: Remove `@mut` support from the typechecker and borrow checker
This commit is contained in:
parent
9b35ae75d2
commit
88281290ff
|
@ -295,7 +295,7 @@ pub fn phase_3_run_analysis_passes(sess: Session,
|
|||
middle::liveness::check_crate(ty_cx, method_map,
|
||||
capture_map, crate));
|
||||
|
||||
let (root_map, write_guard_map) =
|
||||
let root_map =
|
||||
time(time_passes, "borrow checking", (), |_|
|
||||
middle::borrowck::check_crate(ty_cx, method_map,
|
||||
moves_map, moved_variables_set,
|
||||
|
@ -330,7 +330,6 @@ pub fn phase_3_run_analysis_passes(sess: Session,
|
|||
root_map: root_map,
|
||||
method_map: method_map,
|
||||
vtable_map: vtable_map,
|
||||
write_guard_map: write_guard_map,
|
||||
capture_map: capture_map
|
||||
},
|
||||
reachable: reachable_map
|
||||
|
|
|
@ -342,7 +342,7 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
|
|||
let did = parse_def(st, TypeParameter, |x,y| conv(x,y));
|
||||
return ty::mk_self(st.tcx, did);
|
||||
}
|
||||
'@' => return ty::mk_box(st.tcx, parse_mt(st, |x,y| conv(x,y))),
|
||||
'@' => return ty::mk_box(st.tcx, parse_ty(st, |x,y| conv(x,y))),
|
||||
'~' => return ty::mk_uniq(st.tcx, parse_mt(st, |x,y| conv(x,y))),
|
||||
'*' => return ty::mk_ptr(st.tcx, parse_mt(st, |x,y| conv(x,y))),
|
||||
'&' => {
|
||||
|
|
|
@ -292,7 +292,7 @@ fn enc_sty(w: &mut MemWriter, cx: @ctxt, st: &ty::sty) {
|
|||
for t in ts.iter() { enc_ty(w, cx, *t); }
|
||||
mywrite!(w, "]");
|
||||
}
|
||||
ty::ty_box(mt) => { mywrite!(w, "@"); enc_mt(w, cx, mt); }
|
||||
ty::ty_box(typ) => { mywrite!(w, "@"); enc_ty(w, cx, typ); }
|
||||
ty::ty_uniq(mt) => { mywrite!(w, "~"); enc_mt(w, cx, mt); }
|
||||
ty::ty_ptr(mt) => { mywrite!(w, "*"); enc_mt(w, cx, mt); }
|
||||
ty::ty_rptr(r, mt) => {
|
||||
|
|
|
@ -55,7 +55,6 @@ pub struct Maps {
|
|||
root_map: middle::borrowck::root_map,
|
||||
method_map: middle::typeck::method_map,
|
||||
vtable_map: middle::typeck::vtable_map,
|
||||
write_guard_map: middle::borrowck::write_guard_map,
|
||||
capture_map: middle::moves::CaptureMap,
|
||||
}
|
||||
|
||||
|
|
|
@ -368,11 +368,15 @@ impl<'a> CheckLoanCtxt<'a> {
|
|||
cmt = b;
|
||||
}
|
||||
|
||||
mc::cat_deref(_, _, mc::gc_ptr) => {
|
||||
assert_eq!(cmt.mutbl, mc::McImmutable);
|
||||
return;
|
||||
}
|
||||
|
||||
mc::cat_rvalue(..) |
|
||||
mc::cat_static_item |
|
||||
mc::cat_copied_upvar(..) |
|
||||
mc::cat_deref(_, _, mc::unsafe_ptr(..)) |
|
||||
mc::cat_deref(_, _, mc::gc_ptr(..)) |
|
||||
mc::cat_deref(_, _, mc::region_ptr(..)) => {
|
||||
assert_eq!(cmt.mutbl, mc::McDeclared);
|
||||
return;
|
||||
|
@ -411,20 +415,6 @@ impl<'a> CheckLoanCtxt<'a> {
|
|||
check_for_aliasability_violation(this, expr, b);
|
||||
}
|
||||
|
||||
mc::cat_deref(_, deref_count, mc::gc_ptr(ast::MutMutable)) => {
|
||||
// Dynamically check writes to `@mut`
|
||||
|
||||
let key = root_map_key {
|
||||
id: guarantor.id,
|
||||
derefs: deref_count
|
||||
};
|
||||
debug!("Inserting write guard at {:?}", key);
|
||||
let mut write_guard_map = this.bccx
|
||||
.write_guard_map
|
||||
.borrow_mut();
|
||||
write_guard_map.get().insert(key);
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
@ -455,7 +445,7 @@ impl<'a> CheckLoanCtxt<'a> {
|
|||
mc::cat_self(..) |
|
||||
mc::cat_deref(_, _, mc::unsafe_ptr(..)) |
|
||||
mc::cat_static_item(..) |
|
||||
mc::cat_deref(_, _, mc::gc_ptr(_)) |
|
||||
mc::cat_deref(_, _, mc::gc_ptr) |
|
||||
mc::cat_deref(_, _, mc::region_ptr(MutImmutable, _)) => {
|
||||
// Aliasability is independent of base cmt
|
||||
match cmt.freely_aliasable() {
|
||||
|
|
|
@ -102,7 +102,7 @@ fn check_is_legal_to_move_from(bccx: &BorrowckCtxt,
|
|||
cmt: mc::cmt) -> bool {
|
||||
match cmt.cat {
|
||||
mc::cat_deref(_, _, mc::region_ptr(..)) |
|
||||
mc::cat_deref(_, _, mc::gc_ptr(..)) |
|
||||
mc::cat_deref(_, _, mc::gc_ptr) |
|
||||
mc::cat_deref(_, _, mc::unsafe_ptr(..)) |
|
||||
mc::cat_stack_upvar(..) |
|
||||
mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Many, .. }) => {
|
||||
|
|
|
@ -16,10 +16,8 @@
|
|||
use middle::borrowck::*;
|
||||
use mc = middle::mem_categorization;
|
||||
use middle::ty;
|
||||
use syntax::ast::{MutImmutable, MutMutable};
|
||||
use syntax::ast;
|
||||
use syntax::codemap::Span;
|
||||
use util::ppaux::{note_and_explain_region};
|
||||
|
||||
type R = Result<(),()>;
|
||||
|
||||
|
@ -89,12 +87,11 @@ impl<'a> GuaranteeLifetimeContext<'a> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
mc::cat_deref(base, derefs, mc::gc_ptr(ptr_mutbl)) => {
|
||||
mc::cat_deref(base, derefs, mc::gc_ptr) => {
|
||||
let base_scope = self.scope(base);
|
||||
|
||||
// L-Deref-Managed-Imm-User-Root
|
||||
let omit_root = (
|
||||
ptr_mutbl == MutImmutable &&
|
||||
self.bccx.is_subregion_of(self.loan_region, base_scope) &&
|
||||
self.is_rvalue_or_immutable(base) &&
|
||||
!self.is_moved(base)
|
||||
|
@ -103,7 +100,7 @@ impl<'a> GuaranteeLifetimeContext<'a> {
|
|||
if !omit_root {
|
||||
// L-Deref-Managed-Imm-Compiler-Root
|
||||
// L-Deref-Managed-Mut-Compiler-Root
|
||||
self.check_root(cmt, base, derefs, ptr_mutbl, discr_scope)
|
||||
self.check_root(cmt, base, derefs, discr_scope)
|
||||
} else {
|
||||
debug!("omitting root, base={}, base_scope={:?}",
|
||||
base.repr(self.tcx()), base_scope);
|
||||
|
@ -192,14 +189,12 @@ impl<'a> GuaranteeLifetimeContext<'a> {
|
|||
cmt_deref: mc::cmt,
|
||||
cmt_base: mc::cmt,
|
||||
derefs: uint,
|
||||
ptr_mutbl: ast::Mutability,
|
||||
discr_scope: Option<ast::NodeId>) -> R {
|
||||
debug!("check_root(cmt_deref={}, cmt_base={}, derefs={:?}, ptr_mutbl={:?}, \
|
||||
debug!("check_root(cmt_deref={}, cmt_base={}, derefs={:?}, \
|
||||
discr_scope={:?})",
|
||||
cmt_deref.repr(self.tcx()),
|
||||
cmt_base.repr(self.tcx()),
|
||||
derefs,
|
||||
ptr_mutbl,
|
||||
discr_scope);
|
||||
|
||||
// Make sure that the loan does not exceed the maximum time
|
||||
|
@ -235,19 +230,6 @@ impl<'a> GuaranteeLifetimeContext<'a> {
|
|||
}
|
||||
};
|
||||
|
||||
// If we are borrowing the inside of an `@mut` box,
|
||||
// we need to dynamically mark it to prevent incompatible
|
||||
// borrows from happening later.
|
||||
let opt_dyna = match ptr_mutbl {
|
||||
MutImmutable => None,
|
||||
MutMutable => {
|
||||
match self.loan_mutbl {
|
||||
MutableMutability => Some(DynaMut),
|
||||
ImmutableMutability | ConstMutability => Some(DynaImm)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// FIXME(#3511) grow to the nearest cleanup scope---this can
|
||||
// cause observable errors if freezing!
|
||||
if !self.bccx.tcx.region_maps.is_cleanup_scope(root_scope) {
|
||||
|
@ -256,29 +238,12 @@ impl<'a> GuaranteeLifetimeContext<'a> {
|
|||
let cleanup_scope =
|
||||
self.bccx.tcx.region_maps.cleanup_scope(root_scope);
|
||||
|
||||
if opt_dyna.is_some() {
|
||||
self.tcx().sess.span_warn(
|
||||
self.span,
|
||||
format!("Dynamic freeze scope artifically extended \
|
||||
(see Issue \\#6248)"));
|
||||
note_and_explain_region(
|
||||
self.bccx.tcx,
|
||||
"managed value only needs to be frozen for ",
|
||||
ty::ReScope(root_scope),
|
||||
"...");
|
||||
note_and_explain_region(
|
||||
self.bccx.tcx,
|
||||
"...but due to Issue #6248, it will be frozen for ",
|
||||
ty::ReScope(cleanup_scope),
|
||||
"");
|
||||
}
|
||||
|
||||
root_scope = cleanup_scope;
|
||||
}
|
||||
|
||||
// Add a record of what is required
|
||||
let rm_key = root_map_key {id: cmt_deref.id, derefs: derefs};
|
||||
let root_info = RootInfo {scope: root_scope, freeze: opt_dyna};
|
||||
let root_info = RootInfo {scope: root_scope};
|
||||
|
||||
let mut root_map = self.bccx.root_map.borrow_mut();
|
||||
root_map.get().insert(rm_key, root_info);
|
||||
|
@ -357,7 +322,7 @@ impl<'a> GuaranteeLifetimeContext<'a> {
|
|||
}
|
||||
mc::cat_downcast(cmt) |
|
||||
mc::cat_deref(cmt, _, mc::uniq_ptr) |
|
||||
mc::cat_deref(cmt, _, mc::gc_ptr(..)) |
|
||||
mc::cat_deref(cmt, _, mc::gc_ptr) |
|
||||
mc::cat_interior(cmt, _) |
|
||||
mc::cat_stack_upvar(cmt) |
|
||||
mc::cat_discr(cmt, _) => {
|
||||
|
|
|
@ -132,59 +132,11 @@ impl<'a> RestrictionsContext<'a> {
|
|||
Safe
|
||||
}
|
||||
|
||||
mc::cat_deref(_, _, mc::gc_ptr(MutImmutable)) => {
|
||||
mc::cat_deref(_, _, mc::gc_ptr) => {
|
||||
// R-Deref-Imm-Managed
|
||||
Safe
|
||||
}
|
||||
|
||||
mc::cat_deref(cmt_base, _, pk @ mc::gc_ptr(MutMutable)) => {
|
||||
// R-Deref-Managed-Borrowed
|
||||
//
|
||||
// Technically, no restrictions are *necessary* here.
|
||||
// The validity of the borrow is guaranteed
|
||||
// dynamically. However, nonetheless we add a
|
||||
// restriction to make a "best effort" to report
|
||||
// static errors. For example, if there is code like
|
||||
//
|
||||
// let v = @mut ~[1, 2, 3];
|
||||
// for e in v.iter() {
|
||||
// v.push(e + 1);
|
||||
// }
|
||||
//
|
||||
// Then the code below would add restrictions on `*v`,
|
||||
// which means that an error would be reported
|
||||
// here. This of course is not perfect. For example,
|
||||
// a function like the following would not report an error
|
||||
// at compile-time but would fail dynamically:
|
||||
//
|
||||
// let v = @mut ~[1, 2, 3];
|
||||
// let w = v;
|
||||
// for e in v.iter() {
|
||||
// w.push(e + 1);
|
||||
// }
|
||||
//
|
||||
// In addition, we only add a restriction for those cases
|
||||
// where we can construct a sensible loan path, so an
|
||||
// example like the following will fail dynamically:
|
||||
//
|
||||
// impl V {
|
||||
// fn get_list(&self) -> @mut ~[int];
|
||||
// }
|
||||
// ...
|
||||
// let v: &V = ...;
|
||||
// for e in v.get_list().iter() {
|
||||
// v.get_list().push(e + 1);
|
||||
// }
|
||||
match opt_loan_path(cmt_base) {
|
||||
None => Safe,
|
||||
Some(lp_base) => {
|
||||
let lp = @LpExtend(lp_base, cmt.mutbl, LpDeref(pk));
|
||||
SafeIf(lp, ~[Restriction {loan_path: lp,
|
||||
set: restrictions}])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mc::cat_deref(cmt_base, _, pk @ mc::region_ptr(MutMutable, lt)) => {
|
||||
// R-Deref-Mut-Borrowed
|
||||
if !self.bccx.is_subregion_of(self.loan_region, lt) {
|
||||
|
|
|
@ -20,7 +20,7 @@ use middle::dataflow::DataFlowOperator;
|
|||
use util::ppaux::{note_and_explain_region, Repr, UserString};
|
||||
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::hashmap::{HashSet, HashMap};
|
||||
use std::hashmap::HashMap;
|
||||
use std::ops::{BitOr, BitAnd};
|
||||
use std::result::{Result};
|
||||
use syntax::ast;
|
||||
|
@ -67,14 +67,13 @@ impl Visitor<()> for BorrowckCtxt {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn check_crate(
|
||||
tcx: ty::ctxt,
|
||||
method_map: typeck::method_map,
|
||||
moves_map: moves::MovesMap,
|
||||
moved_variables_set: moves::MovedVariablesSet,
|
||||
capture_map: moves::CaptureMap,
|
||||
crate: &ast::Crate) -> (root_map, write_guard_map)
|
||||
{
|
||||
pub fn check_crate(tcx: ty::ctxt,
|
||||
method_map: typeck::method_map,
|
||||
moves_map: moves::MovesMap,
|
||||
moved_variables_set: moves::MovedVariablesSet,
|
||||
capture_map: moves::CaptureMap,
|
||||
crate: &ast::Crate)
|
||||
-> root_map {
|
||||
let mut bccx = BorrowckCtxt {
|
||||
tcx: tcx,
|
||||
method_map: method_map,
|
||||
|
@ -82,7 +81,6 @@ pub fn check_crate(
|
|||
moved_variables_set: moved_variables_set,
|
||||
capture_map: capture_map,
|
||||
root_map: root_map(),
|
||||
write_guard_map: @RefCell::new(HashSet::new()),
|
||||
stats: @BorrowStats {
|
||||
loaned_paths_same: Cell::new(0),
|
||||
loaned_paths_imm: Cell::new(0),
|
||||
|
@ -106,7 +104,7 @@ pub fn check_crate(
|
|||
make_stat(bccx, bccx.stats.stable_paths.get()));
|
||||
}
|
||||
|
||||
return (bccx.root_map, bccx.write_guard_map);
|
||||
return bccx.root_map;
|
||||
|
||||
fn make_stat(bccx: &mut BorrowckCtxt, stat: uint) -> ~str {
|
||||
let stat_f = stat as f64;
|
||||
|
@ -171,7 +169,6 @@ pub struct BorrowckCtxt {
|
|||
moved_variables_set: moves::MovedVariablesSet,
|
||||
capture_map: moves::CaptureMap,
|
||||
root_map: root_map,
|
||||
write_guard_map: write_guard_map,
|
||||
|
||||
// Statistics:
|
||||
stats: @BorrowStats
|
||||
|
@ -213,10 +210,6 @@ pub struct root_map_key {
|
|||
derefs: uint
|
||||
}
|
||||
|
||||
// A set containing IDs of expressions of gc'd type that need to have a write
|
||||
// guard.
|
||||
pub type write_guard_map = @RefCell<HashSet<root_map_key>>;
|
||||
|
||||
pub type BckResult<T> = Result<T, BckError>;
|
||||
|
||||
#[deriving(Eq)]
|
||||
|
@ -402,7 +395,6 @@ impl BitAnd<RestrictionSet,RestrictionSet> for RestrictionSet {
|
|||
|
||||
pub struct RootInfo {
|
||||
scope: ast::NodeId,
|
||||
freeze: Option<DynaFreezeKind> // Some() if we should freeze box at runtime
|
||||
}
|
||||
|
||||
pub type root_map = @RefCell<HashMap<root_map_key, RootInfo>>;
|
||||
|
@ -411,20 +403,6 @@ pub fn root_map() -> root_map {
|
|||
return @RefCell::new(HashMap::new());
|
||||
}
|
||||
|
||||
pub enum DynaFreezeKind {
|
||||
DynaImm,
|
||||
DynaMut
|
||||
}
|
||||
|
||||
impl ToStr for DynaFreezeKind {
|
||||
fn to_str(&self) -> ~str {
|
||||
match *self {
|
||||
DynaMut => ~"mutable",
|
||||
DynaImm => ~"immutable"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Errors
|
||||
|
||||
|
@ -691,20 +669,9 @@ impl BorrowckCtxt {
|
|||
span,
|
||||
format!("{} in an aliasable location", prefix));
|
||||
}
|
||||
mc::AliasableManaged(ast::MutMutable) => {
|
||||
// FIXME(#6269) reborrow @mut to &mut
|
||||
self.tcx.sess.span_err(
|
||||
span,
|
||||
format!("{} in a `@mut` pointer; \
|
||||
try borrowing as `&mut` first", prefix));
|
||||
}
|
||||
mc::AliasableManaged(m) => {
|
||||
self.tcx.sess.span_err(
|
||||
span,
|
||||
format!("{} in a `@{}` pointer; \
|
||||
try an `@mut` instead",
|
||||
prefix,
|
||||
self.mut_to_keyword(m)));
|
||||
mc::AliasableManaged => {
|
||||
self.tcx.sess.span_err(span, format!("{} in a `@` pointer",
|
||||
prefix))
|
||||
}
|
||||
mc::AliasableBorrowed(m) => {
|
||||
self.tcx.sess.span_err(
|
||||
|
|
|
@ -20,7 +20,7 @@ use syntax::visit::Visitor;
|
|||
use syntax::ast::*;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::hashmap::{HashMap, HashSet};
|
||||
use std::hashmap::HashMap;
|
||||
|
||||
//
|
||||
// This pass classifies expressions by their constant-ness.
|
||||
|
@ -132,7 +132,6 @@ pub fn lookup_variant_by_id(tcx: ty::ctxt,
|
|||
root_map: @RefCell::new(HashMap::new()),
|
||||
method_map: @RefCell::new(HashMap::new()),
|
||||
vtable_map: @RefCell::new(HashMap::new()),
|
||||
write_guard_map: @RefCell::new(HashSet::new()),
|
||||
capture_map: @RefCell::new(HashMap::new())
|
||||
};
|
||||
let e = match csearch::maybe_get_item_ast(tcx, enum_def,
|
||||
|
@ -186,7 +185,6 @@ pub fn lookup_const_by_id(tcx: ty::ctxt, def_id: ast::DefId)
|
|||
root_map: @RefCell::new(HashMap::new()),
|
||||
method_map: @RefCell::new(HashMap::new()),
|
||||
vtable_map: @RefCell::new(HashMap::new()),
|
||||
write_guard_map: @RefCell::new(HashSet::new()),
|
||||
capture_map: @RefCell::new(HashMap::new())
|
||||
};
|
||||
let e = match csearch::maybe_get_item_ast(tcx, def_id,
|
||||
|
|
|
@ -207,7 +207,7 @@ pub fn collect_language_items(crate: &ast::Crate,
|
|||
}
|
||||
|
||||
lets_do_this! {
|
||||
There are 43 lang items.
|
||||
There are 37 lang items.
|
||||
|
||||
// ID, Variant name, Name, Method name;
|
||||
0, FreezeTraitLangItem, "freeze", freeze_trait;
|
||||
|
@ -243,24 +243,18 @@ lets_do_this! {
|
|||
26, ExchangeFreeFnLangItem, "exchange_free", exchange_free_fn;
|
||||
27, MallocFnLangItem, "malloc", malloc_fn;
|
||||
28, FreeFnLangItem, "free", free_fn;
|
||||
29, BorrowAsImmFnLangItem, "borrow_as_imm", borrow_as_imm_fn;
|
||||
30, BorrowAsMutFnLangItem, "borrow_as_mut", borrow_as_mut_fn;
|
||||
31, ReturnToMutFnLangItem, "return_to_mut", return_to_mut_fn;
|
||||
32, CheckNotBorrowedFnLangItem, "check_not_borrowed", check_not_borrowed_fn;
|
||||
33, StrDupUniqFnLangItem, "strdup_uniq", strdup_uniq_fn;
|
||||
34, RecordBorrowFnLangItem, "record_borrow", record_borrow_fn;
|
||||
35, UnrecordBorrowFnLangItem, "unrecord_borrow", unrecord_borrow_fn;
|
||||
29, StrDupUniqFnLangItem, "strdup_uniq", strdup_uniq_fn;
|
||||
|
||||
36, StartFnLangItem, "start", start_fn;
|
||||
30, StartFnLangItem, "start", start_fn;
|
||||
|
||||
37, TyDescStructLangItem, "ty_desc", ty_desc;
|
||||
38, TyVisitorTraitLangItem, "ty_visitor", ty_visitor;
|
||||
39, OpaqueStructLangItem, "opaque", opaque;
|
||||
31, TyDescStructLangItem, "ty_desc", ty_desc;
|
||||
32, TyVisitorTraitLangItem, "ty_visitor", ty_visitor;
|
||||
33, OpaqueStructLangItem, "opaque", opaque;
|
||||
|
||||
40, EventLoopFactoryLangItem, "event_loop_factory", event_loop_factory;
|
||||
34, EventLoopFactoryLangItem, "event_loop_factory", event_loop_factory;
|
||||
|
||||
41, TypeIdLangItem, "type_id", type_id;
|
||||
35, TypeIdLangItem, "type_id", type_id;
|
||||
|
||||
42, EhPersonalityLangItem, "eh_personality", eh_personality_fn;
|
||||
36, EhPersonalityLangItem, "eh_personality", eh_personality_fn;
|
||||
}
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ pub struct CopiedUpvar {
|
|||
#[deriving(Eq, IterBytes)]
|
||||
pub enum PointerKind {
|
||||
uniq_ptr,
|
||||
gc_ptr(ast::Mutability),
|
||||
gc_ptr,
|
||||
region_ptr(ast::Mutability, ty::Region),
|
||||
unsafe_ptr(ast::Mutability)
|
||||
}
|
||||
|
@ -178,17 +178,11 @@ pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> {
|
|||
Some(deref_ptr(region_ptr(ast::MutImmutable, r)))
|
||||
}
|
||||
|
||||
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_box(_) |
|
||||
ty::ty_evec(_, ty::vstore_box) |
|
||||
ty::ty_trait(_, _, ty::BoxTraitStore, _, _) |
|
||||
ty::ty_estr(ty::vstore_box) => {
|
||||
Some(deref_ptr(gc_ptr(ast::MutImmutable)))
|
||||
Some(deref_ptr(gc_ptr))
|
||||
}
|
||||
|
||||
ty::ty_ptr(ref mt) => {
|
||||
|
@ -681,7 +675,10 @@ impl mem_categorization_ctxt {
|
|||
uniq_ptr => {
|
||||
base_cmt.mutbl.inherit()
|
||||
}
|
||||
gc_ptr(m) | region_ptr(m, _) | unsafe_ptr(m) => {
|
||||
gc_ptr => {
|
||||
McImmutable
|
||||
}
|
||||
region_ptr(m, _) | unsafe_ptr(m) => {
|
||||
MutabilityCategory::from_mutbl(m)
|
||||
}
|
||||
};
|
||||
|
@ -759,12 +756,15 @@ impl mem_categorization_ctxt {
|
|||
// for unique ptrs, we inherit mutability from the
|
||||
// owning reference.
|
||||
let m = match ptr {
|
||||
uniq_ptr => {
|
||||
base_cmt.mutbl.inherit()
|
||||
}
|
||||
gc_ptr(m) | region_ptr(m, _) | unsafe_ptr(m) => {
|
||||
MutabilityCategory::from_mutbl(m)
|
||||
}
|
||||
uniq_ptr => {
|
||||
base_cmt.mutbl.inherit()
|
||||
}
|
||||
gc_ptr => {
|
||||
McImmutable
|
||||
}
|
||||
region_ptr(m, _) | unsafe_ptr(m) => {
|
||||
MutabilityCategory::from_mutbl(m)
|
||||
}
|
||||
};
|
||||
|
||||
// the deref is explicit in the resulting cmt
|
||||
|
@ -1103,7 +1103,7 @@ pub fn field_mutbl(tcx: ty::ctxt,
|
|||
}
|
||||
|
||||
pub enum AliasableReason {
|
||||
AliasableManaged(ast::Mutability),
|
||||
AliasableManaged,
|
||||
AliasableBorrowed(ast::Mutability),
|
||||
AliasableOther
|
||||
}
|
||||
|
@ -1122,7 +1122,7 @@ impl cmt_ {
|
|||
cat_self(..) |
|
||||
cat_arg(..) |
|
||||
cat_deref(_, _, unsafe_ptr(..)) |
|
||||
cat_deref(_, _, gc_ptr(..)) |
|
||||
cat_deref(_, _, gc_ptr) |
|
||||
cat_deref(_, _, region_ptr(..)) => {
|
||||
self
|
||||
}
|
||||
|
@ -1166,8 +1166,8 @@ impl cmt_ {
|
|||
Some(AliasableOther)
|
||||
}
|
||||
|
||||
cat_deref(_, _, gc_ptr(m)) => {
|
||||
Some(AliasableManaged(m))
|
||||
cat_deref(_, _, gc_ptr) => {
|
||||
Some(AliasableManaged)
|
||||
}
|
||||
|
||||
cat_deref(_, _, region_ptr(m @ MutImmutable, _)) => {
|
||||
|
@ -1229,7 +1229,7 @@ impl Repr for categorization {
|
|||
pub fn ptr_sigil(ptr: PointerKind) -> ~str {
|
||||
match ptr {
|
||||
uniq_ptr => ~"~",
|
||||
gc_ptr(_) => ~"@",
|
||||
gc_ptr => ~"@",
|
||||
region_ptr(_, _) => ~"&",
|
||||
unsafe_ptr(_) => ~"*"
|
||||
}
|
||||
|
|
|
@ -22,12 +22,10 @@ use middle::trans::base;
|
|||
use middle::trans::build;
|
||||
use middle::trans::datum;
|
||||
use middle::trans::glue;
|
||||
use middle::trans::write_guard;
|
||||
use middle::trans::debuginfo;
|
||||
use middle::ty::substs;
|
||||
use middle::ty;
|
||||
use middle::typeck;
|
||||
use middle::borrowck::root_map_key;
|
||||
use util::ppaux::Repr;
|
||||
|
||||
use middle::trans::type_::Type;
|
||||
|
@ -363,27 +361,6 @@ impl CleanupFunction for ImmediateTypeDroppingCleanupFunction {
|
|||
}
|
||||
}
|
||||
|
||||
/// A cleanup function that releases a write guard, returning a value to
|
||||
/// mutable status.
|
||||
pub struct WriteGuardReleasingCleanupFunction {
|
||||
root_key: root_map_key,
|
||||
frozen_val_ref: ValueRef,
|
||||
bits_val_ref: ValueRef,
|
||||
filename_val: ValueRef,
|
||||
line_val: ValueRef,
|
||||
}
|
||||
|
||||
impl CleanupFunction for WriteGuardReleasingCleanupFunction {
|
||||
fn clean(&self, bcx: @Block) -> @Block {
|
||||
write_guard::return_to_mut(bcx,
|
||||
self.root_key,
|
||||
self.frozen_val_ref,
|
||||
self.bits_val_ref,
|
||||
self.filename_val,
|
||||
self.line_val)
|
||||
}
|
||||
}
|
||||
|
||||
/// A cleanup function that frees some memory in the garbage-collected heap.
|
||||
pub struct GCHeapFreeingCleanupFunction {
|
||||
ptr: ValueRef,
|
||||
|
@ -527,42 +504,7 @@ pub fn add_clean_temp_mem_in_scope_(bcx: @Block, scope_id: Option<ast::NodeId>,
|
|||
grow_scope_clean(scope_info);
|
||||
})
|
||||
}
|
||||
pub fn add_clean_return_to_mut(bcx: @Block,
|
||||
scope_id: ast::NodeId,
|
||||
root_key: root_map_key,
|
||||
frozen_val_ref: ValueRef,
|
||||
bits_val_ref: ValueRef,
|
||||
filename_val: ValueRef,
|
||||
line_val: ValueRef) {
|
||||
//! When an `@mut` has been frozen, we have to
|
||||
//! call the lang-item `return_to_mut` when the
|
||||
//! freeze goes out of scope. We need to pass
|
||||
//! in both the value which was frozen (`frozen_val`) and
|
||||
//! the value (`bits_val_ref`) which was returned when the
|
||||
//! box was frozen initially. Here, both `frozen_val_ref` and
|
||||
//! `bits_val_ref` are in fact pointers to stack slots.
|
||||
|
||||
debug!("add_clean_return_to_mut({}, {}, {})",
|
||||
bcx.to_str(),
|
||||
bcx.val_to_str(frozen_val_ref),
|
||||
bcx.val_to_str(bits_val_ref));
|
||||
in_scope_cx(bcx, Some(scope_id), |scope_info| {
|
||||
{
|
||||
let mut cleanups = scope_info.cleanups.borrow_mut();
|
||||
cleanups.get().push(clean_temp(
|
||||
frozen_val_ref,
|
||||
@WriteGuardReleasingCleanupFunction {
|
||||
root_key: root_key,
|
||||
frozen_val_ref: frozen_val_ref,
|
||||
bits_val_ref: bits_val_ref,
|
||||
filename_val: filename_val,
|
||||
line_val: line_val,
|
||||
} as @CleanupFunction,
|
||||
normal_exit_only));
|
||||
}
|
||||
grow_scope_clean(scope_info);
|
||||
})
|
||||
}
|
||||
pub fn add_clean_free(cx: @Block, ptr: ValueRef, heap: heap) {
|
||||
let free_fn = match heap {
|
||||
heap_managed | heap_managed_unique => {
|
||||
|
|
|
@ -552,7 +552,7 @@ impl Datum {
|
|||
* by-ref datum of type T, pointing at the contents. */
|
||||
|
||||
let (content_ty, header) = match ty::get(self.ty).sty {
|
||||
ty::ty_box(mt) => (mt.ty, true),
|
||||
ty::ty_box(typ) => (typ, true),
|
||||
ty::ty_uniq(mt) => (mt.ty, false),
|
||||
ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) => {
|
||||
let unit_ty = ty::sequence_element_type(bcx.tcx(), self.ty);
|
||||
|
|
|
@ -2142,8 +2142,8 @@ fn type_metadata(cx: &CrateContext,
|
|||
ty::ty_enum(def_id, _) => {
|
||||
prepare_enum_metadata(cx, t, def_id, usage_site_span).finalize(cx)
|
||||
},
|
||||
ty::ty_box(ref mt) => {
|
||||
create_pointer_to_box_metadata(cx, t, mt.ty)
|
||||
ty::ty_box(typ) => {
|
||||
create_pointer_to_box_metadata(cx, t, typ)
|
||||
},
|
||||
ty::ty_evec(ref mt, ref vstore) => {
|
||||
match *vstore {
|
||||
|
|
|
@ -378,18 +378,12 @@ pub fn trans_to_datum(bcx: @Block, expr: &ast::Expr) -> DatumBlock {
|
|||
let source_data = Load(bcx, source_data_ptr); // always a ptr
|
||||
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
|
||||
// For deref of @T, create a dummy datum and use the datum's
|
||||
// deref method. This is more work than just calling GEPi
|
||||
// ourselves. 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_ty = ty::mk_box(tcx, ty::mk_i8());
|
||||
let source_datum =
|
||||
Datum {val: source_data,
|
||||
ty: source_ty,
|
||||
|
|
|
@ -157,7 +157,10 @@ pub fn simplified_glue_type(tcx: ty::ctxt, field: uint, t: ty::t) -> ty::t {
|
|||
if (field == abi::tydesc_field_free_glue ||
|
||||
field == abi::tydesc_field_drop_glue) {
|
||||
match ty::get(t).sty {
|
||||
ty::ty_box(mt) |
|
||||
ty::ty_box(typ)
|
||||
if ! ty::type_needs_drop(tcx, typ) =>
|
||||
return ty::mk_imm_box(tcx, ty::mk_u32()),
|
||||
|
||||
ty::ty_evec(mt, ty::vstore_box)
|
||||
if ! ty::type_needs_drop(tcx, mt.ty) =>
|
||||
return ty::mk_imm_box(tcx, ty::mk_u32()),
|
||||
|
@ -356,10 +359,10 @@ pub fn make_free_glue(bcx: @Block, v: ValueRef, t: ty::t) -> @Block {
|
|||
// NB: v0 is an *alias* of type t here, not a direct value.
|
||||
let _icx = push_ctxt("make_free_glue");
|
||||
match ty::get(t).sty {
|
||||
ty::ty_box(body_mt) => {
|
||||
ty::ty_box(body_ty) => {
|
||||
let v = Load(bcx, v);
|
||||
let body = GEPi(bcx, v, [0u, abi::box_field_body]);
|
||||
let bcx = drop_ty(bcx, body, body_mt.ty);
|
||||
let bcx = drop_ty(bcx, body, body_ty);
|
||||
trans_free(bcx, v)
|
||||
}
|
||||
ty::ty_opaque_box => {
|
||||
|
|
|
@ -189,8 +189,11 @@ impl Reflector {
|
|||
self.visit(~"evec_" + name, extra)
|
||||
}
|
||||
}
|
||||
ty::ty_box(ref mt) => {
|
||||
let extra = self.c_mt(mt);
|
||||
ty::ty_box(typ) => {
|
||||
let extra = self.c_mt(&ty::mt {
|
||||
ty: typ,
|
||||
mutbl: ast::MutImmutable,
|
||||
});
|
||||
self.visit("box", extra)
|
||||
}
|
||||
ty::ty_uniq(ref mt) => {
|
||||
|
|
|
@ -236,8 +236,8 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
|
|||
let v_ty = Type::vec(cx.sess.targ_cfg.arch, &e_ty);
|
||||
Type::smart_ptr(cx, &v_ty).ptr_to()
|
||||
}
|
||||
ty::ty_box(ref mt) => {
|
||||
let ty = type_of(cx, mt.ty);
|
||||
ty::ty_box(typ) => {
|
||||
let ty = type_of(cx, typ);
|
||||
Type::smart_ptr(cx, &ty).ptr_to()
|
||||
}
|
||||
ty::ty_opaque_box => Type::opaque_box(cx).ptr_to(),
|
||||
|
|
|
@ -15,26 +15,15 @@
|
|||
//! `RUST_LOG=rustc::middle::trans::write_guard`).
|
||||
|
||||
|
||||
use lib::llvm::ValueRef;
|
||||
use middle::borrowck::{RootInfo, root_map_key, DynaImm, DynaMut};
|
||||
use middle::lang_items::CheckNotBorrowedFnLangItem;
|
||||
use middle::lang_items::{BorrowAsImmFnLangItem, BorrowAsMutFnLangItem};
|
||||
use middle::lang_items::{RecordBorrowFnLangItem, UnrecordBorrowFnLangItem};
|
||||
use middle::lang_items::ReturnToMutFnLangItem;
|
||||
use middle::borrowck::{RootInfo, root_map_key};
|
||||
use middle::trans::base::*;
|
||||
use middle::trans::build::*;
|
||||
use middle::trans::callee;
|
||||
use middle::trans::common::*;
|
||||
use middle::trans::datum::*;
|
||||
use middle::trans::expr;
|
||||
use middle::ty;
|
||||
use syntax::codemap::Span;
|
||||
use syntax::ast;
|
||||
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
pub fn root_and_write_guard(datum: &Datum,
|
||||
mut bcx: @Block,
|
||||
bcx: @Block,
|
||||
span: Span,
|
||||
expr_id: ast::NodeId,
|
||||
derefs: uint) -> @Block {
|
||||
|
@ -45,69 +34,16 @@ pub fn root_and_write_guard(datum: &Datum,
|
|||
//
|
||||
// (Note: root'd values are always boxes)
|
||||
let ccx = bcx.ccx();
|
||||
bcx = {
|
||||
let root_map = ccx.maps.root_map.borrow();
|
||||
match root_map.get().find(&key) {
|
||||
None => bcx,
|
||||
Some(&root_info) => root(datum, bcx, span, key, root_info)
|
||||
}
|
||||
};
|
||||
|
||||
// Perform the write guard, if necessary.
|
||||
//
|
||||
// (Note: write-guarded values are always boxes)
|
||||
let write_guard_map = ccx.maps.write_guard_map.borrow();
|
||||
if write_guard_map.get().contains(&key) {
|
||||
perform_write_guard(datum, bcx, span)
|
||||
} else {
|
||||
bcx
|
||||
let root_map = ccx.maps.root_map.borrow();
|
||||
match root_map.get().find(&key) {
|
||||
None => bcx,
|
||||
Some(&root_info) => root(datum, bcx, span, key, root_info)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn return_to_mut(mut bcx: @Block,
|
||||
root_key: root_map_key,
|
||||
frozen_val_ref: ValueRef,
|
||||
bits_val_ref: ValueRef,
|
||||
filename_val: ValueRef,
|
||||
line_val: ValueRef) -> @Block {
|
||||
debug!("write_guard::return_to_mut(root_key={:?}, {}, {}, {})",
|
||||
root_key,
|
||||
bcx.to_str(),
|
||||
bcx.val_to_str(frozen_val_ref),
|
||||
bcx.val_to_str(bits_val_ref));
|
||||
|
||||
let box_ptr = Load(bcx, PointerCast(bcx, frozen_val_ref, Type::i8p().ptr_to()));
|
||||
|
||||
let bits_val = Load(bcx, bits_val_ref);
|
||||
|
||||
if bcx.tcx().sess.debug_borrows() {
|
||||
bcx = callee::trans_lang_call( bcx,
|
||||
langcall(bcx, None, "unborrow", UnrecordBorrowFnLangItem),
|
||||
[
|
||||
box_ptr,
|
||||
bits_val,
|
||||
filename_val,
|
||||
line_val
|
||||
],
|
||||
Some(expr::Ignore)).bcx;
|
||||
}
|
||||
|
||||
callee::trans_lang_call(
|
||||
bcx,
|
||||
langcall(bcx, None, "unborrow", ReturnToMutFnLangItem),
|
||||
[
|
||||
box_ptr,
|
||||
bits_val,
|
||||
filename_val,
|
||||
line_val
|
||||
],
|
||||
Some(expr::Ignore)
|
||||
).bcx
|
||||
}
|
||||
|
||||
fn root(datum: &Datum,
|
||||
mut bcx: @Block,
|
||||
span: Span,
|
||||
bcx: @Block,
|
||||
_: Span,
|
||||
root_key: root_map_key,
|
||||
root_info: RootInfo) -> @Block {
|
||||
//! In some cases, borrowck will decide that an @T/@[]/@str
|
||||
|
@ -129,73 +65,6 @@ fn root(datum: &Datum,
|
|||
scratch.val,
|
||||
scratch.ty);
|
||||
|
||||
// Now, consider also freezing it.
|
||||
match root_info.freeze {
|
||||
None => {}
|
||||
Some(freeze_kind) => {
|
||||
let (filename, line) = filename_and_line_num_from_span(bcx, span);
|
||||
|
||||
// in this case, we don't have to zero, because
|
||||
// scratch.val will be NULL should the cleanup get
|
||||
// called without the freezing actually occurring, and
|
||||
// return_to_mut checks for this condition.
|
||||
let scratch_bits = scratch_datum(bcx, ty::mk_uint(),
|
||||
"__write_guard_bits", false);
|
||||
|
||||
let freeze_item = match freeze_kind {
|
||||
DynaImm => BorrowAsImmFnLangItem,
|
||||
DynaMut => BorrowAsMutFnLangItem,
|
||||
};
|
||||
|
||||
let box_ptr = Load(bcx, PointerCast(bcx, scratch.val, Type::i8p().ptr_to()));
|
||||
|
||||
let llresult = unpack_result!(bcx, callee::trans_lang_call(
|
||||
bcx,
|
||||
langcall(bcx, Some(span), "freeze", freeze_item),
|
||||
[
|
||||
box_ptr,
|
||||
filename,
|
||||
line
|
||||
],
|
||||
Some(expr::SaveIn(scratch_bits.val))));
|
||||
|
||||
if bcx.tcx().sess.debug_borrows() {
|
||||
bcx = callee::trans_lang_call(
|
||||
bcx,
|
||||
langcall(bcx, Some(span), "freeze", RecordBorrowFnLangItem),
|
||||
[
|
||||
box_ptr,
|
||||
llresult,
|
||||
filename,
|
||||
line
|
||||
],
|
||||
Some(expr::Ignore)).bcx;
|
||||
}
|
||||
|
||||
add_clean_return_to_mut(cleanup_bcx,
|
||||
root_info.scope,
|
||||
root_key,
|
||||
scratch.val,
|
||||
scratch_bits.val,
|
||||
filename,
|
||||
line);
|
||||
}
|
||||
}
|
||||
|
||||
bcx
|
||||
}
|
||||
|
||||
fn perform_write_guard(datum: &Datum,
|
||||
bcx: @Block,
|
||||
span: Span) -> @Block {
|
||||
debug!("perform_write_guard");
|
||||
|
||||
let llval = datum.to_value_llval(bcx);
|
||||
let (filename, line) = filename_and_line_num_from_span(bcx, span);
|
||||
|
||||
callee::trans_lang_call(
|
||||
bcx,
|
||||
langcall(bcx, Some(span), "write guard", CheckNotBorrowedFnLangItem),
|
||||
[PointerCast(bcx, llval, Type::i8p()), filename, line],
|
||||
Some(expr::Ignore)).bcx
|
||||
}
|
||||
|
|
|
@ -637,7 +637,7 @@ pub enum sty {
|
|||
ty_float(ast::float_ty),
|
||||
ty_estr(vstore),
|
||||
ty_enum(DefId, substs),
|
||||
ty_box(mt),
|
||||
ty_box(t),
|
||||
ty_uniq(mt),
|
||||
ty_evec(mt, vstore),
|
||||
ty_ptr(mt),
|
||||
|
@ -1102,8 +1102,9 @@ pub fn mk_t(cx: ctxt, st: sty) -> t {
|
|||
_ => {}
|
||||
}
|
||||
}
|
||||
&ty_box(ref m) | &ty_uniq(ref m) | &ty_evec(ref m, _) |
|
||||
&ty_ptr(ref m) | &ty_unboxed_vec(ref m) => {
|
||||
&ty_box(ref tt) => flags |= get(*tt).flags,
|
||||
&ty_uniq(ref m) | &ty_evec(ref m, _) | &ty_ptr(ref m) |
|
||||
&ty_unboxed_vec(ref m) => {
|
||||
flags |= get(m.ty).flags;
|
||||
}
|
||||
&ty_rptr(r, ref m) => {
|
||||
|
@ -1242,10 +1243,10 @@ pub fn mk_enum(cx: ctxt, did: ast::DefId, substs: substs) -> t {
|
|||
mk_t(cx, ty_enum(did, substs))
|
||||
}
|
||||
|
||||
pub fn mk_box(cx: ctxt, tm: mt) -> t { mk_t(cx, ty_box(tm)) }
|
||||
pub fn mk_box(cx: ctxt, ty: t) -> t { mk_t(cx, ty_box(ty)) }
|
||||
|
||||
pub fn mk_imm_box(cx: ctxt, ty: t) -> t {
|
||||
mk_box(cx, mt {ty: ty, mutbl: ast::MutImmutable})
|
||||
mk_box(cx, ty)
|
||||
}
|
||||
|
||||
pub fn mk_uniq(cx: ctxt, tm: mt) -> t { mk_t(cx, ty_uniq(tm)) }
|
||||
|
@ -1368,8 +1369,11 @@ pub fn maybe_walk_ty(ty: t, f: |t| -> bool) {
|
|||
ty_estr(_) | ty_type | ty_opaque_box | ty_self(_) |
|
||||
ty_opaque_closure_ptr(_) | ty_infer(_) | ty_param(_) | ty_err => {
|
||||
}
|
||||
ty_box(ref tm) | ty_evec(ref tm, _) | ty_unboxed_vec(ref tm) |
|
||||
ty_ptr(ref tm) | ty_rptr(_, ref tm) | ty_uniq(ref tm) => {
|
||||
ty_box(ref ty) => {
|
||||
maybe_walk_ty(*ty, f);
|
||||
}
|
||||
ty_evec(ref tm, _) | ty_unboxed_vec(ref tm) | ty_ptr(ref tm) |
|
||||
ty_rptr(_, ref tm) | ty_uniq(ref tm) => {
|
||||
maybe_walk_ty(tm.ty, f);
|
||||
}
|
||||
ty_enum(_, ref substs) | ty_struct(_, ref substs) |
|
||||
|
@ -2035,8 +2039,8 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
|
|||
closure_contents(cx, c)
|
||||
}
|
||||
|
||||
ty_box(mt) => {
|
||||
tc_mt(cx, mt, cache).managed_pointer()
|
||||
ty_box(typ) => {
|
||||
tc_ty(cx, typ, cache).managed_pointer()
|
||||
}
|
||||
|
||||
ty_trait(_, _, store, mutbl, bounds) => {
|
||||
|
@ -2334,7 +2338,9 @@ pub fn is_instantiable(cx: ctxt, r_ty: t) -> bool {
|
|||
ty_unboxed_vec(_) => {
|
||||
false
|
||||
}
|
||||
ty_box(ref mt) |
|
||||
ty_box(typ) => {
|
||||
type_requires(cx, seen, r_ty, typ)
|
||||
}
|
||||
ty_uniq(ref mt) |
|
||||
ty_rptr(_, ref mt) => {
|
||||
type_requires(cx, seen, r_ty, mt.ty)
|
||||
|
@ -2610,7 +2616,14 @@ pub fn deref(cx: ctxt, t: t, explicit: bool) -> Option<mt> {
|
|||
|
||||
pub fn deref_sty(cx: ctxt, sty: &sty, explicit: bool) -> Option<mt> {
|
||||
match *sty {
|
||||
ty_rptr(_, mt) | ty_box(mt) | ty_uniq(mt) => {
|
||||
ty_box(typ) => {
|
||||
Some(mt {
|
||||
ty: typ,
|
||||
mutbl: ast::MutImmutable,
|
||||
})
|
||||
}
|
||||
|
||||
ty_rptr(_, mt) | ty_uniq(mt) => {
|
||||
Some(mt)
|
||||
}
|
||||
|
||||
|
@ -4818,9 +4831,8 @@ pub fn hash_crate_independent(tcx: ctxt, t: t, local_hash: @str) -> u64 {
|
|||
hash.input([8]);
|
||||
did(&mut hash, d);
|
||||
}
|
||||
ty_box(m) => {
|
||||
ty_box(_) => {
|
||||
hash.input([9]);
|
||||
mt(&mut hash, m);
|
||||
}
|
||||
ty_uniq(m) => {
|
||||
hash.input([10]);
|
||||
|
|
|
@ -140,8 +140,8 @@ pub fn super_fold_mt<T:TypeFolder>(this: &mut T,
|
|||
pub fn super_fold_sty<T:TypeFolder>(this: &mut T,
|
||||
sty: &ty::sty) -> ty::sty {
|
||||
match *sty {
|
||||
ty::ty_box(ref tm) => {
|
||||
ty::ty_box(this.fold_mt(tm))
|
||||
ty::ty_box(typ) => {
|
||||
ty::ty_box(this.fold_ty(typ))
|
||||
}
|
||||
ty::ty_uniq(ref tm) => {
|
||||
ty::ty_uniq(this.fold_mt(tm))
|
||||
|
|
|
@ -402,8 +402,9 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
|
|||
ast::ty_nil => ty::mk_nil(),
|
||||
ast::ty_bot => ty::mk_bot(),
|
||||
ast::ty_box(ref mt) => {
|
||||
mk_pointer(this, rscope, mt, ty::vstore_box,
|
||||
|tmt| ty::mk_box(tcx, tmt))
|
||||
let mt = ast::mt { ty: mt.ty, mutbl: ast::MutImmutable };
|
||||
mk_pointer(this, rscope, &mt, ty::vstore_box,
|
||||
|tmt| ty::mk_box(tcx, tmt.ty))
|
||||
}
|
||||
ast::ty_uniq(ty) => {
|
||||
let mt = ast::mt { ty: ty, mutbl: ast::MutImmutable };
|
||||
|
@ -689,10 +690,8 @@ fn ty_of_method_or_bare_fn<AC:AstConv>(
|
|||
ty::mt {ty: self_info.untransformed_self_ty,
|
||||
mutbl: mutability}))
|
||||
}
|
||||
ast::sty_box(mutability) => {
|
||||
Some(ty::mk_box(this.tcx(),
|
||||
ty::mt {ty: self_info.untransformed_self_ty,
|
||||
mutbl: mutability}))
|
||||
ast::sty_box(_) => {
|
||||
Some(ty::mk_box(this.tcx(), self_info.untransformed_self_ty))
|
||||
}
|
||||
ast::sty_uniq(_) => {
|
||||
Some(ty::mk_uniq(this.tcx(),
|
||||
|
|
|
@ -667,8 +667,8 @@ pub fn check_pointer_pat(pcx: &pat_ctxt,
|
|||
span: Span,
|
||||
expected: ty::t) {
|
||||
let fcx = pcx.fcx;
|
||||
let check_inner: |ty::mt| = |e_inner| {
|
||||
check_pat(pcx, inner, e_inner.ty);
|
||||
let check_inner: |ty::t| = |e_inner| {
|
||||
check_pat(pcx, inner, e_inner);
|
||||
fcx.write_ty(pat_id, expected);
|
||||
};
|
||||
match *structure_of(fcx, span, expected) {
|
||||
|
@ -676,10 +676,10 @@ pub fn check_pointer_pat(pcx: &pat_ctxt,
|
|||
check_inner(e_inner);
|
||||
}
|
||||
ty::ty_uniq(e_inner) if pointer_kind == Send => {
|
||||
check_inner(e_inner);
|
||||
check_inner(e_inner.ty);
|
||||
}
|
||||
ty::ty_rptr(_, e_inner) if pointer_kind == Borrowed => {
|
||||
check_inner(e_inner);
|
||||
check_inner(e_inner.ty);
|
||||
}
|
||||
_ => {
|
||||
check_pat(pcx, inner, ty::mk_err());
|
||||
|
|
|
@ -1092,9 +1092,9 @@ impl<'a> LookupContext<'a> {
|
|||
substs, RegionTraitStore(r), mt.mutbl,
|
||||
ty::EmptyBuiltinBounds())
|
||||
}
|
||||
ty::ty_box(mt) => { // must be sty_box
|
||||
ty::ty_box(_) => { // must be sty_box
|
||||
ty::mk_trait(self.tcx(), trait_def_id,
|
||||
substs, BoxTraitStore, mt.mutbl,
|
||||
substs, BoxTraitStore, ast::MutImmutable,
|
||||
ty::EmptyBuiltinBounds())
|
||||
}
|
||||
ty::ty_uniq(mt) => { // must be sty_uniq
|
||||
|
@ -1224,9 +1224,8 @@ impl<'a> LookupContext<'a> {
|
|||
sty_box(m) => {
|
||||
debug!("(is relevant?) explicit self is a box");
|
||||
match ty::get(rcvr_ty).sty {
|
||||
ty::ty_box(mt) => {
|
||||
mutability_matches(mt.mutbl, m) &&
|
||||
rcvr_matches_ty(self.fcx, mt.ty, candidate)
|
||||
ty::ty_box(typ) => {
|
||||
rcvr_matches_ty(self.fcx, typ, candidate)
|
||||
}
|
||||
|
||||
ty::ty_trait(self_did, _, BoxTraitStore, self_m, _) => {
|
||||
|
|
|
@ -1330,8 +1330,7 @@ pub fn do_autoderef(fcx: @FnCtxt, sp: Span, t: ty::t) -> (ty::t, uint) {
|
|||
|
||||
// Some extra checks to detect weird cycles and so forth:
|
||||
match *sty {
|
||||
ty::ty_box(inner) | ty::ty_uniq(inner) |
|
||||
ty::ty_rptr(_, inner) => {
|
||||
ty::ty_box(inner) => {
|
||||
match ty::get(t1).sty {
|
||||
ty::ty_infer(ty::TyVar(v1)) => {
|
||||
ty::occurs_check(fcx.ccx.tcx, sp, v1,
|
||||
|
@ -1340,6 +1339,15 @@ pub fn do_autoderef(fcx: @FnCtxt, sp: Span, t: ty::t) -> (ty::t, uint) {
|
|||
_ => ()
|
||||
}
|
||||
}
|
||||
ty::ty_uniq(inner) | ty::ty_rptr(_, inner) => {
|
||||
match ty::get(t1).sty {
|
||||
ty::ty_infer(ty::TyVar(v1)) => {
|
||||
ty::occurs_check(fcx.ccx.tcx, sp, v1,
|
||||
ty::mk_box(fcx.ccx.tcx, inner.ty));
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
ty::ty_enum(ref did, _) => {
|
||||
// Watch out for a type like `enum t = @t`. Such a
|
||||
// type would otherwise infinitely auto-deref. Only
|
||||
|
@ -2734,7 +2742,8 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
|
|||
let exp_inner = unpack_expected(fcx, expected, |sty| {
|
||||
match unop {
|
||||
ast::UnBox(_) | ast::UnUniq => match *sty {
|
||||
ty::ty_box(ref mt) | ty::ty_uniq(ref mt) => Some(mt.ty),
|
||||
ty::ty_box(ty) => Some(ty),
|
||||
ty::ty_uniq(ref mt) => Some(mt.ty),
|
||||
_ => None
|
||||
},
|
||||
ast::UnNot | ast::UnNeg => expected,
|
||||
|
@ -2746,9 +2755,8 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
|
|||
if !ty::type_is_error(oprnd_t) &&
|
||||
!ty::type_is_bot(oprnd_t) {
|
||||
match unop {
|
||||
ast::UnBox(mutbl) => {
|
||||
oprnd_t = ty::mk_box(tcx,
|
||||
ty::mt {ty: oprnd_t, mutbl: mutbl});
|
||||
ast::UnBox(_) => {
|
||||
oprnd_t = ty::mk_box(tcx, oprnd_t)
|
||||
}
|
||||
ast::UnUniq => {
|
||||
oprnd_t = ty::mk_uniq(tcx,
|
||||
|
|
|
@ -582,7 +582,13 @@ pub fn early_resolve_expr(ex: @ast::Expr,
|
|||
let ty = structurally_resolved_type(fcx, ex.span,
|
||||
fcx.expr_ty(src));
|
||||
match (&ty::get(ty).sty, store) {
|
||||
(&ty::ty_box(mt), ty::BoxTraitStore) |
|
||||
(&ty::ty_box(..), ty::BoxTraitStore)
|
||||
if !mutability_allowed(ast::MutImmutable,
|
||||
target_mutbl) => {
|
||||
fcx.tcx().sess.span_err(ex.span,
|
||||
format!("types differ in mutability"));
|
||||
}
|
||||
|
||||
(&ty::ty_uniq(mt), ty::UniqTraitStore) |
|
||||
(&ty::ty_rptr(_, mt), ty::RegionTraitStore(..))
|
||||
if !mutability_allowed(mt.mutbl, target_mutbl) => {
|
||||
|
@ -590,9 +596,15 @@ pub fn early_resolve_expr(ex: @ast::Expr,
|
|||
format!("types differ in mutability"));
|
||||
}
|
||||
|
||||
(&ty::ty_box(mt), ty::BoxTraitStore) |
|
||||
(&ty::ty_uniq(mt), ty::UniqTraitStore) |
|
||||
(&ty::ty_rptr(_, mt), ty::RegionTraitStore(..)) => {
|
||||
(&ty::ty_box(..), ty::BoxTraitStore) |
|
||||
(&ty::ty_uniq(..), ty::UniqTraitStore) |
|
||||
(&ty::ty_rptr(..), ty::RegionTraitStore(..)) => {
|
||||
let typ = match (&ty::get(ty).sty) {
|
||||
&ty::ty_box(typ) => typ,
|
||||
&ty::ty_uniq(mt) | &ty::ty_rptr(_, mt) => mt.ty,
|
||||
_ => fail!("shouldn't get here"),
|
||||
};
|
||||
|
||||
let location_info =
|
||||
&location_info_for_expr(ex);
|
||||
let vcx = fcx.vtable_context();
|
||||
|
@ -601,7 +613,7 @@ pub fn early_resolve_expr(ex: @ast::Expr,
|
|||
substs: ty::substs {
|
||||
tps: target_substs.tps.clone(),
|
||||
regions: target_substs.regions.clone(),
|
||||
self_ty: Some(mt.ty)
|
||||
self_ty: Some(typ)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -614,7 +626,7 @@ pub fn early_resolve_expr(ex: @ast::Expr,
|
|||
location_info,
|
||||
None,
|
||||
¶m_bounds,
|
||||
mt.ty,
|
||||
typ,
|
||||
is_early);
|
||||
|
||||
if !is_early {
|
||||
|
|
|
@ -241,7 +241,7 @@ impl Coerce {
|
|||
let r_borrow = self.infcx.next_region_var(Coercion(self.trace));
|
||||
|
||||
let inner_ty = match *sty_a {
|
||||
ty::ty_box(mt_a) => mt_a.ty,
|
||||
ty::ty_box(typ) => typ,
|
||||
ty::ty_uniq(mt_a) => mt_a.ty,
|
||||
ty::ty_rptr(_, mt_a) => mt_a.ty,
|
||||
_ => {
|
||||
|
|
|
@ -515,8 +515,8 @@ pub fn super_tys<C:Combine>(this: &C, a: ty::t, b: ty::t) -> cres<ty::t> {
|
|||
Ok(ty::mk_struct(tcx, a_id, substs))
|
||||
}
|
||||
|
||||
(&ty::ty_box(ref a_mt), &ty::ty_box(ref b_mt)) => {
|
||||
this.mts(a_mt, b_mt).and_then(|mt| Ok(ty::mk_box(tcx, mt)))
|
||||
(&ty::ty_box(a_inner), &ty::ty_box(b_inner)) => {
|
||||
this.tys(a_inner, b_inner).and_then(|typ| Ok(ty::mk_box(tcx, typ)))
|
||||
}
|
||||
|
||||
(&ty::ty_uniq(ref a_mt), &ty::ty_uniq(ref b_mt)) => {
|
||||
|
|
|
@ -637,7 +637,10 @@ impl<'a> ConstraintContext<'a> {
|
|||
self.add_constraints_from_mt(mt, variance);
|
||||
}
|
||||
|
||||
ty::ty_box(ref mt) |
|
||||
ty::ty_box(typ) => {
|
||||
self.add_constraints_from_ty(typ, variance);
|
||||
}
|
||||
|
||||
ty::ty_uniq(ref mt) |
|
||||
ty::ty_ptr(ref mt) => {
|
||||
self.add_constraints_from_mt(mt, variance);
|
||||
|
|
|
@ -454,7 +454,7 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str {
|
|||
ty_uint(ast::ty_u) => ~"uint",
|
||||
ty_uint(t) => ast_util::uint_ty_to_str(t),
|
||||
ty_float(t) => ast_util::float_ty_to_str(t),
|
||||
ty_box(ref tm) => ~"@" + mt_to_str(cx, tm),
|
||||
ty_box(typ) => ~"@" + ty_to_str(cx, typ),
|
||||
ty_uniq(ref tm) => ~"~" + mt_to_str(cx, tm),
|
||||
ty_ptr(ref tm) => ~"*" + mt_to_str(cx, tm),
|
||||
ty_rptr(r, ref tm) => {
|
||||
|
|
|
@ -95,7 +95,7 @@ pub fn path_elt_to_str(pe: path_elt, itr: @ident_interner) -> ~str {
|
|||
fn pretty_ty(ty: &Ty, itr: @ident_interner, out: &mut ~str) {
|
||||
let (prefix, subty) = match ty.node {
|
||||
ty_uniq(ty) => ("$UP$", &*ty),
|
||||
ty_box(mt { ty, .. }) => ("$SP$", &*ty),
|
||||
ty_box(ty) => ("$SP$", &*ty),
|
||||
ty_ptr(mt { ty, mutbl }) => (if mutbl == MutMutable {"$RPmut$"} else {"$RP$"},
|
||||
&*ty),
|
||||
ty_rptr(_, mt { ty, mutbl }) => (if mutbl == MutMutable {"$BPmut$"} else {"$BP$"},
|
||||
|
|
Loading…
Reference in New Issue