librustc: Remove `@mut` support from the typechecker and borrow checker

This commit is contained in:
Patrick Walton 2013-12-30 18:57:48 -08:00
parent 9b35ae75d2
commit 88281290ff
32 changed files with 170 additions and 462 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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(_) => ~"*"
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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,
&param_bounds,
mt.ty,
typ,
is_early);
if !is_early {

View File

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

View File

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

View File

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

View File

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

View File

@ -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$"},