提交 5c350479 编写于 作者: P Patrick Walton

librustc: Remove `&const` and `*const` from the language.

They are still present as part of the borrow check.
上级 58d6eb50
......@@ -25,13 +25,13 @@ pub mod rustrt {
#[link_name = "rustrt"]
extern {
pub fn tdefl_compress_mem_to_heap(psrc_buf: *const c_void,
pub fn tdefl_compress_mem_to_heap(psrc_buf: *c_void,
src_buf_len: size_t,
pout_len: *mut size_t,
flags: c_int)
-> *c_void;
pub fn tinfl_decompress_mem_to_heap(psrc_buf: *const c_void,
pub fn tinfl_decompress_mem_to_heap(psrc_buf: *c_void,
src_buf_len: size_t,
pout_len: *mut size_t,
flags: c_int)
......
......@@ -804,12 +804,9 @@ pub fn get_enum_variants(intr: @ident_interner, cdata: cmd, id: ast::NodeId,
fn get_explicit_self(item: ebml::Doc) -> ast::explicit_self_ {
fn get_mutability(ch: u8) -> ast::mutability {
match ch as char {
'i' => { ast::m_imm }
'm' => { ast::m_mutbl }
'c' => { ast::m_const }
_ => {
fail!("unknown mutability character: `%c`", ch as char)
}
'i' => ast::m_imm,
'm' => ast::m_mutbl,
_ => fail!("unknown mutability character: `%c`", ch as char),
}
}
......
......@@ -635,15 +635,8 @@ fn encode_explicit_self(ebml_w: &mut writer::Encoder, explicit_self: ast::explic
fn encode_mutability(ebml_w: &writer::Encoder,
m: ast::mutability) {
match m {
m_imm => {
ebml_w.writer.write(&[ 'i' as u8 ]);
}
m_mutbl => {
ebml_w.writer.write(&[ 'm' as u8 ]);
}
m_const => {
ebml_w.writer.write(&[ 'c' as u8 ]);
}
m_imm => ebml_w.writer.write(&[ 'i' as u8 ]),
m_mutbl => ebml_w.writer.write(&[ 'm' as u8 ]),
}
}
}
......
......@@ -417,7 +417,6 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
fn parse_mutability(st: &mut PState) -> ast::mutability {
match peek(st) {
'm' => { next(st); ast::m_mutbl }
'?' => { next(st); ast::m_const }
_ => { ast::m_imm }
}
}
......
......@@ -99,7 +99,6 @@ fn enc_mutability(w: @io::Writer, mt: ast::mutability) {
match mt {
m_imm => (),
m_mutbl => w.write_char('m'),
m_const => w.write_char('?')
}
}
......
......@@ -23,7 +23,7 @@
use middle::borrowck::*;
use middle::moves;
use middle::ty;
use syntax::ast::{m_mutbl, m_imm, m_const};
use syntax::ast::m_mutbl;
use syntax::ast;
use syntax::ast_util;
use syntax::codemap::span;
......@@ -220,9 +220,9 @@ pub fn report_error_if_loan_conflicts_with_restriction(&self,
// Restrictions that would cause the new loan to be illegal:
let illegal_if = match loan2.mutbl {
m_mutbl => RESTR_ALIAS | RESTR_FREEZE | RESTR_CLAIM,
m_imm => RESTR_ALIAS | RESTR_FREEZE,
m_const => RESTR_ALIAS,
MutableMutability => RESTR_ALIAS | RESTR_FREEZE | RESTR_CLAIM,
ImmutableMutability => RESTR_ALIAS | RESTR_FREEZE,
ConstMutability => RESTR_ALIAS,
};
debug!("illegal_if=%?", illegal_if);
......@@ -231,7 +231,7 @@ pub fn report_error_if_loan_conflicts_with_restriction(&self,
if restr.loan_path != loan2.loan_path { loop; }
match (new_loan.mutbl, old_loan.mutbl) {
(m_mutbl, m_mutbl) => {
(MutableMutability, MutableMutability) => {
self.bccx.span_err(
new_loan.span,
fmt!("cannot borrow `%s` as mutable \
......@@ -582,7 +582,6 @@ fn check_for_assignment_to_restricted_or_frozen_location(
// Otherwise stop iterating
LpExtend(_, mc::McDeclared, _) |
LpExtend(_, mc::McImmutable, _) |
LpExtend(_, mc::McReadOnly, _) |
LpVar(_) => {
return true;
}
......@@ -590,8 +589,11 @@ fn check_for_assignment_to_restricted_or_frozen_location(
// Check for a non-const loan of `loan_path`
let cont = do this.each_in_scope_loan(expr.id) |loan| {
if loan.loan_path == loan_path && loan.mutbl != m_const {
this.report_illegal_mutation(expr, full_loan_path, loan);
if loan.loan_path == loan_path &&
loan.mutbl != ConstMutability {
this.report_illegal_mutation(expr,
full_loan_path,
loan);
false
} else {
true
......
......@@ -15,7 +15,7 @@
use middle::borrowck::*;
use mc = middle::mem_categorization;
use middle::ty;
use syntax::ast::{m_const, m_imm, m_mutbl};
use syntax::ast::{m_imm, m_mutbl};
use syntax::ast;
use syntax::codemap::span;
use util::ppaux::{note_and_explain_region};
......@@ -26,7 +26,7 @@ pub fn guarantee_lifetime(bccx: @BorrowckCtxt,
span: span,
cmt: mc::cmt,
loan_region: ty::Region,
loan_mutbl: ast::mutability) {
loan_mutbl: LoanMutability) {
debug!("guarantee_lifetime(cmt=%s, loan_region=%s)",
cmt.repr(bccx.tcx), loan_region.repr(bccx.tcx));
let ctxt = GuaranteeLifetimeContext {bccx: bccx,
......@@ -54,7 +54,7 @@ struct GuaranteeLifetimeContext {
span: span,
loan_region: ty::Region,
loan_mutbl: ast::mutability,
loan_mutbl: LoanMutability,
cmt_original: mc::cmt
}
......@@ -235,11 +235,11 @@ fn check_root(&self,
// we need to dynamically mark it to prevent incompatible
// borrows from happening later.
let opt_dyna = match ptr_mutbl {
m_imm | m_const => None,
m_imm => None,
m_mutbl => {
match self.loan_mutbl {
m_mutbl => Some(DynaMut),
m_imm | m_const => Some(DynaImm)
MutableMutability => Some(DynaMut),
ImmutableMutability | ConstMutability => Some(DynaImm)
}
}
};
......
......@@ -26,7 +26,6 @@
use util::common::indenter;
use util::ppaux::{Repr};
use syntax::ast::{m_const, m_imm, m_mutbl};
use syntax::ast;
use syntax::ast_util::id_range;
use syntax::codemap::span;
......@@ -237,7 +236,11 @@ fn gather_loans_in_expr(v: &mut GatherLoanVisitor,
// make sure that the thing we are pointing out stays valid
// for the lifetime `scope_r` of the resulting ptr:
let scope_r = ty_region(tcx, ex.span, ty::expr_ty(tcx, ex));
this.guarantee_valid(ex.id, ex.span, base_cmt, mutbl, scope_r);
this.guarantee_valid(ex.id,
ex.span,
base_cmt,
LoanMutability::from_ast_mutability(mutbl),
scope_r);
visit::walk_expr(v, ex, this);
}
......@@ -278,7 +281,11 @@ fn gather_loans_in_expr(v: &mut GatherLoanVisitor,
// adjustments).
let scope_r = ty::re_scope(ex.id);
let arg_cmt = this.bccx.cat_expr(arg);
this.guarantee_valid(arg.id, arg.span, arg_cmt, m_imm, scope_r);
this.guarantee_valid(arg.id,
arg.span,
arg_cmt,
ImmutableMutability,
scope_r);
visit::walk_expr(v, ex, this);
}
......@@ -357,18 +364,22 @@ pub fn guarantee_adjustments(&mut self,
match *autoref {
ty::AutoPtr(r, m) => {
let loan_mutability =
LoanMutability::from_ast_mutability(m);
self.guarantee_valid(expr.id,
expr.span,
cmt,
m,
loan_mutability,
r)
}
ty::AutoBorrowVec(r, m) | ty::AutoBorrowVecRef(r, m) => {
let cmt_index = mcx.cat_index(expr, cmt, autoderefs+1);
let loan_mutability =
LoanMutability::from_ast_mutability(m);
self.guarantee_valid(expr.id,
expr.span,
cmt_index,
m,
loan_mutability,
r)
}
ty::AutoBorrowFn(r) => {
......@@ -376,7 +387,7 @@ pub fn guarantee_adjustments(&mut self,
self.guarantee_valid(expr.id,
expr.span,
cmt_deref,
m_imm,
ImmutableMutability,
r)
}
ty::AutoBorrowObj(r, m) => {
......@@ -402,7 +413,7 @@ pub fn guarantee_valid(&mut self,
borrow_id: ast::NodeId,
borrow_span: span,
cmt: mc::cmt,
req_mutbl: ast::mutability,
req_mutbl: LoanMutability,
loan_region: ty::Region) {
debug!("guarantee_valid(borrow_id=%?, cmt=%s, \
req_mutbl=%?, loan_region=%?)",
......@@ -473,7 +484,7 @@ pub fn guarantee_valid(&mut self,
let kill_scope = self.compute_kill_scope(loan_scope, loan_path);
debug!("kill_scope = %?", kill_scope);
if req_mutbl == m_mutbl {
if req_mutbl == MutableMutability {
self.mark_loan_path_as_mutated(loan_path);
}
......@@ -516,7 +527,7 @@ pub fn guarantee_valid(&mut self,
// index: all_loans.len(),
// loan_path: loan_path,
// cmt: cmt,
// mutbl: m_const,
// mutbl: ConstMutability,
// gen_scope: borrow_id,
// kill_scope: kill_scope,
// span: borrow_span,
......@@ -527,29 +538,20 @@ pub fn guarantee_valid(&mut self,
fn check_mutability(bccx: @BorrowckCtxt,
borrow_span: span,
cmt: mc::cmt,
req_mutbl: ast::mutability) {
req_mutbl: LoanMutability) {
//! Implements the M-* rules in doc.rs.
match req_mutbl {
m_const => {
ConstMutability => {
// Data of any mutability can be lent as const.
}
m_imm => {
match cmt.mutbl {
mc::McImmutable | mc::McDeclared | mc::McInherited => {
// both imm and mut data can be lent as imm;
// for mutable data, this is a freeze
}
mc::McReadOnly => {
bccx.report(BckError {span: borrow_span,
cmt: cmt,
code: err_mutbl(req_mutbl)});
}
}
ImmutableMutability => {
// both imm and mut data can be lent as imm;
// for mutable data, this is a freeze
}
m_mutbl => {
MutableMutability => {
// Only mutable data can be lent as mutable.
if !cmt.mutbl.is_mutable() {
bccx.report(BckError {span: borrow_span,
......@@ -561,12 +563,14 @@ fn check_mutability(bccx: @BorrowckCtxt,
}
}
pub fn restriction_set(&self, req_mutbl: ast::mutability)
pub fn restriction_set(&self, req_mutbl: LoanMutability)
-> RestrictionSet {
match req_mutbl {
m_const => RESTR_EMPTY,
m_imm => RESTR_EMPTY | RESTR_MUTATE | RESTR_CLAIM,
m_mutbl => RESTR_EMPTY | RESTR_MUTATE | RESTR_CLAIM | RESTR_FREEZE
ConstMutability => RESTR_EMPTY,
ImmutableMutability => RESTR_EMPTY | RESTR_MUTATE | RESTR_CLAIM,
MutableMutability => {
RESTR_EMPTY | RESTR_MUTATE | RESTR_CLAIM | RESTR_FREEZE
}
}
}
......@@ -582,8 +586,8 @@ pub fn mark_loan_path_as_mutated(&self, loan_path: @LoanPath) {
self.mark_loan_path_as_mutated(base);
}
LpExtend(_, mc::McDeclared, _) |
LpExtend(_, mc::McImmutable, _) |
LpExtend(_, mc::McReadOnly, _) => {
LpExtend(_, mc::McImmutable, _) => {
// Nothing to do.
}
}
}
......@@ -701,8 +705,13 @@ fn gather_pat(&mut self,
}
}
};
self.guarantee_valid(pat.id, pat.span,
cmt_discr, mutbl, scope_r);
let loan_mutability =
LoanMutability::from_ast_mutability(mutbl);
self.guarantee_valid(pat.id,
pat.span,
cmt_discr,
loan_mutability,
scope_r);
}
ast::bind_infer => {
// No borrows here, but there may be moves
......@@ -725,6 +734,8 @@ fn gather_pat(&mut self,
self.vec_slice_info(slice_pat, slice_ty);
let mcx = self.bccx.mc_ctxt();
let cmt_index = mcx.cat_index(slice_pat, cmt, 0);
let slice_loan_mutability =
LoanMutability::from_ast_mutability(slice_mutbl);
// Note: We declare here that the borrow occurs upon
// entering the `[...]` pattern. This implies that
......@@ -743,8 +754,11 @@ fn gather_pat(&mut self,
// trans do the right thing, and it would only work
// for `~` vectors. It seems simpler to just require
// that people call `vec.pop()` or `vec.unshift()`.
self.guarantee_valid(pat.id, pat.span,
cmt_index, slice_mutbl, slice_r);
self.guarantee_valid(pat.id,
pat.span,
cmt_index,
slice_loan_mutability,
slice_r);
}
_ => {}
......
......@@ -15,7 +15,7 @@
use middle::borrowck::*;
use mc = middle::mem_categorization;
use middle::ty;
use syntax::ast::{m_const, m_imm, m_mutbl};
use syntax::ast::{m_imm, m_mutbl};
use syntax::codemap::span;
pub enum RestrictionResult {
......@@ -121,13 +121,6 @@ fn restrict(&self,
Safe
}
mc::cat_deref(_, _, mc::region_ptr(m_const, _)) |
mc::cat_deref(_, _, mc::gc_ptr(m_const)) => {
// R-Deref-Freeze-Borrowed
self.check_no_mutability_control(cmt, restrictions);
Safe
}
mc::cat_deref(cmt_base, _, pk @ mc::gc_ptr(m_mutbl)) => {
// R-Deref-Managed-Borrowed
//
......
......@@ -241,12 +241,39 @@ pub enum PartialTotal {
///////////////////////////////////////////////////////////////////////////
// Loans and loan paths
#[deriving(Clone, Eq)]
pub enum LoanMutability {
ImmutableMutability,
ConstMutability,
MutableMutability,
}
impl LoanMutability {
pub fn from_ast_mutability(ast_mutability: ast::mutability)
-> LoanMutability {
match ast_mutability {
ast::m_imm => ImmutableMutability,
ast::m_mutbl => MutableMutability,
}
}
}
impl ToStr for LoanMutability {
fn to_str(&self) -> ~str {
match *self {
ImmutableMutability => ~"immutable",
ConstMutability => ~"read-only",
MutableMutability => ~"mutable",
}
}
}
/// Record of a loan that was issued.
pub struct Loan {
index: uint,
loan_path: @LoanPath,
cmt: mc::cmt,
mutbl: ast::mutability,
mutbl: LoanMutability,
restrictions: ~[Restriction],
gen_scope: ast::NodeId,
kill_scope: ast::NodeId,
......@@ -417,7 +444,7 @@ fn to_str(&self) -> ~str {
// Errors that can occur
#[deriving(Eq)]
pub enum bckerr_code {
err_mutbl(ast::mutability),
err_mutbl(LoanMutability),
err_out_of_root_scope(ty::Region, ty::Region), // superscope, subscope
err_out_of_scope(ty::Region, ty::Region), // superscope, subscope
err_freeze_aliasable_const
......@@ -794,17 +821,14 @@ pub fn cmt_to_str(&self, cmt: mc::cmt) -> ~str {
mc.cmt_to_str(cmt)
}
pub fn mut_to_str(&self, mutbl: ast::mutability) -> ~str {
let mc = &mc::mem_categorization_ctxt {tcx: self.tcx,
method_map: self.method_map};
mc.mut_to_str(mutbl)
pub fn mut_to_str(&self, mutbl: LoanMutability) -> ~str {
mutbl.to_str()
}
pub fn mut_to_keyword(&self, mutbl: ast::mutability) -> &'static str {
match mutbl {
ast::m_imm => "",
ast::m_const => "const",
ast::m_mutbl => "mut"
ast::m_mutbl => "mut",
}
}
}
......
......@@ -52,7 +52,7 @@
use util::ppaux::{ty_to_str, region_ptr_to_str, Repr};
use util::common::indenter;
use syntax::ast::{m_imm, m_const, m_mutbl};
use syntax::ast::{m_imm, m_mutbl};
use syntax::ast;
use syntax::codemap::span;
use syntax::print::pprust;
......@@ -113,7 +113,6 @@ pub enum ElementKind {
#[deriving(Eq, IterBytes)]
pub enum MutabilityCategory {
McImmutable, // Immutable.
McReadOnly, // Read-only (`const`)
McDeclared, // Directly declared as mutable.
McInherited // Inherited from the fact that owner is mutable.
}
......@@ -297,7 +296,6 @@ impl MutabilityCategory {
pub fn from_mutbl(m: ast::mutability) -> MutabilityCategory {
match m {
m_imm => McImmutable,
m_const => McReadOnly,
m_mutbl => McDeclared
}
}
......@@ -305,7 +303,6 @@ pub fn from_mutbl(m: ast::mutability) -> MutabilityCategory {
pub fn inherit(&self) -> MutabilityCategory {
match *self {
McImmutable => McImmutable,
McReadOnly => McReadOnly,
McDeclared => McInherited,
McInherited => McInherited
}
......@@ -313,7 +310,7 @@ pub fn inherit(&self) -> MutabilityCategory {
pub fn is_mutable(&self) -> bool {
match *self {
McImmutable | McReadOnly => false,
McImmutable => false,
McDeclared | McInherited => true
}
}
......@@ -321,7 +318,7 @@ pub fn is_mutable(&self) -> bool {
pub fn is_immutable(&self) -> bool {
match *self {
McImmutable => true,
McReadOnly | McDeclared | McInherited => false
McDeclared | McInherited => false
}
}
......@@ -329,7 +326,6 @@ pub fn to_user_str(&self) -> &'static str {
match *self {
McDeclared | McInherited => "mutable",
McImmutable => "immutable",
McReadOnly => "const"
}
}
}
......@@ -610,7 +606,6 @@ pub fn inherited_mutability(&self,
-> MutabilityCategory {
match interior_m {
m_imm => base_m.inherit(),
m_const => McReadOnly,
m_mutbl => McDeclared
}
}
......@@ -999,7 +994,6 @@ pub fn cat_pattern(&self,
pub fn mut_to_str(&self, mutbl: ast::mutability) -> ~str {
match mutbl {
m_mutbl => ~"mutable",
m_const => ~"const",
m_imm => ~"immutable"
}
}
......@@ -1164,7 +1158,6 @@ pub fn freely_aliasable(&self) -> Option<AliasableReason> {
Some(AliasableManaged(m))
}
cat_deref(_, _, region_ptr(m @ m_const, _)) |
cat_deref(_, _, region_ptr(m @ m_imm, _)) => {
Some(AliasableBorrowed(m))
}
......
......@@ -272,8 +272,7 @@ fn mk_pointer<AC:AstConv,RS:region_scope + Clone + 'static>(
match a_seq_ty.ty.node {
ast::ty_vec(ref mt) => {
let mut mt = ast_mt_to_mt(this, rscope, mt);
if a_seq_ty.mutbl == ast::m_mutbl ||
a_seq_ty.mutbl == ast::m_const {
if a_seq_ty.mutbl == ast::m_mutbl {
mt = ty::mt { ty: mt.ty, mutbl: a_seq_ty.mutbl };
}
return ty::mk_evec(tcx, mt, vst);
......
......@@ -102,7 +102,7 @@ trait `ToStr` imported, and I call `to_str()` on a value of type `T`,
use extra::list::Nil;
use syntax::ast::{def_id, sty_value, sty_region, sty_box};
use syntax::ast::{sty_uniq, sty_static, NodeId};
use syntax::ast::{m_const, m_mutbl, m_imm};
use syntax::ast::{m_mutbl, m_imm};
use syntax::ast;
use syntax::ast_map;
......@@ -700,7 +700,7 @@ fn search_for_autosliced_method(&self,
ty_evec(mt, vstore_fixed(_)) => {
// First try to borrow to a slice
let entry = self.search_for_some_kind_of_autorefd_method(
AutoBorrowVec, autoderefs, [m_const, m_imm, m_mutbl],
AutoBorrowVec, autoderefs, [m_imm, m_mutbl],
|m,r| ty::mk_evec(tcx,
ty::mt {ty:mt.ty, mutbl:m},
vstore_slice(r)));
......@@ -709,7 +709,7 @@ fn search_for_autosliced_method(&self,
// Then try to borrow to a slice *and* borrow a pointer.
self.search_for_some_kind_of_autorefd_method(
AutoBorrowVecRef, autoderefs, [m_const, m_imm, m_mutbl],
AutoBorrowVecRef, autoderefs, [m_imm, m_mutbl],
|m,r| {
let slice_ty = ty::mk_evec(tcx,
ty::mt {ty:mt.ty, mutbl:m},
......@@ -744,7 +744,7 @@ fn search_for_autosliced_method(&self,
// Coerce ~/@/&Trait instances to &Trait.
self.search_for_some_kind_of_autorefd_method(
AutoBorrowObj, autoderefs, [m_const, m_imm, m_mutbl],
AutoBorrowObj, autoderefs, [m_imm, m_mutbl],
|trt_mut, reg| {
ty::mk_trait(tcx, trt_did, trt_substs.clone(),
RegionTraitStore(reg), trt_mut, b)
......@@ -779,7 +779,7 @@ fn search_for_autoptrd_method(&self, self_ty: ty::t, autoderefs: uint)
ty_float(*) | ty_enum(*) | ty_ptr(*) | ty_struct(*) | ty_tup(*) |
ty_estr(*) | ty_evec(*) | ty_trait(*) | ty_closure(*) => {
self.search_for_some_kind_of_autorefd_method(
AutoPtr, autoderefs, [m_const, m_imm, m_mutbl],
AutoPtr, autoderefs, [m_imm, m_mutbl],
|m,r| ty::mk_rptr(tcx, r, ty::mt {ty:self_ty, mutbl:m}))
}
......@@ -1270,18 +1270,10 @@ fn rcvr_matches_ty(fcx: @mut FnCtxt,
}
fn mutability_matches(self_mutbl: ast::mutability,
candidate_mutbl: ast::mutability) -> bool {
candidate_mutbl: ast::mutability)
-> bool {
//! True if `self_mutbl <: candidate_mutbl`
match (self_mutbl, candidate_mutbl) {
(_, m_const) => true,
(m_mutbl, m_mutbl) => true,
(m_imm, m_imm) => true,
(m_mutbl, m_imm) => false,
(m_imm, m_mutbl) => false,
(m_const, m_imm) => false,
(m_const, m_mutbl) => false,
}
self_mutbl == candidate_mutbl
}
}
......
......@@ -21,7 +21,7 @@
use middle::typeck::infer::{TypeTrace, Subtype};
use middle::typeck::infer::fold_regions_in_sig;
use middle::typeck::isr_alist;
use syntax::ast::{Many, Once, extern_fn, impure_fn, m_const, m_imm, m_mutbl};
use syntax::ast::{Many, Once, extern_fn, impure_fn, m_imm, m_mutbl};
use syntax::ast::{unsafe_fn};
use syntax::ast::{Onceness, purity};
use util::common::{indenter};
......@@ -52,16 +52,6 @@ fn mts(&self, a: &ty::mt, b: &ty::mt) -> cres<ty::mt> {
match (a.mutbl, b.mutbl) {
// If one side or both is mut, then the GLB must use
// the precise type from the mut side.
(m_mutbl, m_const) => {
Sub(**self).tys(a.ty, b.ty).chain(|_t| {
Ok(ty::mt {ty: a.ty, mutbl: m_mutbl})
})
}
(m_const, m_mutbl) => {
Sub(**self).tys(b.ty, a.ty).chain(|_t| {
Ok(ty::mt {ty: b.ty, mutbl: m_mutbl})
})
}
(m_mutbl, m_mutbl) => {
eq_tys(self, a.ty, b.ty).then(|| {
Ok(ty::mt {ty: a.ty, mutbl: m_mutbl})
......@@ -70,22 +60,12 @@ fn mts(&self, a: &ty::mt, b: &ty::mt) -> cres<ty::mt> {
// If one side or both is immutable, we can use the GLB of
// both sides but mutbl must be `m_imm`.
(m_imm, m_const) |
(m_const, m_imm) |
(m_imm, m_imm) => {
self.tys(a.ty, b.ty).chain(|t| {
Ok(ty::mt {ty: t, mutbl: m_imm})
})
}
// If both sides are const, then we can use GLB of both
// sides and mutbl of only `m_const`.
(m_const, m_const) => {
self.tys(a.ty, b.ty).chain(|t| {
Ok(ty::mt {ty: t, mutbl: m_const})
})
}
// There is no mutual subtype of these combinations.
(m_mutbl, m_imm) |
(m_imm, m_mutbl) => {
......
......@@ -24,7 +24,7 @@
use util::ppaux::mt_to_str;
use extra::list;
use syntax::ast::{Many, Once, extern_fn, m_const, impure_fn};
use syntax::ast::{Many, Once, extern_fn, impure_fn};
use syntax::ast::{unsafe_fn};
use syntax::ast::{Onceness, purity};
......@@ -55,14 +55,13 @@ fn mts(&self, a: &ty::mt, b: &ty::mt) -> cres<ty::mt> {
mt_to_str(tcx, a),
mt_to_str(tcx, b));
let m = if a.mutbl == b.mutbl {
a.mutbl
} else {
m_const
};
if a.mutbl != b.mutbl {
return Err(ty::terr_mutability)
}
let m = a.mutbl;
match m {
m_imm | m_const => {
m_imm => {
self.tys(a.ty, b.ty).chain(|t| Ok(ty::mt {ty: t, mutbl: m}) )
}
......@@ -71,11 +70,7 @@ fn mts(&self, a: &ty::mt, b: &ty::mt) -> cres<ty::mt> {
eq_tys(self, a.ty, b.ty).then(|| {
Ok(ty::mt {ty: a.ty, mutbl: m})
})
}).chain_err(|_e| {
self.tys(a.ty, b.ty).chain(|t| {
Ok(ty::mt {ty: t, mutbl: m_const})
})
})
}).chain_err(|e| Err(e))
}
}
}
......
......@@ -26,7 +26,7 @@
use extra::list::Nil;
use extra::list;
use syntax::ast::{Onceness, m_const, purity};
use syntax::ast::{Onceness, purity};
pub struct Sub(CombineFields); // "subtype", "subregion" etc
......@@ -67,7 +67,7 @@ fn regions(&self, a: ty::Region, b: ty::Region) -> cres<ty::Region> {
fn mts(&self, a: &ty::mt, b: &ty::mt) -> cres<ty::mt> {
debug!("mts(%s <: %s)", a.inf_str(self.infcx), b.inf_str(self.infcx));
if a.mutbl != b.mutbl && b.mutbl != m_const {
if a.mutbl != b.mutbl {
return Err(ty::terr_mutability);
}
......@@ -77,7 +77,7 @@ fn mts(&self, a: &ty::mt, b: &ty::mt) -> cres<ty::mt> {
// (i.e., invariant if mut):
eq_tys(self, a.ty, b.ty).then(|| Ok(*a))
}
m_imm | m_const => {
m_imm => {
// Otherwise we can be covariant:
self.tys(a.ty, b.ty).chain(|_t| Ok(*a) )
}
......
......@@ -239,7 +239,6 @@ fn mutability_to_str(m: ast::mutability) -> ~str {
match m {
ast::m_mutbl => ~"mut ",
ast::m_imm => ~"",
ast::m_const => ~"const "
}
}
......
......@@ -10,6 +10,7 @@
//! Unsafe casting functions
use ptr::RawPtr;
use sys;
use unstable::intrinsics;
......@@ -94,13 +95,13 @@ pub unsafe fn transmute_region<'a,'b,T>(ptr: &'a T) -> &'b T {
/// Coerce an immutable reference to be mutable.
#[inline]
pub unsafe fn transmute_mut_unsafe<T>(ptr: *const T) -> *mut T {
pub unsafe fn transmute_mut_unsafe<T,P:RawPtr<T>>(ptr: P) -> *mut T {
transmute(ptr)
}
/// Coerce an immutable reference to be mutable.
#[inline]
pub unsafe fn transmute_immut_unsafe<T>(ptr: *const T) -> *T {
pub unsafe fn transmute_immut_unsafe<T,P:RawPtr<T>>(ptr: P) -> *T {
transmute(ptr)
}
......
......@@ -11,7 +11,7 @@
#[doc(hidden)];
use libc::c_void;
use ptr::{mut_null};
use ptr::null;
use unstable::intrinsics::TyDesc;
use unstable::raw;
......@@ -37,7 +37,7 @@ unsafe fn each_live_alloc(read_next_before: bool,
use rt::local_heap;
let mut box = local_heap::live_allocs();
while box != mut_null() {
while box != null() {
let next_before = (*box).next;
let uniq = (*box).ref_count == managed::RC_MANAGED_UNIQUE;
......
......@@ -1521,7 +1521,7 @@ pub fn new(min_len: uint, options: ~[MapOption]) -> Result<~MemoryMap, MapError>
let r = unsafe {
libc::mmap(addr, len, prot, flags, fd, offset)
};
if r == libc::MAP_FAILED {
if r.equiv(&libc::MAP_FAILED) {
Err(match errno() as c_int {
libc::EACCES => ErrFdNotAvail,
libc::EBADF => ErrInvalidFd,
......
......@@ -12,8 +12,11 @@
use cast;
use clone::Clone;
use cmp::Equiv;
use iterator::{range, Iterator};
use option::{Option, Some, None};
#[cfg(stage0)]
use sys;
use unstable::intrinsics;
use util::swap;
......@@ -24,18 +27,28 @@
/// Calculate the offset from a pointer
#[inline]
#[cfg(stage0)]
pub fn offset<T>(ptr: *T, count: int) -> *T {
unsafe { intrinsics::offset(ptr, count) }
(ptr as uint + (count as uint) * sys::size_of::<T>()) as *T
}
/// Calculate the offset from a const pointer
/// Calculate the offset from a mut pointer
#[inline]
pub fn const_offset<T>(ptr: *const T, count: int) -> *const T {
unsafe { intrinsics::offset(ptr as *T, count) }
#[cfg(stage0)]
pub fn mut_offset<T>(ptr: *mut T, count: int) -> *mut T {
(ptr as uint + (count as uint) * sys::size_of::<T>()) as *mut T
}
/// Calculate the offset from a pointer
#[inline]
#[cfg(not(stage0))]
pub fn offset<T>(ptr: *T, count: int) -> *T {
unsafe { intrinsics::offset(ptr, count) }
}
/// Calculate the offset from a mut pointer
#[inline]
#[cfg(not(stage0))]
pub fn mut_offset<T>(ptr: *mut T, count: int) -> *mut T {
unsafe { intrinsics::offset(ptr as *T, count) as *mut T }
}
......@@ -73,11 +86,11 @@ pub fn mut_null<T>() -> *mut T { 0 as *mut T }
/// Returns true if the pointer is equal to the null pointer.
#[inline]
pub fn is_null<T>(ptr: *const T) -> bool { ptr == null() }
pub fn is_null<T,P:RawPtr<T>>(ptr: P) -> bool { ptr.is_null() }
/// Returns true if the pointer is not equal to the null pointer.
#[inline]
pub fn is_not_null<T>(ptr: *const T) -> bool { !is_null(ptr) }
pub fn is_not_null<T,P:RawPtr<T>>(ptr: P) -> bool { ptr.is_not_null() }
/**
* Copies data from one location to another.
......@@ -87,8 +100,10 @@ pub fn is_not_null<T>(ptr: *const T) -> bool { !is_null(ptr) }
*/
#[inline]
#[cfg(target_word_size = "32")]
pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) {
intrinsics::memmove32(dst, src as *T, count as u32);
pub unsafe fn copy_memory<T,P:RawPtr<T>>(dst: *mut T, src: P, count: uint) {
intrinsics::memmove32(dst,
cast::transmute_immut_unsafe(src),
count as u32);
}
/**
......@@ -99,8 +114,10 @@ pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) {
*/
#[inline]
#[cfg(target_word_size = "64")]
pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) {
intrinsics::memmove64(dst, src as *T, count as u64);
pub unsafe fn copy_memory<T,P:RawPtr<T>>(dst: *mut T, src: P, count: uint) {
intrinsics::memmove64(dst,
cast::transmute_immut_unsafe(src),
count as u64);
}
/**
......@@ -111,8 +128,12 @@ pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) {
*/
#[inline]
#[cfg(target_word_size = "32")]
pub unsafe fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: uint) {
intrinsics::memcpy32(dst, src as *T, count as u32);
pub unsafe fn copy_nonoverlapping_memory<T,P:RawPtr<T>>(dst: *mut T,
src: P,
count: uint) {
intrinsics::memcpy32(dst,
cast::transmute_immut_unsafe(src),
count as u32);
}
/**
......@@ -123,8 +144,12 @@ pub unsafe fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: u
*/
#[inline]
#[cfg(target_word_size = "64")]
pub unsafe fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: uint) {
intrinsics::memcpy64(dst, src as *T, count as u64);
pub unsafe fn copy_nonoverlapping_memory<T,P:RawPtr<T>>(dst: *mut T,
src: P,
count: uint) {
intrinsics::memcpy64(dst,
cast::transmute_immut_unsafe(src),
count as u64);
}
/**
......@@ -216,12 +241,6 @@ pub fn to_unsafe_ptr<T>(thing: &T) -> *T {
thing as *T
}
/// Transform a const region pointer - &const T - to a const unsafe pointer - *const T.
#[inline]
pub fn to_const_unsafe_ptr<T>(thing: &const T) -> *const T {
thing as *const T
}
/// Transform a mutable region pointer - &mut T - to a mutable unsafe pointer - *mut T.
#[inline]
pub fn to_mut_unsafe_ptr<T>(thing: &mut T) -> *mut T {
......@@ -269,8 +288,10 @@ pub unsafe fn array_each<T>(arr: **T, cb: &fn(*T)) {
#[allow(missing_doc)]
pub trait RawPtr<T> {
fn null() -> Self;
fn is_null(&self) -> bool;
fn is_not_null(&self) -> bool;
fn to_uint(&self) -> uint;
unsafe fn to_option(&self) -> Option<&T>;
fn offset(&self, count: int) -> Self;
unsafe fn offset_inbounds(self, count: int) -> Self;
......@@ -278,13 +299,21 @@ pub trait RawPtr<T> {
/// Extension methods for immutable pointers
impl<T> RawPtr<T> for *T {
/// Returns the null pointer.
#[inline]
fn null() -> *T { null() }
/// Returns true if the pointer is equal to the null pointer.
#[inline]
fn is_null(&self) -> bool { is_null(*self) }
fn is_null(&self) -> bool { *self == RawPtr::null() }
/// Returns true if the pointer is not equal to the null pointer.
#[inline]
fn is_not_null(&self) -> bool { is_not_null(*self) }
fn is_not_null(&self) -> bool { *self != RawPtr::null() }
/// Returns the address of this pointer.
#[inline]
fn to_uint(&self) -> uint { *self as uint }
///
/// Returns `None` if the pointer is null, or else returns the value wrapped
......@@ -317,13 +346,21 @@ unsafe fn offset_inbounds(self, count: int) -> *T {
/// Extension methods for mutable pointers
impl<T> RawPtr<T> for *mut T {
/// Returns the null pointer.
#[inline]
fn null() -> *mut T { mut_null() }
/// Returns true if the pointer is equal to the null pointer.
#[inline]
fn is_null(&self) -> bool { is_null(*self) }
fn is_null(&self) -> bool { *self == RawPtr::null() }
/// Returns true if the pointer is not equal to the null pointer.
#[inline]
fn is_not_null(&self) -> bool { is_not_null(*self) }
fn is_not_null(&self) -> bool { *self != RawPtr::null() }
/// Returns the address of this pointer.
#[inline]
fn to_uint(&self) -> uint { *self as uint }
///
/// Returns `None` if the pointer is null, or else returns the value wrapped
......@@ -360,13 +397,38 @@ unsafe fn offset_inbounds(self, count: int) -> *mut T {
// Equality for pointers
#[cfg(not(test))]
impl<T> Eq for *const T {
impl<T> Eq for *T {
#[inline]
fn eq(&self, other: &*T) -> bool {
(*self as uint) == (*other as uint)
}
#[inline]
fn ne(&self, other: &*T) -> bool { !self.eq(other) }
}
#[cfg(not(test))]
impl<T> Eq for *mut T {
#[inline]
fn eq(&self, other: &*const T) -> bool {
fn eq(&self, other: &*mut T) -> bool {
(*self as uint) == (*other as uint)
}
#[inline]
fn ne(&self, other: &*const T) -> bool { !self.eq(other) }
fn ne(&self, other: &*mut T) -> bool { !self.eq(other) }
}
// Equivalence for pointers
#[cfg(not(test))]
impl<T> Equiv<*mut T> for *T {
fn equiv(&self, other: &*mut T) -> bool {
self.to_uint() == other.to_uint()
}
}
#[cfg(not(test))]
impl<T> Equiv<*T> for *mut T {
fn equiv(&self, other: &*T) -> bool {
self.to_uint() == other.to_uint()
}
}
// Equality for extern "C" fn pointers
......@@ -412,21 +474,41 @@ fn ne(&self, other: &extern "C" fn($($p),*) -> _R) -> bool {
// Comparison for pointers
#[cfg(not(test))]
impl<T> Ord for *const T {
impl<T> Ord for *T {
#[inline]
fn lt(&self, other: &*T) -> bool {
(*self as uint) < (*other as uint)
}
#[inline]
fn le(&self, other: &*T) -> bool {
(*self as uint) <= (*other as uint)
}
#[inline]
fn ge(&self, other: &*T) -> bool {
(*self as uint) >= (*other as uint)
}
#[inline]
fn gt(&self, other: &*T) -> bool {
(*self as uint) > (*other as uint)
}
}
#[cfg(not(test))]
impl<T> Ord for *mut T {
#[inline]
fn lt(&self, other: &*const T) -> bool {
fn lt(&self, other: &*mut T) -> bool {
(*self as uint) < (*other as uint)
}
#[inline]
fn le(&self, other: &*const T) -> bool {
fn le(&self, other: &*mut T) -> bool {
(*self as uint) <= (*other as uint)
}
#[inline]
fn ge(&self, other: &*const T) -> bool {
fn ge(&self, other: &*mut T) -> bool {
(*self as uint) >= (*other as uint)
}
#[inline]
fn gt(&self, other: &*const T) -> bool {
fn gt(&self, other: &*mut T) -> bool {
(*self as uint) > (*other as uint)
}
}
......
......@@ -11,17 +11,18 @@
use cell::Cell;
use c_str::ToCStr;
use cast::transmute;
use libc::{c_char, size_t, STDERR_FILENO};
use io;
use io::{Writer, WriterUtil};
use io;
use libc::{c_char, c_void, size_t, STDERR_FILENO};
use option::{Option, None, Some};
use uint;
use ptr::RawPtr;
use rt::env;
use rt::local::Local;
use rt::task::Task;
use str;
use str::{OwnedStr, StrSlice};
use str;
use sys;
use uint;
use unstable::raw;
use vec::ImmutableVector;
......@@ -93,12 +94,12 @@ unsafe fn fail_borrowed(box: *mut raw::Box<()>, file: *c_char, line: size_t) {
static ENABLE_DEBUG: bool = false;
#[inline]
unsafe fn debug_borrow<T>(tag: &'static str,
p: *const T,
old_bits: uint,
new_bits: uint,
filename: *c_char,
line: size_t) {
unsafe fn debug_borrow<T,P:RawPtr<T>>(tag: &'static str,
p: P,
old_bits: uint,
new_bits: uint,
filename: *c_char,
line: size_t) {
//! A useful debugging function that prints a pointer + tag + newline
//! without allocating memory.
......@@ -106,15 +107,15 @@ unsafe fn debug_borrow<T>(tag: &'static str,
debug_borrow_slow(tag, p, old_bits, new_bits, filename, line);
}
unsafe fn debug_borrow_slow<T>(tag: &'static str,
p: *const T,
old_bits: uint,
new_bits: uint,
filename: *c_char,
line: size_t) {
unsafe fn debug_borrow_slow<T,P:RawPtr<T>>(tag: &'static str,
p: P,
old_bits: uint,
new_bits: uint,
filename: *c_char,
line: size_t) {
let dbg = STDERR_FILENO as io::fd_t;
dbg.write_str(tag);
dbg.write_hex(p as uint);
dbg.write_hex(p.to_uint());
dbg.write_str(" ");
dbg.write_hex(old_bits);
dbg.write_str(" ");
......
......@@ -554,6 +554,7 @@ pub fn change_task_context(~self,
let current_task: &mut Task = match sched.cleanup_job {
Some(CleanupJob { task: ref task, _ }) => {
let task_ptr: *~Task = task;
transmute_mut_region(*transmute_mut_unsafe(task))
}
None => {
......
......@@ -343,7 +343,14 @@ fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
// NB: raw-pointer IterBytes does _not_ dereference
// to the target; it just gives you the pointer-bytes.
impl<A> IterBytes for *const A {
impl<A> IterBytes for *A {
#[inline]
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
(*self as uint).iter_bytes(lsb0, f)
}
}
impl<A> IterBytes for *mut A {
#[inline]
fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
(*self as uint).iter_bytes(lsb0, f)
......
......@@ -54,8 +54,10 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
let t: *mut T = &mut tmp;
// Perform the swap, `&mut` pointers never alias
ptr::copy_nonoverlapping_memory(t, x, 1);
ptr::copy_nonoverlapping_memory(x, y, 1);
let x_raw: *mut T = x;
let y_raw: *mut T = y;
ptr::copy_nonoverlapping_memory(t, x_raw, 1);
ptr::copy_nonoverlapping_memory(x, y_raw, 1);
ptr::copy_nonoverlapping_memory(y, t, 1);
// y and t now point to the same thing, but we need to completely forget `tmp`
......
......@@ -1122,14 +1122,7 @@ fn map<U>(&self, f: &fn(t: &T) -> U) -> ~[U] {
* foreign interop.
*/
#[inline]
fn as_imm_buf<U>(&self,
/* NB---this CANNOT be const, see below */
f: &fn(*T, uint) -> U) -> U {
// NB---Do not change the type of s to `&const [T]`. This is
// unsound. The reason is that we are going to create immutable pointers
// into `s` and pass them to `f()`, but in fact they are potentially
// pointing at *mutable memory*. Use `as_mut_buf` instead!
fn as_imm_buf<U>(&self, f: &fn(*T, uint) -> U) -> U {
let s = self.repr();
f(s.data, s.len / sys::nonzero_size_of::<T>())
}
......
......@@ -298,7 +298,10 @@ pub enum pat_ {
}
#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
pub enum mutability { m_mutbl, m_imm, m_const, }
pub enum mutability {
m_mutbl,
m_imm,
}
#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
pub enum Sigil {
......
......@@ -53,7 +53,6 @@ pub enum ObsoleteSyntax {
ObsoleteMode,
ObsoleteImplicitSelf,
ObsoleteLifetimeNotation,
ObsoleteConstManagedPointer,
ObsoletePurity,
ObsoleteStaticMethod,
ObsoleteConstItem,
......@@ -65,6 +64,7 @@ pub enum ObsoleteSyntax {
ObsoleteUnsafeExternFn,
ObsoletePrivVisibility,
ObsoleteTraitFuncVisibility,
ObsoleteConstPointer,
}
impl to_bytes::IterBytes for ObsoleteSyntax {
......@@ -201,10 +201,6 @@ fn obsolete(&self, sp: span, kind: ObsoleteSyntax) {
"instead of `&foo/bar`, write `&'foo bar`; instead of \
`bar/&foo`, write `&bar<'foo>"
),
ObsoleteConstManagedPointer => (
"const `@` pointer",
"instead of `@const Foo`, write `@Foo`"
),
ObsoletePurity => (
"pure function",
"remove `pure`"
......@@ -255,6 +251,11 @@ fn obsolete(&self, sp: span, kind: ObsoleteSyntax) {
"visibility not necessary",
"trait functions inherit the visibility of the trait itself"
),
ObsoleteConstPointer => (
"const pointer",
"instead of `&const Foo` or `@const Foo`, write `&Foo` or \
`@Foo`"
),
};
self.report(sp, kind, kind_str, desc);
......
......@@ -38,7 +38,7 @@
use ast::{item_enum, item_fn, item_foreign_mod, item_impl};
use ast::{item_mac, item_mod, item_struct, item_trait, item_ty, lit, lit_};
use ast::{lit_bool, lit_float, lit_float_unsuffixed, lit_int};
use ast::{lit_int_unsuffixed, lit_nil, lit_str, lit_uint, Local, m_const};
use ast::{lit_int_unsuffixed, lit_nil, lit_str, lit_uint, Local};
use ast::{m_imm, m_mutbl, mac_, mac_invoc_tt, matcher, match_nonterminal};
use ast::{match_seq, match_tok, method, mt, mul, mutability};
use ast::{named_field, neg, NodeId, noreturn, not, pat, pat_box, pat_enum};
......@@ -1153,9 +1153,6 @@ pub fn parse_box_or_uniq_pointee(&self,
if mt.mutbl != m_imm && sigil == OwnedSigil {
self.obsolete(*self.last_span, ObsoleteMutOwnedPointer);
}
if mt.mutbl == m_const && sigil == ManagedSigil {
self.obsolete(*self.last_span, ObsoleteConstManagedPointer);
}
ctor(mt)
}
......@@ -1568,7 +1565,8 @@ pub fn parse_mutability(&self) -> mutability {
if self.eat_keyword(keywords::Mut) {
m_mutbl
} else if self.eat_keyword(keywords::Const) {
m_const
self.obsolete(*self.last_span, ObsoleteConstPointer);
m_imm
} else {
m_imm
}
......@@ -1727,7 +1725,7 @@ pub fn parse_bottom_expr(&self) -> @expr {
} else if *self.token == token::LBRACKET {
self.bump();
let mutbl = self.parse_mutability();
if mutbl == m_mutbl || mutbl == m_const {
if mutbl == m_mutbl {
self.obsolete(*self.last_span, ObsoleteMutVector);
}
......@@ -2182,10 +2180,6 @@ pub fn parse_prefix_expr(&self) -> @expr {
token::AT => {
self.bump();
let m = self.parse_mutability();
if m == m_const {
self.obsolete(*self.last_span, ObsoleteConstManagedPointer);
}
let e = self.parse_prefix_expr();
hi = e.span.hi;
// HACK: turn @[...] into a @-evec
......
......@@ -386,7 +386,6 @@ pub fn print_type(s: @ps, ty: &ast::Ty) {
word(s.s, "[");
match mt.mutbl {
ast::m_mutbl => word_space(s, "mut"),
ast::m_const => word_space(s, "const"),
ast::m_imm => ()
}
print_type(s, mt.ty);
......@@ -429,7 +428,6 @@ pub fn print_type(s: @ps, ty: &ast::Ty) {
word(s.s, "[");
match mt.mutbl {
ast::m_mutbl => word_space(s, "mut"),
ast::m_const => word_space(s, "const"),
ast::m_imm => ()
}
print_type(s, mt.ty);
......@@ -1882,7 +1880,6 @@ pub fn print_view_item(s: @ps, item: &ast::view_item) {
pub fn print_mutability(s: @ps, mutbl: ast::mutability) {
match mutbl {
ast::m_mutbl => word_nbsp(s, "mut"),
ast::m_const => word_nbsp(s, "const"),
ast::m_imm => {/* nothing */ }
}
}
......
// Test that attempt to alias `&mut` pointer while pointee is borrowed
// yields an error.
//
// Example from src/middle/borrowck/doc.rs
use std::util::swap;
fn foo(t0: &mut int) {
let p: &int = &*t0; // Freezes `*t0`
let q: &const &mut int = &const t0; //~ ERROR cannot borrow `t0`
**q = 22; //~ ERROR cannot assign to an `&mut` in a `&const` pointer
}
fn main() {
}
\ No newline at end of file
......@@ -11,16 +11,6 @@ fn foo(t0: & &mut int) {
**t1 = 22; //~ ERROR cannot assign
}
fn foo2(t0: &const &mut int) {
// Note: reborrowing from an &const actually yields two errors, since it
// is unsafe in two ways: we can't control the aliasing, and we can't
// control the mutation.
let t1 = t0;
let p: &int = &**t0; //~ ERROR cannot borrow an `&mut` in a `&const` pointer
//~^ ERROR unsafe borrow of aliasable, const value
**t1 = 22; //~ ERROR cannot assign
}
fn foo3(t0: &mut &mut int) {
let t1 = &mut *t0;
let p: &int = &**t0; //~ ERROR cannot borrow
......@@ -28,4 +18,4 @@ fn foo3(t0: &mut &mut int) {
}
fn main() {
}
\ No newline at end of file
}
......@@ -14,29 +14,18 @@ struct Foo {
impl Foo {
pub fn f(&self) {}
pub fn g(&const self) {}
pub fn h(&mut self) {}
}
fn a(x: &mut Foo) {
x.f();
x.g();
x.h();
}
fn b(x: &Foo) {
x.f();
x.g();
x.h(); //~ ERROR cannot borrow
}
fn c(x: &const Foo) {
x.f(); //~ ERROR cannot borrow
//~^ ERROR unsafe borrow
x.g();
x.h(); //~ ERROR cannot borrow
//~^ ERROR unsafe borrow
}
fn main() {
}
......@@ -32,14 +32,6 @@ fn pre_freeze() {
borrow_mut(v); //~ ERROR cannot borrow
}
fn pre_const() {
// In this instance, the freeze starts before the mut borrow.
let mut v = ~3;
let _w = &const v;
borrow_mut(v);
}
fn post_freeze() {
// In this instance, the const alias starts after the borrow.
......
......@@ -29,16 +29,5 @@ fn has_mut_vec_but_tries_to_change_it() {
}
}
fn takes_const_elt(_v: &const int, f: &fn()) {
f();
}
fn has_mut_vec_and_tries_to_change_it() {
let mut v = ~[1, 2, 3];
do takes_const_elt(&const v[0]) {
v[1] = 4;
}
}
fn main() {
}
// 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.
fn process<T>(_t: T) {}
fn match_const_opt_by_mut_ref(v: &const Option<int>) {
match *v {
Some(ref mut i) => process(i), //~ ERROR cannot borrow
//~^ ERROR unsafe borrow of aliasable, const value
None => ()
}
}
fn match_const_opt_by_const_ref(v: &const Option<int>) {
match *v {
Some(ref const i) => process(i),
//~^ ERROR unsafe borrow of aliasable, const value
None => ()
}
}
fn match_const_opt_by_imm_ref(v: &const Option<int>) {
match *v {
Some(ref i) => process(i), //~ ERROR cannot borrow
//~^ ERROR unsafe borrow of aliasable, const value
None => ()
}
}
fn match_const_opt_by_value(v: &const Option<int>) {
match *v {
Some(i) => process(i),
None => ()
}
}
fn main() {
}
......@@ -35,12 +35,6 @@ fn aliased_imm() {
borrow(v);
}
fn aliased_const() {
let mut v = ~3;
let _w = &const v;
borrow(v);
}
fn aliased_mut() {
let mut v = ~3;
let _w = &mut v;
......
......@@ -23,13 +23,10 @@ fn main() {
// @int <: X
//
// This constraint forces X to be
// @const int.
r(@3);
// Here the type check fails because @const is gone and there is no
// supertype.
r(@3); //~ ERROR mismatched types
// Here the type check succeeds but the
// mutability check will fail, because the
// type of r has been inferred to be
// fn(@const int) -> @const int
*r(@mut 3) = 4; //~ ERROR cannot assign to const dereference of @ pointer
// Here the type check succeeds.
*r(@mut 3) = 4;
}
// 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.
struct Bike {
name: ~str,
}
trait BikeMethods {
fn woops(&const self) -> ~str;
}
impl BikeMethods for Bike {
fn woops() -> ~str { ~"foo" }
//~^ ERROR has a `&const self` declaration in the trait, but not in the impl
}
pub fn main() {
}
// 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.
extern mod extra;
fn main() {
unsafe fn f(v: *const int) {
*v = 1 //~ ERROR cannot assign
}
unsafe {
let mut a = 0;
let v = &mut a;
f(v);
}
}
......@@ -26,13 +26,6 @@ fn matcher2(x: opts) {
}
}
fn matcher3(x: opts) {
match x {
a(ref mut i) | b(ref const i) => {} //~ ERROR variable `i` is bound with different mode in pattern #2 than in pattern #1
c(_) => {}
}
}
fn matcher4(x: opts) {
match x {
a(ref mut i) | b(ref i) => {} //~ ERROR variable `i` is bound with different mode in pattern #2 than in pattern #1
......
......@@ -13,17 +13,14 @@
trait MyIter {
fn test_imm(&self);
fn test_const(&const self);
}
impl<'self> MyIter for &'self [int] {
fn test_imm(&self) { assert_eq!(self[0], 1) }
fn test_const(&const self) { assert_eq!(self[0], 1) }
}
impl<'self> MyIter for &'self str {
fn test_imm(&self) { assert_eq!(*self, "test") }
fn test_const(&const self) { assert_eq!(self[0], 't' as u8) }
}
pub fn main() {
......@@ -40,15 +37,6 @@ pub fn main() {
// XXX: Other types of mutable vecs don't currently exist
([1]).test_const();
(~[1]).test_const();
(@[1]).test_const();
(&[1]).test_const();
("test").test_const();
(~"test").test_const();
(@"test").test_const();
(&"test").test_const();
// NB: We don't do this double autoreffing for &mut self because that would
// allow creating a mutable pointer to a temporary, which would be a source
// of confusion
......
......@@ -13,7 +13,7 @@ struct Foo {
}
impl Foo {
pub fn f(&const self) {}
pub fn f(&self) {}
}
fn g(x: &mut Foo) {
......
......@@ -24,32 +24,9 @@ fn match_ref_unused(v: Option<int>) {
}
}
fn match_const_reg(v: &const Option<int>) -> int {
match *v {
Some(ref i) => {*i} //~ ERROR cannot borrow
//~^ ERROR unsafe borrow
None => {0}
}
}
fn impure(_i: int) {
}
fn match_const_reg_unused(v: &const Option<int>) {
match *v {
Some(_) => {impure(0)} // OK because nothing is captured
None => {}
}
}
fn match_const_reg_impure(v: &const Option<int>) {
match *v {
Some(ref i) => {impure(*i)} //~ ERROR cannot borrow
//~^ ERROR unsafe borrow
None => {}
}
}
fn match_imm_reg(v: &Option<int>) {
match *v {
Some(ref i) => {impure(*i)} // OK because immutable
......
......@@ -25,7 +25,6 @@ struct Innermost {
}
fn borrow(_v: &int) {}
fn borrow_const(_v: &const int) {}
fn box_mut(v: &mut ~int) {
borrow(*v); // OK: &mut -> &imm
......@@ -51,17 +50,5 @@ fn box_imm_recs(v: &Outer) {
borrow(v.f.g.h); // OK
}
fn box_const(v: &const ~int) {
borrow_const(*v); //~ ERROR unsafe borrow
}
fn box_const_rec(v: &const Rec) {
borrow_const(v.f); //~ ERROR unsafe borrow
}
fn box_const_recs(v: &const Outer) {
borrow_const(v.f.g.h); //~ ERROR unsafe borrow
}
fn main() {
}
......@@ -49,8 +49,8 @@ pub fn eat(&mut self) -> bool {
}
impl<T> Container for cat<T> {
fn len(&const self) -> uint { self.meows as uint }
fn is_empty(&const self) -> bool { self.meows == 0 }
fn len(&self) -> uint { self.meows as uint }
fn is_empty(&self) -> bool { self.meows == 0 }
}
impl<T> Mutable for cat<T> {
......
......@@ -3,14 +3,14 @@ struct SpeechMaker {
}
impl SpeechMaker {
pub fn how_many(&const self) -> uint { self.speeches }
pub fn how_many(&self) -> uint { self.speeches }
}
fn foo(speaker: &const SpeechMaker) -> uint {
fn foo(speaker: &SpeechMaker) -> uint {
speaker.how_many() + 33
}
pub fn main() {
let lincoln = SpeechMaker {speeches: 22};
assert_eq!(foo(&const lincoln), 55);
assert_eq!(foo(&lincoln), 55);
}
......@@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn f(_: &const [int]) {}
fn f(_: &[int]) {}
pub fn main() {
let v = [ 1, 2, 3 ];
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册