Region + borrow checker support and tests for overloaded autoderef.

This commit is contained in:
Eduard Burtescu 2014-03-11 22:27:55 +02:00
parent feedd37653
commit 27c62449db
8 changed files with 540 additions and 24 deletions

View file

@ -0,0 +1,131 @@
// Copyright 2014 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.
// Test how overloaded deref interacts with borrows when DerefMut
// is implemented.
use std::ops::{Deref, DerefMut};
struct Own<T> {
value: *mut T
}
impl<T> Deref<T> for Own<T> {
fn deref<'a>(&'a self) -> &'a T {
unsafe { &*self.value }
}
}
impl<T> DerefMut<T> for Own<T> {
fn deref_mut<'a>(&'a mut self) -> &'a mut T {
unsafe { &mut *self.value }
}
}
struct Point {
x: int,
y: int
}
impl Point {
fn get(&self) -> (int, int) {
(self.x, self.y)
}
fn set(&mut self, x: int, y: int) {
self.x = x;
self.y = y;
}
fn x_ref<'a>(&'a self) -> &'a int {
&self.x
}
fn y_mut<'a>(&'a mut self) -> &'a mut int {
&mut self.y
}
}
fn deref_imm_field(x: Own<Point>) {
let _i = &x.y;
}
fn deref_mut_field1(x: Own<Point>) {
let _i = &mut x.y; //~ ERROR cannot borrow
}
fn deref_mut_field2(mut x: Own<Point>) {
let _i = &mut x.y;
}
fn deref_extend_field<'a>(x: &'a Own<Point>) -> &'a int {
&x.y
}
fn deref_extend_mut_field1<'a>(x: &'a Own<Point>) -> &'a mut int {
&mut x.y //~ ERROR cannot borrow
}
fn deref_extend_mut_field2<'a>(x: &'a mut Own<Point>) -> &'a mut int {
&mut x.y
}
fn assign_field1<'a>(x: Own<Point>) {
x.y = 3; //~ ERROR cannot borrow
}
fn assign_field2<'a>(x: &'a Own<Point>) {
x.y = 3; //~ ERROR cannot assign
}
fn assign_field3<'a>(x: &'a mut Own<Point>) {
x.y = 3;
}
// FIXME(eddyb) #12825 This shouldn't attempt to call deref_mut.
/*
fn deref_imm_method(x: Own<Point>) {
let _i = x.get();
}
*/
fn deref_mut_method1(x: Own<Point>) {
x.set(0, 0); //~ ERROR cannot borrow
}
fn deref_mut_method2(mut x: Own<Point>) {
x.set(0, 0);
}
fn deref_extend_method<'a>(x: &'a Own<Point>) -> &'a int {
x.x_ref()
}
fn deref_extend_mut_method1<'a>(x: &'a Own<Point>) -> &'a mut int {
x.y_mut() //~ ERROR cannot borrow
}
fn deref_extend_mut_method2<'a>(x: &'a mut Own<Point>) -> &'a mut int {
x.y_mut()
}
fn assign_method1<'a>(x: Own<Point>) {
*x.y_mut() = 3; //~ ERROR cannot borrow
}
fn assign_method2<'a>(x: &'a Own<Point>) {
*x.y_mut() = 3; //~ ERROR cannot borrow
}
fn assign_method3<'a>(x: &'a mut Own<Point>) {
*x.y_mut() = 3;
}
pub fn main() {}

View file

@ -0,0 +1,122 @@
// Copyright 2014 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.
// Test how overloaded deref interacts with borrows when only
// Deref and not DerefMut is implemented.
use std::ops::Deref;
struct Rc<T> {
value: *T
}
impl<T> Deref<T> for Rc<T> {
fn deref<'a>(&'a self) -> &'a T {
unsafe { &*self.value }
}
}
struct Point {
x: int,
y: int
}
impl Point {
fn get(&self) -> (int, int) {
(self.x, self.y)
}
fn set(&mut self, x: int, y: int) {
self.x = x;
self.y = y;
}
fn x_ref<'a>(&'a self) -> &'a int {
&self.x
}
fn y_mut<'a>(&'a mut self) -> &'a mut int {
&mut self.y
}
}
fn deref_imm_field(x: Rc<Point>) {
let _i = &x.y;
}
fn deref_mut_field1(x: Rc<Point>) {
let _i = &mut x.y; //~ ERROR cannot borrow
}
fn deref_mut_field2(mut x: Rc<Point>) {
let _i = &mut x.y; //~ ERROR cannot borrow
}
fn deref_extend_field<'a>(x: &'a Rc<Point>) -> &'a int {
&x.y
}
fn deref_extend_mut_field1<'a>(x: &'a Rc<Point>) -> &'a mut int {
&mut x.y //~ ERROR cannot borrow
}
fn deref_extend_mut_field2<'a>(x: &'a mut Rc<Point>) -> &'a mut int {
&mut x.y //~ ERROR cannot borrow
}
fn assign_field1<'a>(x: Rc<Point>) {
x.y = 3; //~ ERROR cannot assign
}
fn assign_field2<'a>(x: &'a Rc<Point>) {
x.y = 3; //~ ERROR cannot assign
}
fn assign_field3<'a>(x: &'a mut Rc<Point>) {
x.y = 3; //~ ERROR cannot assign
}
fn deref_imm_method(x: Rc<Point>) {
let _i = x.get();
}
fn deref_mut_method1(x: Rc<Point>) {
x.set(0, 0); //~ ERROR cannot borrow
}
fn deref_mut_method2(mut x: Rc<Point>) {
x.set(0, 0); //~ ERROR cannot borrow
}
fn deref_extend_method<'a>(x: &'a Rc<Point>) -> &'a int {
x.x_ref()
}
fn deref_extend_mut_method1<'a>(x: &'a Rc<Point>) -> &'a mut int {
x.y_mut() //~ ERROR cannot borrow
}
fn deref_extend_mut_method2<'a>(x: &'a mut Rc<Point>) -> &'a mut int {
x.y_mut() //~ ERROR cannot borrow
}
fn assign_method1<'a>(x: Rc<Point>) {
*x.y_mut() = 3; //~ ERROR cannot borrow
}
fn assign_method2<'a>(x: &'a Rc<Point>) {
*x.y_mut() = 3; //~ ERROR cannot borrow
}
fn assign_method3<'a>(x: &'a mut Rc<Point>) {
*x.y_mut() = 3; //~ ERROR cannot borrow
}
pub fn main() {}

