auto merge of #5480 : pcwalton/rust/at-const, r=pcwalton
r? @catamorphism
This commit is contained in:
commit
d52408d46a
@ -84,6 +84,7 @@ struct Guard<T, U> {
|
||||
cond: &'self Condition/&self<T, U>
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl<T, U> Drop for Guard/&self<T, U> {
|
||||
fn finalize(&self) {
|
||||
unsafe {
|
||||
|
@ -1230,15 +1230,17 @@ pub mod fsync {
|
||||
arg: Arg<t>,
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl<T:Copy> Drop for Res<T> {
|
||||
fn finalize(&self) {
|
||||
match self.arg.opt_level {
|
||||
None => (),
|
||||
Some(level) => {
|
||||
// fail hard if not succesful
|
||||
fail_unless!(((self.arg.fsync_fn)(self.arg.val, level) != -1));
|
||||
match self.arg.opt_level {
|
||||
None => (),
|
||||
Some(level) => {
|
||||
// fail hard if not succesful
|
||||
fail_unless!(((self.arg.fsync_fn)(self.arg.val, level)
|
||||
!= -1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,23 +49,43 @@ pub pure fn mut_ptr_eq<T>(a: @mut T, b: @mut T) -> bool {
|
||||
}
|
||||
|
||||
#[cfg(notest)]
|
||||
impl<T:Eq> Eq for @const T {
|
||||
impl<T:Eq> Eq for @T {
|
||||
#[inline(always)]
|
||||
pure fn eq(&self, other: &@const T) -> bool { *(*self) == *(*other) }
|
||||
pure fn eq(&self, other: &@T) -> bool { *(*self) == *(*other) }
|
||||
#[inline(always)]
|
||||
pure fn ne(&self, other: &@const T) -> bool { *(*self) != *(*other) }
|
||||
pure fn ne(&self, other: &@T) -> bool { *(*self) != *(*other) }
|
||||
}
|
||||
|
||||
#[cfg(notest)]
|
||||
impl<T:Ord> Ord for @const T {
|
||||
impl<T:Eq> Eq for @mut T {
|
||||
#[inline(always)]
|
||||
pure fn lt(&self, other: &@const T) -> bool { *(*self) < *(*other) }
|
||||
pure fn eq(&self, other: &@mut T) -> bool { *(*self) == *(*other) }
|
||||
#[inline(always)]
|
||||
pure fn le(&self, other: &@const T) -> bool { *(*self) <= *(*other) }
|
||||
pure fn ne(&self, other: &@mut T) -> bool { *(*self) != *(*other) }
|
||||
}
|
||||
|
||||
#[cfg(notest)]
|
||||
impl<T:Ord> Ord for @T {
|
||||
#[inline(always)]
|
||||
pure fn ge(&self, other: &@const T) -> bool { *(*self) >= *(*other) }
|
||||
pure fn lt(&self, other: &@T) -> bool { *(*self) < *(*other) }
|
||||
#[inline(always)]
|
||||
pure fn gt(&self, other: &@const T) -> bool { *(*self) > *(*other) }
|
||||
pure fn le(&self, other: &@T) -> bool { *(*self) <= *(*other) }
|
||||
#[inline(always)]
|
||||
pure fn ge(&self, other: &@T) -> bool { *(*self) >= *(*other) }
|
||||
#[inline(always)]
|
||||
pure fn gt(&self, other: &@T) -> bool { *(*self) > *(*other) }
|
||||
}
|
||||
|
||||
#[cfg(notest)]
|
||||
impl<T:Ord> Ord for @mut T {
|
||||
#[inline(always)]
|
||||
pure fn lt(&self, other: &@mut T) -> bool { *(*self) < *(*other) }
|
||||
#[inline(always)]
|
||||
pure fn le(&self, other: &@mut T) -> bool { *(*self) <= *(*other) }
|
||||
#[inline(always)]
|
||||
pure fn ge(&self, other: &@mut T) -> bool { *(*self) >= *(*other) }
|
||||
#[inline(always)]
|
||||
pure fn gt(&self, other: &@mut T) -> bool { *(*self) > *(*other) }
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -514,6 +514,7 @@ fn test_unwrap_resource() {
|
||||
i: @mut int,
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl ::ops::Drop for R {
|
||||
fn finalize(&self) { *(self.i) += 1; }
|
||||
}
|
||||
|
@ -350,6 +350,7 @@ struct BufferResource<T> {
|
||||
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl<T> ::ops::Drop for BufferResource<T> {
|
||||
fn finalize(&self) {
|
||||
unsafe {
|
||||
@ -445,16 +446,17 @@ pub fn try_recv<T:Owned,Tbuffer:Owned>(p: RecvPacketBuffered<T, Tbuffer>)
|
||||
let p_ = p.unwrap();
|
||||
let p = unsafe { &*p_ };
|
||||
|
||||
#[unsafe_destructor]
|
||||
struct DropState {
|
||||
p: &'self PacketHeader,
|
||||
|
||||
drop {
|
||||
if task::failing() {
|
||||
self.p.state = Terminated;
|
||||
let old_task = swap_task(&mut self.p.blocked_task,
|
||||
ptr::null());
|
||||
if !old_task.is_null() {
|
||||
unsafe {
|
||||
unsafe {
|
||||
if task::failing() {
|
||||
self.p.state = Terminated;
|
||||
let old_task = swap_task(&mut self.p.blocked_task,
|
||||
ptr::null());
|
||||
if !old_task.is_null() {
|
||||
rustrt::rust_task_deref(old_task);
|
||||
}
|
||||
}
|
||||
@ -773,6 +775,7 @@ pub struct SendPacketBuffered<T, Tbuffer> {
|
||||
mut buffer: Option<BufferResource<Tbuffer>>,
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl<T:Owned,Tbuffer:Owned> ::ops::Drop for SendPacketBuffered<T,Tbuffer> {
|
||||
fn finalize(&self) {
|
||||
//if self.p != none {
|
||||
@ -842,6 +845,7 @@ pub struct RecvPacketBuffered<T, Tbuffer> {
|
||||
mut buffer: Option<BufferResource<Tbuffer>>,
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl<T:Owned,Tbuffer:Owned> ::ops::Drop for RecvPacketBuffered<T,Tbuffer> {
|
||||
fn finalize(&self) {
|
||||
//if self.p != none {
|
||||
|
@ -118,6 +118,7 @@ struct ArcDestruct<T> {
|
||||
mut data: *libc::c_void,
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl<T> Drop for ArcDestruct<T>{
|
||||
fn finalize(&self) {
|
||||
unsafe {
|
||||
|
@ -45,6 +45,7 @@ struct Finallyalizer {
|
||||
dtor: &'self fn()
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for Finallyalizer/&self {
|
||||
fn finalize(&self) {
|
||||
(self.dtor)();
|
||||
|
@ -22,6 +22,7 @@ use core::str;
|
||||
use core::vec;
|
||||
use std::oldmap::HashMap;
|
||||
use syntax::ast::*;
|
||||
use syntax::attr::attrs_contains_name;
|
||||
use syntax::codemap::{span, spanned};
|
||||
use syntax::print::pprust::expr_to_str;
|
||||
use syntax::{visit, ast_util};
|
||||
@ -55,6 +56,8 @@ use syntax::{visit, ast_util};
|
||||
// primitives in the stdlib are explicitly annotated to only take sendable
|
||||
// types.
|
||||
|
||||
use core::hashmap::linear::LinearSet;
|
||||
|
||||
pub const try_adding: &'static str = "Try adding a move";
|
||||
|
||||
pub type rval_map = HashMap<node_id, ()>;
|
||||
@ -63,7 +66,7 @@ pub struct Context {
|
||||
tcx: ty::ctxt,
|
||||
method_map: typeck::method_map,
|
||||
last_use_map: liveness::last_use_map,
|
||||
current_item: node_id
|
||||
current_item: node_id,
|
||||
}
|
||||
|
||||
pub fn check_crate(tcx: ty::ctxt,
|
||||
@ -74,16 +77,15 @@ pub fn check_crate(tcx: ty::ctxt,
|
||||
tcx: tcx,
|
||||
method_map: method_map,
|
||||
last_use_map: last_use_map,
|
||||
current_item: -1
|
||||
current_item: -1,
|
||||
};
|
||||
let visit = visit::mk_vt(@visit::Visitor {
|
||||
visit_arm: check_arm,
|
||||
visit_expr: check_expr,
|
||||
visit_fn: check_fn,
|
||||
visit_ty: check_ty,
|
||||
visit_item: |i, cx, v| {
|
||||
visit::visit_item(i, Context { current_item: i.id,.. cx }, v);
|
||||
},
|
||||
visit_item: check_item,
|
||||
visit_block: check_block,
|
||||
.. *visit::default_visitor()
|
||||
});
|
||||
visit::visit_crate(*crate, ctx, visit);
|
||||
@ -92,6 +94,93 @@ pub fn check_crate(tcx: ty::ctxt,
|
||||
|
||||
type check_fn = @fn(Context, @freevar_entry);
|
||||
|
||||
fn check_struct_safe_for_destructor(cx: Context,
|
||||
span: span,
|
||||
struct_did: def_id) {
|
||||
let struct_tpt = ty::lookup_item_type(cx.tcx, struct_did);
|
||||
if struct_tpt.bounds.len() == 0 {
|
||||
let struct_ty = ty::mk_struct(cx.tcx, struct_did, ty::substs {
|
||||
self_r: None,
|
||||
self_ty: None,
|
||||
tps: ~[]
|
||||
});
|
||||
if !ty::type_is_owned(cx.tcx, struct_ty) {
|
||||
cx.tcx.sess.span_err(span,
|
||||
~"cannot implement a destructor on a struct \
|
||||
that is not Owned");
|
||||
cx.tcx.sess.span_note(span,
|
||||
~"use \"#[unsafe_destructor]\" on the \
|
||||
implementation to force the compiler to \
|
||||
allow this");
|
||||
}
|
||||
} else {
|
||||
cx.tcx.sess.span_err(span,
|
||||
~"cannot implement a destructor on a struct \
|
||||
with type parameters");
|
||||
cx.tcx.sess.span_note(span,
|
||||
~"use \"#[unsafe_destructor]\" on the \
|
||||
implementation to force the compiler to \
|
||||
allow this");
|
||||
}
|
||||
}
|
||||
|
||||
fn check_block(block: &blk, cx: Context, visitor: visit::vt<Context>) {
|
||||
visit::visit_block(block, cx, visitor);
|
||||
}
|
||||
|
||||
fn check_item(item: @item, cx: Context, visitor: visit::vt<Context>) {
|
||||
// If this is a destructor, check kinds.
|
||||
if !attrs_contains_name(item.attrs, "unsafe_destructor") {
|
||||
match item.node {
|
||||
item_impl(_, Some(trait_ref), self_type, _) => {
|
||||
match cx.tcx.def_map.find(&trait_ref.ref_id) {
|
||||
None => cx.tcx.sess.bug(~"trait ref not in def map!"),
|
||||
Some(trait_def) => {
|
||||
let trait_def_id = ast_util::def_id_of_def(trait_def);
|
||||
if cx.tcx.lang_items.drop_trait() == trait_def_id {
|
||||
// Yes, it's a destructor.
|
||||
match self_type.node {
|
||||
ty_path(_, path_node_id) => {
|
||||
let struct_def = cx.tcx.def_map.get(
|
||||
&path_node_id);
|
||||
let struct_did =
|
||||
ast_util::def_id_of_def(struct_def);
|
||||
check_struct_safe_for_destructor(
|
||||
cx,
|
||||
self_type.span,
|
||||
struct_did);
|
||||
}
|
||||
_ => {
|
||||
cx.tcx.sess.span_bug(self_type.span,
|
||||
~"the self type for \
|
||||
the Drop trait \
|
||||
impl is not a \
|
||||
path");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
item_struct(struct_def, _) => {
|
||||
match struct_def.dtor {
|
||||
None => {}
|
||||
Some(ref dtor) => {
|
||||
let struct_did = def_id { crate: 0, node: item.id };
|
||||
check_struct_safe_for_destructor(cx,
|
||||
dtor.span,
|
||||
struct_did);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
let cx = Context { current_item: item.id, ..cx };
|
||||
visit::visit_item(item, cx, visitor);
|
||||
}
|
||||
|
||||
// Yields the appropriate function to check the kind of closed over
|
||||
// variables. `id` is the node_id for some expression that creates the
|
||||
// closure.
|
||||
|
@ -88,11 +88,14 @@ pub struct icx_popper {
|
||||
ccx: @CrateContext,
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for icx_popper {
|
||||
fn finalize(&self) {
|
||||
if self.ccx.sess.count_llvm_insns() {
|
||||
self.ccx.stats.llvm_insn_ctxt.pop();
|
||||
}
|
||||
unsafe {
|
||||
if self.ccx.sess.count_llvm_insns() {
|
||||
self.ccx.stats.llvm_insn_ctxt.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,6 +88,7 @@ pub struct Arena {
|
||||
priv mut chunks: @List<Chunk>,
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for Arena {
|
||||
fn finalize(&self) {
|
||||
unsafe {
|
||||
|
@ -54,11 +54,14 @@ struct DtorRes {
|
||||
dtor: Option<@fn()>,
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for DtorRes {
|
||||
fn finalize(&self) {
|
||||
match self.dtor {
|
||||
option::None => (),
|
||||
option::Some(f) => f()
|
||||
unsafe {
|
||||
match self.dtor {
|
||||
option::None => (),
|
||||
option::Some(f) => f()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ pub struct Future<A> {
|
||||
|
||||
// FIXME(#2829) -- futures should not be copyable, because they close
|
||||
// over ~fn's that have pipes and so forth within!
|
||||
#[unsafe_destructor]
|
||||
impl<A> Drop for Future<A> {
|
||||
fn finalize(&self) {}
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ pub struct TcpSocket {
|
||||
socket_data: @TcpSocketData,
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for TcpSocket {
|
||||
fn finalize(&self) {
|
||||
unsafe {
|
||||
|
@ -1190,6 +1190,7 @@ mod big_tests {
|
||||
key: &'self fn(@uint),
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for LVal/&self {
|
||||
fn finalize(&self) {
|
||||
let x = unsafe { task::local_data::local_data_get(self.key) };
|
||||
|
@ -167,9 +167,12 @@ type SemRelease = SemReleaseGeneric<'self, ()>;
|
||||
type SemAndSignalRelease = SemReleaseGeneric<'self, ~[Waitqueue]>;
|
||||
struct SemReleaseGeneric<Q> { sem: &'self Sem<Q> }
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl<Q:Owned> Drop for SemReleaseGeneric/&self<Q> {
|
||||
fn finalize(&self) {
|
||||
self.sem.release();
|
||||
unsafe {
|
||||
self.sem.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -189,6 +192,7 @@ fn SemAndSignalRelease(sem: &'r Sem<~[Waitqueue]>)
|
||||
/// A mechanism for atomic-unlock-and-deschedule blocking and signalling.
|
||||
pub struct Condvar { priv sem: &'self Sem<~[Waitqueue]> }
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for Condvar/&self { fn finalize(&self) {} }
|
||||
|
||||
pub impl Condvar/&self {
|
||||
@ -261,6 +265,7 @@ pub impl Condvar/&self {
|
||||
sem: &'self Sem<~[Waitqueue]>,
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for SemAndSignalReacquire/&self {
|
||||
fn finalize(&self) {
|
||||
unsafe {
|
||||
@ -613,6 +618,7 @@ struct RWlockReleaseRead {
|
||||
lock: &'self RWlock,
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for RWlockReleaseRead/&self {
|
||||
fn finalize(&self) {
|
||||
unsafe {
|
||||
@ -643,10 +649,12 @@ fn RWlockReleaseRead(lock: &'r RWlock) -> RWlockReleaseRead/&r {
|
||||
|
||||
// FIXME(#3588) should go inside of downgrade()
|
||||
#[doc(hidden)]
|
||||
#[unsafe_destructor]
|
||||
struct RWlockReleaseDowngrade {
|
||||
lock: &'self RWlock,
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for RWlockReleaseDowngrade/&self {
|
||||
fn finalize(&self) {
|
||||
unsafe {
|
||||
@ -685,10 +693,12 @@ fn RWlockReleaseDowngrade(lock: &'r RWlock) -> RWlockReleaseDowngrade/&r {
|
||||
|
||||
/// The "write permission" token used for rwlock.write_downgrade().
|
||||
pub struct RWlockWriteMode { priv lock: &'self RWlock }
|
||||
#[unsafe_destructor]
|
||||
impl Drop for RWlockWriteMode/&self { fn finalize(&self) {} }
|
||||
|
||||
/// The "read permission" token used for rwlock.write_downgrade().
|
||||
pub struct RWlockReadMode { priv lock: &'self RWlock }
|
||||
#[unsafe_destructor]
|
||||
impl Drop for RWlockReadMode/&self { fn finalize(&self) {} }
|
||||
|
||||
pub impl RWlockWriteMode/&self {
|
||||
|
@ -28,6 +28,7 @@ pub struct TaskPool<T> {
|
||||
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl<T> Drop for TaskPool<T> {
|
||||
fn finalize(&self) {
|
||||
for self.channels.each |channel| {
|
||||
|
@ -58,6 +58,7 @@ pub enum ObsoleteSyntax {
|
||||
ObsoleteMode,
|
||||
ObsoleteImplicitSelf,
|
||||
ObsoleteLifetimeNotation,
|
||||
ObsoleteConstManagedPointer,
|
||||
}
|
||||
|
||||
impl to_bytes::IterBytes for ObsoleteSyntax {
|
||||
@ -193,6 +194,10 @@ pub impl Parser {
|
||||
"instead of `&foo/bar`, write `&'foo bar`; instead of \
|
||||
`bar/&foo`, write `&bar<'foo>"
|
||||
),
|
||||
ObsoleteConstManagedPointer => (
|
||||
"const `@` pointer",
|
||||
"instead of `@const Foo`, write `@Foo`"
|
||||
),
|
||||
};
|
||||
|
||||
self.report(sp, kind, kind_str, desc);
|
||||
|
@ -79,7 +79,7 @@ use parse::obsolete::{ObsoleteRecordType, ObsoleteRecordPattern};
|
||||
use parse::obsolete::{ObsoleteAssertion, ObsoletePostFnTySigil};
|
||||
use parse::obsolete::{ObsoleteBareFnType, ObsoleteNewtypeEnum};
|
||||
use parse::obsolete::{ObsoleteMode, ObsoleteImplicitSelf};
|
||||
use parse::obsolete::{ObsoleteLifetimeNotation};
|
||||
use parse::obsolete::{ObsoleteLifetimeNotation, ObsoleteConstManagedPointer};
|
||||
use parse::prec::{as_prec, token_to_binop};
|
||||
use parse::token::{can_begin_expr, is_ident, is_ident_or_path};
|
||||
use parse::token::{is_plain_ident, INTERPOLATED, special_idents};
|
||||
@ -268,6 +268,7 @@ pub struct Parser {
|
||||
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for Parser {
|
||||
/* do not copy the parser; its state is tied to outside state */
|
||||
fn finalize(&self) {}
|
||||
@ -709,6 +710,9 @@ pub impl Parser {
|
||||
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)
|
||||
}
|
||||
@ -1635,6 +1639,10 @@ pub impl Parser {
|
||||
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
|
||||
|
@ -19,6 +19,7 @@ struct arc_destruct<T> {
|
||||
_data: int,
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl<T:Const> Drop for arc_destruct<T> {
|
||||
fn finalize(&self) {}
|
||||
}
|
||||
|
@ -56,6 +56,7 @@ struct r {
|
||||
_l: @nillist,
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for r {
|
||||
fn finalize(&self) {}
|
||||
}
|
||||
|
@ -13,7 +13,6 @@ fn main() {
|
||||
a: int,
|
||||
w: B,
|
||||
x: @B,
|
||||
y: @const B,
|
||||
z: @mut B
|
||||
}
|
||||
struct B {
|
||||
@ -23,7 +22,6 @@ fn main() {
|
||||
a: 1,
|
||||
w: B {a: 1},
|
||||
x: @B {a: 1},
|
||||
y: @const B {a: 1},
|
||||
z: @mut B {a: 1}
|
||||
};
|
||||
|
||||
@ -37,6 +35,5 @@ fn main() {
|
||||
// in these cases we pass through a box, so the mut
|
||||
// of the box is dominant
|
||||
p.x.a = 2; //~ ERROR assigning to immutable field
|
||||
p.y.a = 2; //~ ERROR assigning to const field
|
||||
p.z.a = 2;
|
||||
}
|
||||
|
@ -12,9 +12,12 @@ struct defer {
|
||||
x: &'self [&'self str],
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for defer<'self> {
|
||||
fn finalize(&self) {
|
||||
error!("%?", self.x);
|
||||
unsafe {
|
||||
error!("%?", self.x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,37 +0,0 @@
|
||||
// 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 match_imm_box(v: &const @Option<int>) -> int {
|
||||
match *v {
|
||||
@Some(ref i) => {*i}
|
||||
@None => {0}
|
||||
}
|
||||
}
|
||||
|
||||
fn match_const_box(v: &const @const Option<int>) -> int {
|
||||
match *v {
|
||||
@Some(ref i) => { *i } // ok because this is pure
|
||||
@None => {0}
|
||||
}
|
||||
}
|
||||
|
||||
fn process(_i: int) {}
|
||||
|
||||
fn match_const_box_and_do_bad_things(v: &const @const Option<int>) {
|
||||
match *v {
|
||||
@Some(ref i) => { //~ ERROR illegal borrow unless pure
|
||||
process(*i) //~ NOTE impure due to access to impure function
|
||||
}
|
||||
@None => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
@ -50,18 +50,6 @@ fn box_imm_recs(v: @Outer) {
|
||||
borrow(v.f.g.h); // OK
|
||||
}
|
||||
|
||||
fn box_const(v: @const ~int) {
|
||||
borrow(*v); //~ ERROR illegal borrow unless pure
|
||||
}
|
||||
|
||||
fn box_const_rec(v: @const Rec) {
|
||||
borrow(v.f); //~ ERROR illegal borrow unless pure
|
||||
}
|
||||
|
||||
fn box_const_recs(v: @const Outer) {
|
||||
borrow(v.f.g.h); //~ ERROR illegal borrow unless pure
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
||||
|
||||
|
@ -1,17 +0,0 @@
|
||||
fn mutate(x: &mut @const int) {
|
||||
*x = @3;
|
||||
}
|
||||
|
||||
fn give_away1(y: @mut @mut int) {
|
||||
mutate(y); //~ ERROR values differ in mutability
|
||||
}
|
||||
|
||||
fn give_away2(y: @mut @const int) {
|
||||
mutate(y);
|
||||
}
|
||||
|
||||
fn give_away3(y: @mut @int) {
|
||||
mutate(y); //~ ERROR values differ in mutability
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -11,7 +11,6 @@
|
||||
#[legacy_modes];
|
||||
|
||||
fn takes_mut(&&x: @mut int) { }
|
||||
fn takes_const(&&x: @const int) { }
|
||||
fn takes_imm(&&x: @int) { }
|
||||
|
||||
fn apply<T>(t: T, f: &fn(T)) {
|
||||
@ -20,10 +19,8 @@ fn apply<T>(t: T, f: &fn(T)) {
|
||||
|
||||
fn main() {
|
||||
apply(@3, takes_mut); //~ ERROR (values differ in mutability)
|
||||
apply(@3, takes_const);
|
||||
apply(@3, takes_imm);
|
||||
|
||||
apply(@mut 3, takes_mut);
|
||||
apply(@mut 3, takes_const);
|
||||
apply(@mut 3, takes_imm); //~ ERROR (values differ in mutability)
|
||||
}
|
||||
|
@ -25,9 +25,6 @@ fn main() {
|
||||
// @mut int.
|
||||
let f: @mut int = r();
|
||||
|
||||
// OK.
|
||||
let g: @const int = r();
|
||||
|
||||
// Bad.
|
||||
let h: @int = r(); //~ ERROR (values differ in mutability)
|
||||
}
|
||||
|
@ -16,10 +16,13 @@ struct foo {
|
||||
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for foo {
|
||||
fn finalize(&self) {
|
||||
io::println("Goodbye, World!");
|
||||
*self.x += 1;
|
||||
unsafe {
|
||||
io::println("Goodbye, World!");
|
||||
*self.x += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
12
src/test/compile-fail/kindck-destructor-owned.rs
Normal file
12
src/test/compile-fail/kindck-destructor-owned.rs
Normal file
@ -0,0 +1,12 @@
|
||||
struct Foo {
|
||||
f: @mut int,
|
||||
}
|
||||
|
||||
impl Drop for Foo { //~ ERROR cannot implement a destructor on a struct that is not Owned
|
||||
fn finalize(&self) {
|
||||
*self.f = 10;
|
||||
}
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
@ -1,19 +0,0 @@
|
||||
// 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 main() {
|
||||
fn f(&&v: @const int) {
|
||||
*v = 1 //~ ERROR assigning to dereference of const @ pointer
|
||||
}
|
||||
|
||||
let v = @0;
|
||||
|
||||
f(v);
|
||||
}
|
@ -17,6 +17,7 @@ fn main() {
|
||||
_x: Port<()>,
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for foo {
|
||||
fn finalize(&self) {}
|
||||
}
|
||||
|
@ -12,9 +12,12 @@ struct r {
|
||||
i: @mut int,
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for r {
|
||||
fn finalize(&self) {
|
||||
*(self.i) = *(self.i) + 1;
|
||||
unsafe {
|
||||
*(self.i) = *(self.i) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,33 +0,0 @@
|
||||
// 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 box_impl<T> {
|
||||
f: T,
|
||||
}
|
||||
|
||||
fn box_impl<T>(f: T) -> box_impl<T> {
|
||||
box_impl {
|
||||
f: f
|
||||
}
|
||||
}
|
||||
|
||||
fn set_box_impl<T>(b: box_impl<@const T>, v: @const T) {
|
||||
b.f = v;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let b = box_impl::<@int>(@3);
|
||||
set_box_impl(b, @mut 5);
|
||||
//~^ ERROR values differ in mutability
|
||||
|
||||
// No error when type of parameter actually IS @const int
|
||||
let b = box_impl::<@const int>(@3);
|
||||
set_box_impl(b, @mut 5);
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
// 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 box<T> {
|
||||
f: T
|
||||
}
|
||||
|
||||
struct box_impl<T>(box<T>);
|
||||
|
||||
fn set_box_impl<T>(b: box_impl<@const T>, v: @const T) {
|
||||
b.f = v;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let b = box_impl::<@int>(box::<@int> {f: @3});
|
||||
set_box_impl(b, @mut 5);
|
||||
//~^ ERROR values differ in mutability
|
||||
|
||||
// No error when type of parameter actually IS @const int
|
||||
let x: @const int = @3; // only way I could find to upcast
|
||||
let b = box_impl::<@const int>(box::<@const int>{f: x});
|
||||
set_box_impl(b, @mut 5);
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
trait box_trait<T> {
|
||||
fn get(&self) -> T;
|
||||
fn set(&self, t: T);
|
||||
}
|
||||
|
||||
struct box<T> {
|
||||
f: T
|
||||
}
|
||||
|
||||
struct box_impl<T>(box<T>);
|
||||
|
||||
impl<T:Copy> box_trait<T> for box_impl<T> {
|
||||
fn get(&self) -> T { return self.f; }
|
||||
fn set(&self, t: T) { self.f = t; }
|
||||
}
|
||||
|
||||
fn set_box_trait<T>(b: @box_trait<@const T>, v: @const T) {
|
||||
b.set(v);
|
||||
}
|
||||
|
||||
fn set_box_impl<T>(b: box_impl<@const T>, v: @const T) {
|
||||
b.set(v);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let b = box_impl::<@int>(box::<@int> {f: @3});
|
||||
set_box_trait(@b as @box_trait<@int>, @mut 5);
|
||||
//~^ ERROR values differ in mutability
|
||||
set_box_impl(b, @mut 5);
|
||||
//~^ ERROR values differ in mutability
|
||||
}
|
@ -10,22 +10,12 @@
|
||||
|
||||
trait Mumbo {
|
||||
fn jumbo(&self, x: @uint) -> uint;
|
||||
fn jambo(&self, x: @const uint) -> uint;
|
||||
fn jbmbo(&self) -> @uint;
|
||||
}
|
||||
|
||||
impl Mumbo for uint {
|
||||
// Cannot have a larger effect than the trait:
|
||||
unsafe fn jumbo(&self, x: @uint) { *self + *x; }
|
||||
//~^ ERROR expected impure fn but found unsafe fn
|
||||
|
||||
// Cannot accept a narrower range of parameters:
|
||||
fn jambo(&self, x: @uint) { *self + *x; }
|
||||
//~^ ERROR values differ in mutability
|
||||
|
||||
// Cannot return a wider range of values:
|
||||
fn jbmbo(&self) -> @const uint { @const 0 }
|
||||
//~^ ERROR values differ in mutability
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,31 +0,0 @@
|
||||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
trait Mumbo {
|
||||
fn jumbo(&self, x: @uint) -> uint;
|
||||
}
|
||||
|
||||
impl Mumbo for uint {
|
||||
// Note: this method def is ok, it is more accepting and
|
||||
// less effecting than the trait method:
|
||||
pure fn jumbo(&self, x: @const uint) -> uint { *self + *x }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a = 3u;
|
||||
let b = a.jumbo(@mut 6);
|
||||
|
||||
let x = @a as @Mumbo;
|
||||
let y = x.jumbo(@mut 6); //~ ERROR values differ in mutability
|
||||
let z = x.jumbo(@6);
|
||||
}
|
||||
|
||||
|
||||
|
@ -12,9 +12,12 @@ struct r {
|
||||
i: @mut int,
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for r {
|
||||
fn finalize(&self) {
|
||||
*(self.i) = *(self.i) + 1;
|
||||
unsafe {
|
||||
*(self.i) = *(self.i) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,7 @@ struct faily_box {
|
||||
|
||||
fn faily_box(i: @int) -> faily_box { faily_box { i: i } }
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for faily_box {
|
||||
fn finalize(&self) {
|
||||
fail!(~"quux");
|
||||
|
@ -12,6 +12,7 @@ struct S<T> {
|
||||
x: T
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl<T> ::core::ops::Drop for S<T> {
|
||||
fn finalize(&self) {
|
||||
io::println("bye");
|
||||
|
@ -17,9 +17,12 @@ struct r {
|
||||
|
||||
struct Box { x: r }
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for r {
|
||||
fn finalize(&self) {
|
||||
*(self.i) = *(self.i) + 1;
|
||||
unsafe {
|
||||
*(self.i) = *(self.i) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -155,6 +155,7 @@ pub mod pipes {
|
||||
p: Option<*packet<T>>,
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl<T:Owned> Drop for send_packet<T> {
|
||||
fn finalize(&self) {
|
||||
unsafe {
|
||||
@ -187,6 +188,7 @@ pub mod pipes {
|
||||
p: Option<*packet<T>>,
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl<T:Owned> Drop for recv_packet<T> {
|
||||
fn finalize(&self) {
|
||||
unsafe {
|
||||
|
@ -13,9 +13,12 @@ struct defer {
|
||||
b: &'self mut bool,
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for defer/&self {
|
||||
fn finalize(&self) {
|
||||
*(self.b) = true;
|
||||
unsafe {
|
||||
*(self.b) = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,9 +13,12 @@ struct defer {
|
||||
b: &'self mut bool,
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for defer/&self {
|
||||
fn finalize(&self) {
|
||||
*(self.b) = true;
|
||||
unsafe {
|
||||
*(self.b) = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,9 +12,12 @@ struct r {
|
||||
b: @mut int,
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for r {
|
||||
fn finalize(&self) {
|
||||
*(self.b) += 1;
|
||||
unsafe {
|
||||
*(self.b) += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,10 +13,13 @@ struct dtor {
|
||||
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for dtor {
|
||||
fn finalize(&self) {
|
||||
// abuse access to shared mutable state to write this code
|
||||
*self.x -= 1;
|
||||
unsafe {
|
||||
*self.x -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,9 +12,12 @@ struct r {
|
||||
i: @mut int,
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for r {
|
||||
fn finalize(&self) {
|
||||
*(self.i) += 1;
|
||||
unsafe {
|
||||
*(self.i) += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,9 +12,12 @@ struct shrinky_pointer {
|
||||
i: @@mut int,
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for shrinky_pointer {
|
||||
fn finalize(&self) {
|
||||
error!(~"Hello!"); **(self.i) -= 1;
|
||||
unsafe {
|
||||
error!(~"Hello!"); **(self.i) -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,9 +16,12 @@ struct finish<T> {
|
||||
arg: Arg<T>
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl<T:Copy> Drop for finish<T> {
|
||||
fn finalize(&self) {
|
||||
(self.arg.fin)(self.arg.val);
|
||||
unsafe {
|
||||
(self.arg.fin)(self.arg.val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,9 +18,12 @@ struct close_res {
|
||||
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for close_res {
|
||||
fn finalize(&self) {
|
||||
*(self.i) = false;
|
||||
unsafe {
|
||||
*(self.i) = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,15 +20,18 @@ struct notify {
|
||||
ch: Chan<bool>, v: @mut bool,
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for notify {
|
||||
fn finalize(&self) {
|
||||
error!("notify: task=%? v=%x unwinding=%b b=%b",
|
||||
task::get_task(),
|
||||
ptr::addr_of(&(*(self.v))) as uint,
|
||||
task::failing(),
|
||||
*(self.v));
|
||||
let b = *(self.v);
|
||||
self.ch.send(b);
|
||||
unsafe {
|
||||
error!("notify: task=%? v=%x unwinding=%b b=%b",
|
||||
task::get_task(),
|
||||
ptr::addr_of(&(*(self.v))) as uint,
|
||||
task::failing(),
|
||||
*(self.v));
|
||||
let b = *(self.v);
|
||||
self.ch.send(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,9 +12,12 @@ struct r {
|
||||
i: @mut int,
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for r {
|
||||
fn finalize(&self) {
|
||||
*(self.i) = *(self.i) + 1;
|
||||
unsafe {
|
||||
*(self.i) = *(self.i) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@ struct complainer {
|
||||
c: @int,
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for complainer {
|
||||
fn finalize(&self) {}
|
||||
}
|
||||
|
@ -13,9 +13,12 @@ struct foo {
|
||||
x: @mut int,
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl Drop for foo {
|
||||
fn finalize(&self) {
|
||||
*self.x += 1;
|
||||
unsafe {
|
||||
*self.x += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user