Skip to content

add #[non_owned] and #[mutable] attributes #6251

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/libcore/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ A dynamic, mutable location.
Similar to a mutable option type, but friendlier.
*/

#[mutable]
pub struct Cell<T> {
priv value: Option<T>
}
Expand Down
69 changes: 43 additions & 26 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1784,7 +1784,7 @@ pub impl TypeContents {
}

fn nonowned(_cx: ctxt) -> TypeContents {
TC_MANAGED + TC_BORROWED_POINTER
TC_MANAGED + TC_BORROWED_POINTER + TC_NON_OWNED
}

fn contains_managed(&self) -> bool {
Expand Down Expand Up @@ -1838,40 +1838,43 @@ impl ToStr for TypeContents {
}

/// Constant for a type containing nothing of interest.
static TC_NONE: TypeContents = TypeContents{bits:0b0000_00000000};
static TC_NONE: TypeContents = TypeContents{bits: 0b0000_0000_0000};

/// Contains a borrowed value with a lifetime other than static
static TC_BORROWED_POINTER: TypeContents = TypeContents{bits:0b0000_00000001};
static TC_BORROWED_POINTER: TypeContents = TypeContents{bits: 0b0000_0000_0001};

/// Contains an owned pointer (~T) but not slice of some kind
static TC_OWNED_POINTER: TypeContents = TypeContents{bits:0b000000000010};
static TC_OWNED_POINTER: TypeContents = TypeContents{bits: 0b0000_0000_0010};

/// Contains an owned vector ~[] or owned string ~str
static TC_OWNED_VEC: TypeContents = TypeContents{bits:0b000000000100};
static TC_OWNED_VEC: TypeContents = TypeContents{bits: 0b0000_0000_0100};

/// Contains a ~fn() or a ~Trait, which is non-copyable.
static TC_OWNED_CLOSURE: TypeContents = TypeContents{bits:0b000000001000};
static TC_OWNED_CLOSURE: TypeContents = TypeContents{bits: 0b0000_0000_1000};

/// Type with a destructor
static TC_DTOR: TypeContents = TypeContents{bits:0b000000010000};
static TC_DTOR: TypeContents = TypeContents{bits: 0b0000_0001_0000};

/// Contains a managed value
static TC_MANAGED: TypeContents = TypeContents{bits:0b000000100000};
static TC_MANAGED: TypeContents = TypeContents{bits: 0b0000_0010_0000};

/// &mut with any region
static TC_BORROWED_MUT: TypeContents = TypeContents{bits:0b000001000000};
static TC_BORROWED_MUT: TypeContents = TypeContents{bits: 0b0000_0100_0000};

/// Mutable content, whether owned or by ref
static TC_MUTABLE: TypeContents = TypeContents{bits:0b000010000000};
static TC_MUTABLE: TypeContents = TypeContents{bits: 0b0000_1000_0000};

/// Mutable content, whether owned or by ref
static TC_ONCE_CLOSURE: TypeContents = TypeContents{bits:0b000100000000};
/// One-shot closure
static TC_ONCE_CLOSURE: TypeContents = TypeContents{bits: 0b0001_0000_0000};

/// An enum with no variants.
static TC_EMPTY_ENUM: TypeContents = TypeContents{bits:0b010000000000};
static TC_EMPTY_ENUM: TypeContents = TypeContents{bits: 0b0010_0000_0000};

/// Contains a type marked with `#[non_owned]`
static TC_NON_OWNED: TypeContents = TypeContents{bits: 0b0100_0000_0000};

/// All possible contents.
static TC_ALL: TypeContents = TypeContents{bits:0b011111111111};
static TC_ALL: TypeContents = TypeContents{bits: 0b0111_1111_1111};

pub fn type_is_copyable(cx: ctxt, t: ty::t) -> bool {
type_contents(cx, t).is_copy(cx)
Expand Down Expand Up @@ -1939,7 +1942,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {

let _i = indenter();

let mut result = match get(ty).sty {
let result = match get(ty).sty {
// Scalar and unique types are sendable, constant, and owned
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_bare_fn(_) | ty_ptr(_) => {
Expand Down Expand Up @@ -2013,14 +2016,13 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {

ty_struct(did, ref substs) => {
let flds = struct_fields(cx, did, substs);
let flds_tc = flds.foldl(
let mut res = flds.foldl(
TC_NONE,
|tc, f| tc + tc_mt(cx, f.mt, cache));
if ty::has_dtor(cx, did) {
flds_tc + TC_DTOR
} else {
flds_tc
res += TC_DTOR;
}
apply_tc_attr(cx, did, res)
}

ty_tup(ref tys) => {
Expand All @@ -2029,7 +2031,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {

ty_enum(did, ref substs) => {
let variants = substd_enum_variants(cx, did, substs);
if variants.is_empty() {
let res = if variants.is_empty() {
// we somewhat arbitrary declare that empty enums
// are non-copyable
TC_EMPTY_ENUM
Expand All @@ -2039,7 +2041,8 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
*tc,
|tc, arg_ty| *tc + tc_ty(cx, *arg_ty, cache))
})
}
};
apply_tc_attr(cx, did, res)
}

ty_param(p) => {
Expand Down Expand Up @@ -2099,6 +2102,16 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
mc + tc_ty(cx, mt.ty, cache)
}

fn apply_tc_attr(cx: ctxt, did: def_id, mut tc: TypeContents) -> TypeContents {
if has_attr(cx, did, "mutable") {
tc += TC_MUTABLE;
}
if has_attr(cx, did, "non_owned") {
tc += TC_NON_OWNED;
}
tc
}

fn borrowed_contents(region: ty::Region,
mutbl: ast::mutability) -> TypeContents
{
Expand Down Expand Up @@ -3841,28 +3854,32 @@ pub fn lookup_trait_def(cx: ctxt, did: ast::def_id) -> @ty::TraitDef {
}
}

// Determine whether an item is annotated with #[packed] or not
pub fn lookup_packed(tcx: ctxt,
did: def_id) -> bool {
/// Determine whether an item is annotated with an attribute
pub fn has_attr(tcx: ctxt, did: def_id, attr: &str) -> bool {
if is_local(did) {
match tcx.items.find(&did.node) {
Some(
&ast_map::node_item(@ast::item {
attrs: ref attrs,
_
}, _)) => attr::attrs_contains_name(*attrs, "packed"),
}, _)) => attr::attrs_contains_name(*attrs, attr),
_ => tcx.sess.bug(fmt!("lookup_packed: %? is not an item",
did))
}
} else {
let mut ret = false;
do csearch::get_item_attrs(tcx.cstore, did) |meta_items| {
ret = attr::contains_name(meta_items, "packed");
ret = attr::contains_name(meta_items, attr);
}
ret
}
}

/// Determine whether an item is annotated with `#[packed]` or not
pub fn lookup_packed(tcx: ctxt, did: def_id) -> bool {
has_attr(tcx, did, "packed")
}

// Look up a field ID, whether or not it's local
// Takes a list of type substs in case the struct is generic
pub fn lookup_field_type(tcx: ctxt,
Expand Down
19 changes: 19 additions & 0 deletions src/test/compile-fail/mutable-enum.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[mutable]
enum Foo { A }

fn bar<T: Const>(_: T) {}

fn main() {
let x = A;
bar(x); //~ ERROR instantiating a type parameter with an incompatible type `Foo`, which does not fulfill `Const`
}
19 changes: 19 additions & 0 deletions src/test/compile-fail/mutable-struct.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[mutable]
struct Foo { a: int }

fn bar<T: Const>(_: T) {}

fn main() {
let x = Foo { a: 5 };
bar(x); //~ ERROR instantiating a type parameter with an incompatible type `Foo`, which does not fulfill `Const`
}
19 changes: 19 additions & 0 deletions src/test/compile-fail/non_owned-enum.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[non_owned]
enum Foo { A }

fn bar<T: Owned>(_: T) {}

fn main() {
let x = A;
bar(x); //~ ERROR instantiating a type parameter with an incompatible type `Foo`, which does not fulfill `Owned`
}
19 changes: 19 additions & 0 deletions src/test/compile-fail/non_owned-struct.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[non_owned]
struct Foo { a: int }

fn bar<T: Owned>(_: T) {}

fn main() {
let x = Foo { a: 5 };
bar(x); //~ ERROR instantiating a type parameter with an incompatible type `Foo`, which does not fulfill `Owned`
}