librustc: Forbid &
pointers (other than &'static
) inside @
boxes.
This makes custom borrowing implementations for custom smart pointers sound.
This commit is contained in:
parent
93fa7a4b09
commit
9089cf2ec9
@ -31,10 +31,17 @@ enum TreeNode<K, V> {
|
||||
}
|
||||
|
||||
/// Create a treemap
|
||||
pub fn init<K, V>() -> Treemap<K, V> { @Empty }
|
||||
pub fn init<K: 'static, V: 'static>() -> Treemap<K, V> {
|
||||
@Empty
|
||||
}
|
||||
|
||||
/// Insert a value into the map
|
||||
pub fn insert<K:Eq + Ord,V>(m: Treemap<K, V>, k: K, v: V) -> Treemap<K, V> {
|
||||
pub fn insert<K:Eq + Ord + 'static,
|
||||
V:'static>(
|
||||
m: Treemap<K, V>,
|
||||
k: K,
|
||||
v: V)
|
||||
-> Treemap<K, V> {
|
||||
@match m {
|
||||
@Empty => Node(@k, @v, @Empty, @Empty),
|
||||
@Node(kk, vv, left, right) => cond!(
|
||||
@ -46,7 +53,11 @@ pub fn insert<K:Eq + Ord,V>(m: Treemap<K, V>, k: K, v: V) -> Treemap<K, V> {
|
||||
}
|
||||
|
||||
/// Find a value based on the key
|
||||
pub fn find<K:Eq + Ord,V:Clone>(m: Treemap<K, V>, k: K) -> Option<V> {
|
||||
pub fn find<K:Eq + Ord + 'static,
|
||||
V:Clone + 'static>(
|
||||
m: Treemap<K, V>,
|
||||
k: K)
|
||||
-> Option<V> {
|
||||
match *m {
|
||||
Empty => None,
|
||||
Node(kk, v, left, right) => cond!(
|
||||
|
@ -25,7 +25,7 @@ pub enum MutList<T> {
|
||||
}
|
||||
|
||||
/// Create a list from a vector
|
||||
pub fn from_vec<T:Clone>(v: &[T]) -> @List<T> {
|
||||
pub fn from_vec<T:Clone + 'static>(v: &[T]) -> @List<T> {
|
||||
v.rev_iter().fold(@Nil::<T>, |t, h| @Cons((*h).clone(), t))
|
||||
}
|
||||
|
||||
@ -109,7 +109,7 @@ pub fn head<T:Clone>(ls: @List<T>) -> T {
|
||||
}
|
||||
|
||||
/// Appends one list to another
|
||||
pub fn append<T:Clone>(l: @List<T>, m: @List<T>) -> @List<T> {
|
||||
pub fn append<T:Clone + 'static>(l: @List<T>, m: @List<T>) -> @List<T> {
|
||||
match *l {
|
||||
Nil => return m,
|
||||
Cons(ref x, xs) => {
|
||||
|
@ -423,7 +423,7 @@ impl<S:Encoder,T:Encodable<S>> Encodable<S> for @T {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D:Decoder,T:Decodable<D>> Decodable<D> for @T {
|
||||
impl<D:Decoder,T:Decodable<D> + 'static> Decodable<D> for @T {
|
||||
fn decode(d: &mut D) -> @T {
|
||||
@Decodable::decode(d)
|
||||
}
|
||||
@ -435,7 +435,7 @@ impl<S:Encoder,T:Encodable<S>> Encodable<S> for @mut T {
|
||||
}
|
||||
}
|
||||
|
||||
impl<D:Decoder,T:Decodable<D>> Decodable<D> for @mut T {
|
||||
impl<D:Decoder,T:Decodable<D> + 'static> Decodable<D> for @mut T {
|
||||
fn decode(d: &mut D) -> @mut T {
|
||||
@mut Decodable::decode(d)
|
||||
}
|
||||
|
@ -1259,8 +1259,9 @@ fn encode_info_for_items(ecx: &EncodeContext,
|
||||
|
||||
// Path and definition ID indexing
|
||||
|
||||
fn create_index<T:Clone + Hash + IterBytes>(index: ~[entry<T>])
|
||||
-> ~[@~[entry<T>]] {
|
||||
fn create_index<T:Clone + Hash + IterBytes + 'static>(
|
||||
index: ~[entry<T>])
|
||||
-> ~[@~[entry<T>]] {
|
||||
let mut buckets: ~[@mut ~[entry<T>]] = ~[];
|
||||
for uint::range(0u, 256u) |_i| { buckets.push(@mut ~[]); };
|
||||
for index.iter().advance |elt| {
|
||||
@ -1275,9 +1276,10 @@ fn create_index<T:Clone + Hash + IterBytes>(index: ~[entry<T>])
|
||||
return buckets_frozen;
|
||||
}
|
||||
|
||||
fn encode_index<T>(ebml_w: &mut writer::Encoder,
|
||||
buckets: ~[@~[entry<T>]],
|
||||
write_fn: &fn(@io::Writer, &T)) {
|
||||
fn encode_index<T:'static>(
|
||||
ebml_w: &mut writer::Encoder,
|
||||
buckets: ~[@~[entry<T>]],
|
||||
write_fn: &fn(@io::Writer, &T)) {
|
||||
let writer = ebml_w.writer;
|
||||
ebml_w.start_tag(tag_index);
|
||||
let mut bucket_locs: ~[uint] = ~[];
|
||||
|
@ -285,6 +285,10 @@ pub fn check_expr(e: @expr, (cx, v): (Context, visit::vt<Context>)) {
|
||||
}
|
||||
|
||||
match e.node {
|
||||
expr_unary(_, box(_), interior) => {
|
||||
let interior_type = ty::expr_ty(cx.tcx, interior);
|
||||
let _ = check_durable(cx.tcx, interior_type, interior.span);
|
||||
}
|
||||
expr_cast(source, _) => {
|
||||
check_cast_for_escaping_regions(cx, source, e);
|
||||
match ty::get(ty::expr_ty(cx.tcx, e)).sty {
|
||||
|
@ -79,7 +79,7 @@ impl<T:Subst> Subst for ~[T] {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T:Subst> Subst for @T {
|
||||
impl<T:Subst + 'static> Subst for @T {
|
||||
fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> @T {
|
||||
match self {
|
||||
&@ref t => @t.subst(tcx, substs)
|
||||
|
@ -858,7 +858,7 @@ fn mk_rcache() -> creader_cache {
|
||||
return @mut HashMap::new();
|
||||
}
|
||||
|
||||
pub fn new_ty_hash<V>() -> @mut HashMap<t, V> {
|
||||
pub fn new_ty_hash<V:'static>() -> @mut HashMap<t, V> {
|
||||
@mut HashMap::new()
|
||||
}
|
||||
|
||||
|
@ -112,7 +112,7 @@ impl<T: DeepClone> DeepClone for ~T {
|
||||
}
|
||||
|
||||
// FIXME: #6525: should also be implemented for `T: Send + DeepClone`
|
||||
impl<T: Freeze + DeepClone> DeepClone for @T {
|
||||
impl<T: Freeze + DeepClone + 'static> DeepClone for @T {
|
||||
/// Return a deep copy of the managed box. The `Freeze` trait is required to prevent performing
|
||||
/// a deep clone of a potentially cyclical type.
|
||||
#[inline]
|
||||
@ -120,7 +120,7 @@ impl<T: Freeze + DeepClone> DeepClone for @T {
|
||||
}
|
||||
|
||||
// FIXME: #6525: should also be implemented for `T: Send + DeepClone`
|
||||
impl<T: Freeze + DeepClone> DeepClone for @mut T {
|
||||
impl<T: Freeze + DeepClone + 'static> DeepClone for @mut T {
|
||||
/// Return a deep copy of the managed box. The `Freeze` trait is required to prevent performing
|
||||
/// a deep clone of a potentially cyclical type.
|
||||
#[inline]
|
||||
|
@ -446,12 +446,12 @@ pub fn pow_with_uint<T:NumCast+One+Zero+Div<T,T>+Mul<T,T>>(radix: uint, pow: uin
|
||||
total
|
||||
}
|
||||
|
||||
impl<T: Zero> Zero for @mut T {
|
||||
impl<T: Zero + 'static> Zero for @mut T {
|
||||
fn zero() -> @mut T { @mut Zero::zero() }
|
||||
fn is_zero(&self) -> bool { (**self).is_zero() }
|
||||
}
|
||||
|
||||
impl<T: Zero> Zero for @T {
|
||||
impl<T: Zero + 'static> Zero for @T {
|
||||
fn zero() -> @T { @Zero::zero() }
|
||||
fn is_zero(&self) -> bool { (**self).is_zero() }
|
||||
}
|
||||
|
@ -242,7 +242,7 @@ impl<T: Rand> Rand for ~T {
|
||||
fn rand<R: Rng>(rng: &mut R) -> ~T { ~rng.gen() }
|
||||
}
|
||||
|
||||
impl<T: Rand> Rand for @T {
|
||||
impl<T: Rand + 'static> Rand for @T {
|
||||
#[inline]
|
||||
fn rand<R: Rng>(rng: &mut R) -> @T { @rng.gen() }
|
||||
}
|
||||
|
@ -414,8 +414,7 @@ pub enum MapChain<K,V> {
|
||||
|
||||
|
||||
// get the map from an env frame
|
||||
impl <K: Eq + Hash + IterBytes, V> MapChain<K,V>{
|
||||
|
||||
impl <K: Eq + Hash + IterBytes + 'static, V: 'static> MapChain<K,V>{
|
||||
// Constructor. I don't think we need a zero-arg one.
|
||||
fn new(init: ~HashMap<K,@V>) -> @mut MapChain<K,V> {
|
||||
@mut BaseMapChain(init)
|
||||
|
@ -21,7 +21,7 @@ pub struct Interner<T> {
|
||||
}
|
||||
|
||||
// when traits can extend traits, we should extend index<uint,T> to get []
|
||||
impl<T:Eq + IterBytes + Hash + Freeze + Clone> Interner<T> {
|
||||
impl<T:Eq + IterBytes + Hash + Freeze + Clone + 'static> Interner<T> {
|
||||
pub fn new() -> Interner<T> {
|
||||
Interner {
|
||||
map: @mut HashMap::new(),
|
||||
|
@ -18,11 +18,15 @@ pub struct alist<A,B> {
|
||||
data: @mut ~[Entry<A,B>]
|
||||
}
|
||||
|
||||
pub fn alist_add<A,B>(lst: &alist<A,B>, k: A, v: B) {
|
||||
pub fn alist_add<A:'static,B:'static>(lst: &alist<A,B>, k: A, v: B) {
|
||||
lst.data.push(Entry{key:k, value:v});
|
||||
}
|
||||
|
||||
pub fn alist_get<A:Clone,B:Clone>(lst: &alist<A,B>, k: A) -> B {
|
||||
pub fn alist_get<A:Clone + 'static,
|
||||
B:Clone + 'static>(
|
||||
lst: &alist<A,B>,
|
||||
k: A)
|
||||
-> B {
|
||||
let eq_fn = lst.eq_fn;
|
||||
for lst.data.iter().advance |entry| {
|
||||
if eq_fn(entry.key.clone(), k.clone()) {
|
||||
@ -33,13 +37,13 @@ pub fn alist_get<A:Clone,B:Clone>(lst: &alist<A,B>, k: A) -> B {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new_int_alist<B>() -> alist<int, B> {
|
||||
pub fn new_int_alist<B:'static>() -> alist<int, B> {
|
||||
fn eq_int(a: int, b: int) -> bool { a == b }
|
||||
return alist {eq_fn: eq_int, data: @mut ~[]};
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new_int_alist_2<B>() -> alist<int, B> {
|
||||
pub fn new_int_alist_2<B:'static>() -> alist<int, B> {
|
||||
#[inline]
|
||||
fn eq_int(a: int, b: int) -> bool { a == b }
|
||||
return alist {eq_fn: eq_int, data: @mut ~[]};
|
||||
|
10
src/test/compile-fail/box-static-bound.rs
Normal file
10
src/test/compile-fail/box-static-bound.rs
Normal file
@ -0,0 +1,10 @@
|
||||
fn f<T>(x: T) -> @T {
|
||||
@x //~ ERROR value may contain borrowed pointers
|
||||
}
|
||||
|
||||
fn g<T:'static>(x: T) -> @T {
|
||||
@x // ok
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -14,6 +14,7 @@ fn to_foo<T:Clone + foo>(t: T) -> @foo {
|
||||
@t as @foo
|
||||
//~^ ERROR value may contain borrowed pointers; add `'static` bound
|
||||
//~^^ ERROR cannot pack type
|
||||
//~^^^ ERROR value may contain borrowed pointers
|
||||
}
|
||||
|
||||
fn to_foo2<T:Clone + foo + 'static>(t: T) -> @foo {
|
||||
|
@ -23,5 +23,6 @@ fn main() {
|
||||
copy2(&x); //~ ERROR does not fulfill `'static`
|
||||
|
||||
copy2(@3);
|
||||
copy2(@&x); //~ ERROR does not fulfill `'static`
|
||||
copy2(@&x); //~ ERROR value may contain borrowed pointers
|
||||
//~^ ERROR does not fulfill `'static`
|
||||
}
|
||||
|
@ -18,12 +18,16 @@ struct Rec<A> {
|
||||
rec: Option<@mut RecEnum<A>>
|
||||
}
|
||||
|
||||
fn make_cycle<A>(a: A) {
|
||||
fn make_cycle<A:'static>(a: A) {
|
||||
let g: @mut RecEnum<A> = @mut RecEnum(Rec {val: a, rec: None});
|
||||
g.rec = Some(g);
|
||||
}
|
||||
|
||||
fn f<A:Send + Clone,B:Send + Clone>(a: A, b: B) -> @fn() -> (A, B) {
|
||||
fn f<A:Send + Clone + 'static,
|
||||
B:Send + Clone + 'static>(
|
||||
a: A,
|
||||
b: B)
|
||||
-> @fn() -> (A, B) {
|
||||
let result: @fn() -> (A, B) = || (a.clone(), b.clone());
|
||||
result
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
|
||||
|
||||
fn box<T>(x: Box<T>) -> @Box<T> { return @x; }
|
||||
fn box<T:'static>(x: Box<T>) -> @Box<T> { return @x; }
|
||||
|
||||
struct Box<T> {x: T, y: T, z: T}
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
struct Recbox<T> {x: @T}
|
||||
|
||||
fn reclift<T>(t: T) -> Recbox<T> { return Recbox {x: @t}; }
|
||||
fn reclift<T:'static>(t: T) -> Recbox<T> { return Recbox {x: @t}; }
|
||||
|
||||
pub fn main() {
|
||||
let foo: int = 17;
|
||||
|
@ -14,12 +14,12 @@
|
||||
// happen.)
|
||||
|
||||
fn eat_tup(_r: ~@(int, @fn(Pair) -> int)) {}
|
||||
fn eat_rec(_r: @~Rec) {}
|
||||
fn eat_rec(_r: ~Rec) {}
|
||||
|
||||
struct Rec<'self> { a: int, b: &'self fn(Pair) -> int }
|
||||
struct Pair { x: int, y: int }
|
||||
|
||||
pub fn main() {
|
||||
eat_tup(~@(10, |a| a.x ));
|
||||
eat_rec(@~Rec{a: 10, b: |a| a.x });
|
||||
eat_rec(~Rec{a: 10, b: |a| a.x });
|
||||
}
|
||||
|
@ -8,13 +8,15 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
struct list<'self, T> {
|
||||
element: &'self T,
|
||||
next: Option<@mut list<'self, T>>
|
||||
static S: &'static str = "str";
|
||||
|
||||
struct list<T> {
|
||||
element: T,
|
||||
next: Option<@mut list<T>>
|
||||
}
|
||||
|
||||
impl<'self, T> list<'self, T>{
|
||||
pub fn addEnd(&mut self, element: &'self T) {
|
||||
impl<T:'static> list<T> {
|
||||
pub fn addEnd(&mut self, element: T) {
|
||||
let newList = list {
|
||||
element: element,
|
||||
next: None
|
||||
@ -25,10 +27,9 @@ impl<'self, T> list<'self, T>{
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let s = @"str";
|
||||
let ls = list {
|
||||
element: &s,
|
||||
element: S,
|
||||
next: None
|
||||
};
|
||||
println(*ls.element);
|
||||
println(ls.element);
|
||||
}
|
||||
|
@ -10,19 +10,19 @@
|
||||
|
||||
trait repeat<A> { fn get(&self) -> A; }
|
||||
|
||||
impl<A:Clone> repeat<A> for @A {
|
||||
impl<A:Clone + 'static> repeat<A> for @A {
|
||||
fn get(&self) -> A {
|
||||
(**self).clone()
|
||||
}
|
||||
}
|
||||
|
||||
fn repeater<A:Clone>(v: @A) -> @repeat:<A> {
|
||||
fn repeater<A:Clone + 'static>(v: @A) -> @repeat:<A> {
|
||||
// Note: owned kind is not necessary as A appears in the trait type
|
||||
@v as @repeat:<A> // No
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let x = &3;
|
||||
let x = 3;
|
||||
let y = repeater(@x);
|
||||
assert_eq!(*x, *(y.get()));
|
||||
assert_eq!(x, y.get());
|
||||
}
|
||||
|
@ -19,12 +19,12 @@ struct Smallintmap<T> {v: ~[option<T>]}
|
||||
|
||||
struct V<T> { v: ~[option<T>] }
|
||||
|
||||
fn mk<T>() -> @mut Smallintmap<T> {
|
||||
fn mk<T:'static>() -> @mut Smallintmap<T> {
|
||||
let mut v: ~[option<T>] = ~[];
|
||||
return @mut Smallintmap {v: v};
|
||||
}
|
||||
|
||||
fn f<T,U>() {
|
||||
fn f<T,U:'static>() {
|
||||
let mut sim = mk::<U>();
|
||||
error!(sim);
|
||||
}
|
||||
|
@ -1,34 +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 Ctxt { v: uint }
|
||||
|
||||
trait get_ctxt<'self> {
|
||||
fn get_ctxt(&self) -> &'self Ctxt;
|
||||
}
|
||||
|
||||
struct HasCtxt<'self> { c: &'self Ctxt }
|
||||
|
||||
impl<'self> get_ctxt<'self> for HasCtxt<'self> {
|
||||
fn get_ctxt(&self) -> &'self Ctxt {
|
||||
self.c
|
||||
}
|
||||
}
|
||||
|
||||
fn get_v(gc: @get_ctxt:) -> uint {
|
||||
gc.get_ctxt().v
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let ctxt = Ctxt { v: 22 };
|
||||
let hc = HasCtxt { c: &ctxt };
|
||||
|
||||
assert_eq!(get_v(@hc as @get_ctxt:), 22);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user