View file

@ -0,0 +1,16 @@
// Copyright 2014 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.
use std::rc::Rc;
pub fn main() {
let _x = Rc::new(vec!(1, 2)).move_iter();
//~^ ERROR cannot move out of dereference of `&`-pointer
}

View file

@ -0,0 +1,82 @@
// Copyright 2014 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.
use std::cell::Cell;
use std::ops::{Deref, DerefMut};
use std::vec_ng::Vec;
#[deriving(Eq)]
struct DerefCounter<T> {
count_imm: Cell<uint>,
count_mut: uint,
value: T
}
impl<T> DerefCounter<T> {
fn new(value: T) -> DerefCounter<T> {
DerefCounter {
count_imm: Cell::new(0),
count_mut: 0,
value: value
}
}
fn counts(&self) -> (uint, uint) {
(self.count_imm.get(), self.count_mut)
}
}
impl<T> Deref<T> for DerefCounter<T> {
fn deref<'a>(&'a self) -> &'a T {
self.count_imm.set(self.count_imm.get() + 1);
&self.value
}
}
impl<T> DerefMut<T> for DerefCounter<T> {
fn deref_mut<'a>(&'a mut self) -> &'a mut T {
self.count_mut += 1;
&mut self.value
}
}
#[deriving(Eq, Show)]
struct Point {
x: int,
y: int
}
impl Point {
fn get(&self) -> (int, int) {
(self.x, self.y)
}
}
pub fn main() {
let mut p = DerefCounter::new(Point {x: 0, y: 0});
let _ = p.x;
assert_eq!(p.counts(), (1, 0));
let _ = &p.x;
assert_eq!(p.counts(), (2, 0));
let _ = &mut p.y;
assert_eq!(p.counts(), (2, 1));
p.x += 3;
assert_eq!(p.counts(), (2, 2));
p.get();
assert_eq!(p.counts(), (2, 3));
// Check the final state.
assert_eq!(*p, Point {x: 3, y: 0});
}

View file

@ -0,0 +1,24 @@
// Copyright 2014 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 DerefArray<'a, T> {
inner: &'a [T]
}
impl<'a, T> Deref<&'a [T]> for DerefArray<'a, T> {
fn deref<'b>(&'b self) -> &'b &'a [T] {
&self.inner
}
}
pub fn main() {
let a = &[1, 2, 3];
assert_eq!(DerefArray {inner: a}[1], 2);
}

View file

@ -0,0 +1,71 @@
// Copyright 2014 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.
use std::rc::Rc;
struct DerefWrapper<X, Y> {
x: X,
y: Y
}
impl<X, Y> DerefWrapper<X, Y> {
fn get_x(self) -> X {
self.x
}
}
impl<X, Y> Deref<Y> for DerefWrapper<X, Y> {
fn deref<'a>(&'a self) -> &'a Y {
&self.y
}
}
mod priv_test {
pub struct DerefWrapperHideX<X, Y> {
priv x: X,
y: Y
}
impl<X, Y> DerefWrapperHideX<X, Y> {
pub fn new(x: X, y: Y) -> DerefWrapperHideX<X, Y> {
DerefWrapperHideX {
x: x,
y: y
}
}
}
impl<X, Y> Deref<Y> for DerefWrapperHideX<X, Y> {
fn deref<'a>(&'a self) -> &'a Y {
&self.y
}
}
}
pub fn main() {
let nested = DerefWrapper {x: true, y: DerefWrapper {x: 0, y: 1}};
// Use the first field that you can find.
assert_eq!(nested.x, true);
assert_eq!((*nested).x, 0);
// Same for methods, even though there are multiple
// candidates (at different nesting levels).
assert_eq!(nested.get_x(), true);
assert_eq!((*nested).get_x(), 0);
// Also go through multiple levels of indirection.
assert_eq!(Rc::new(nested).x, true);
let nested_priv = priv_test::DerefWrapperHideX::new(true, DerefWrapper {x: 0, y: 1});
// FIXME(eddyb) #12808 should skip private fields.
// assert_eq!(nested_priv.x, 0);
assert_eq!((*nested_priv).x, 0);
}