Introduce the new phantomdata/phantomfn markers and integrate them

into variance inference; fix various bugs in variance inference
so that it considers the correct set of constraints; modify infer to
consider the results of variance inference for type arguments.
This commit is contained in:
Niko Matsakis 2015-02-12 05:16:02 -05:00
parent dfc5c0f1e8
commit 2594d56e32
38 changed files with 1521 additions and 502 deletions

View file

@ -0,0 +1,31 @@
// Copyright 2015 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.
#![allow(dead_code)]
trait Get<T> : 'static {
fn get(&self, t: T);
}
fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
-> Box<Get<&'min i32>>
where 'max : 'min
{
v //~ ERROR mismatched types
}
fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
-> Box<Get<&'max i32>>
where 'max : 'min
{
v
}
fn main() { }

View file

@ -0,0 +1,31 @@
// Copyright 2015 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.
#![allow(dead_code)]
trait Get<T> {
fn get(&self, t: T);
}
fn get_min_from_max<'min, 'max, G>()
where 'max : 'min, G : Get<&'max i32>
{
impls_get::<G,&'min i32>() //~ ERROR mismatched types
}
fn get_max_from_min<'min, 'max, G>()
where 'max : 'min, G : Get<&'min i32>
{
impls_get::<G,&'max i32>()
}
fn impls_get<G,T>() where G : Get<T> { }
fn main() { }

View file

@ -0,0 +1,31 @@
// Copyright 2015 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.
#![allow(dead_code)]
trait Get {
fn get(&self);
}
fn get_min_from_max<'min, 'max, G>()
where 'max : 'min, G : 'max, &'max G : Get
{
impls_get::<&'min G>(); //~ ERROR mismatched types
}
fn get_max_from_min<'min, 'max, G>()
where 'max : 'min, G : 'max, &'min G : Get
{
impls_get::<&'max G>();
}
fn impls_get<G>() where G : Get { }
fn main() { }

View file

@ -0,0 +1,31 @@
// Copyright 2015 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.
#![allow(dead_code)]
trait Get<T> : 'static {
fn get(&self) -> T;
}
fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
-> Box<Get<&'min i32>>
where 'max : 'min
{
v
}
fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
-> Box<Get<&'max i32>>
where 'max : 'min
{
v //~ ERROR mismatched types
}
fn main() { }

View file

@ -0,0 +1,31 @@
// Copyright 2015 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.
#![allow(dead_code)]
trait Get<T> {
fn get(&self) -> T;
}
fn get_min_from_max<'min, 'max, G>()
where 'max : 'min, G : Get<&'max i32>
{
impls_get::<G,&'min i32>()
}
fn get_max_from_min<'min, 'max, G>()
where 'max : 'min, G : Get<&'min i32>
{
impls_get::<G,&'max i32>() //~ ERROR mismatched types
}
fn impls_get<G,T>() where G : Get<T> { }
fn main() { }

View file

@ -0,0 +1,31 @@
// Copyright 2015 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.
#![allow(dead_code)]
trait Get {
fn get() -> Self;
}
fn get_min_from_max<'min, 'max, G>()
where 'max : 'min, G : 'max, &'max G : Get
{
impls_get::<&'min G>();
}
fn get_max_from_min<'min, 'max, G>()
where 'max : 'min, G : 'max, &'min G : Get
{
impls_get::<&'max G>(); //~ ERROR mismatched types
}
fn impls_get<G>() where G : Get { }
fn main() { }

View file

@ -0,0 +1,31 @@
// Copyright 2015 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.
#![allow(dead_code)]
trait Get<T> : 'static {
fn get(&self, t: T) -> T;
}
fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
-> Box<Get<&'min i32>>
where 'max : 'min
{
v //~ ERROR mismatched types
}
fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
-> Box<Get<&'max i32>>
where 'max : 'min
{
v //~ ERROR mismatched types
}
fn main() { }

View file

@ -0,0 +1,31 @@
// Copyright 2015 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.
#![allow(dead_code)]
trait Get<T> {
fn get(&self, t: T) -> T;
}
fn get_min_from_max<'min, 'max, G>()
where 'max : 'min, G : Get<&'max i32>
{
impls_get::<G,&'min i32>() //~ ERROR mismatched types
}
fn get_max_from_min<'min, 'max, G>()
where 'max : 'min, G : Get<&'min i32>
{
impls_get::<G,&'max i32>() //~ ERROR mismatched types
}
fn impls_get<G,T>() where G : Get<T> { }
fn main() { }

View file

@ -0,0 +1,31 @@
// Copyright 2015 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.
#![allow(dead_code)]
trait Get {
fn get(&self) -> Self;
}
fn get_min_from_max<'min, 'max, G>()
where 'max : 'min, &'max G : Get
{
impls_get::<&'min G>(); //~ ERROR mismatched types
}
fn get_max_from_min<'min, 'max, G>()
where 'max : 'min, &'min G : Get
{
impls_get::<&'max G>(); //~ ERROR mismatched types
}
fn impls_get<G>() where G : Get { }
fn main() { }

View file

@ -0,0 +1,25 @@
// 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.
// Test that disallow lifetime parameters that are unused.
use std::marker;
struct Bivariant<'a>; //~ ERROR parameter `'a` is never used
struct Struct<'a, 'd> { //~ ERROR parameter `'d` is never used
field: &'a [i32]
}
trait Trait<'a, 'd> { //~ ERROR parameter `'d` is never used
fn method(&'a self);
}
fn main() {}

View file

@ -0,0 +1,21 @@
// 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.
// Test that disallow lifetime parameters that are unused.
enum Foo<'a> { //~ ERROR parameter `'a` is never used
Foo1(Bar<'a>)
}
enum Bar<'a> { //~ ERROR parameter `'a` is never used
Bar1(Foo<'a>)
}
fn main() {}

View file

@ -0,0 +1,64 @@
// 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.
#![deny(bivariance)]
#![allow(dead_code)]
// Check that bounds on type parameters (other than `Self`) do not
// influence variance.
#[rustc_variance]
trait Getter<T> { //~ ERROR types=[[+];[-];[]]
fn get(&self) -> T;
}
#[rustc_variance]
trait Setter<T> { //~ ERROR types=[[-];[-];[]]
fn get(&self, T);
}
#[rustc_variance]
struct TestStruct<U,T:Setter<U>> { //~ ERROR types=[[+, +];[];[]]
t: T, u: U
}
#[rustc_variance]
enum TestEnum<U,T:Setter<U>> {//~ ERROR types=[[*, +];[];[]]
//~^ ERROR parameter `U` is never used
Foo(T)
}
#[rustc_variance]
trait TestTrait<U,T:Setter<U>> { //~ ERROR types=[[-, +];[-];[]]
fn getter(&self, u: U) -> T;
}
#[rustc_variance]
trait TestTrait2<U> : Getter<U> { //~ ERROR types=[[+];[-];[]]
}
#[rustc_variance]
trait TestTrait3<U> { //~ ERROR types=[[-];[-];[]]
fn getter<T:Getter<U>>(&self);
}
#[rustc_variance]
struct TestContraStruct<U,T:Setter<U>> { //~ ERROR types=[[*, +];[];[]]
//~^ ERROR parameter `U` is never used
t: T
}
#[rustc_variance]
struct TestBox<U,T:Getter<U>+Setter<U>> { //~ ERROR types=[[*, +];[];[]]
//~^ ERROR parameter `U` is never used
t: T
}
pub fn main() { }

View file

@ -0,0 +1,74 @@
// 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.
// Test that we correctly infer variance for type parameters in
// various types and traits.
#[rustc_variance]
struct TestImm<A, B> { //~ ERROR types=[[+, +];[];[]]
x: A,
y: B,
}
#[rustc_variance]
struct TestMut<A, B:'static> { //~ ERROR types=[[+, o];[];[]]
x: A,
y: &'static mut B,
}
#[rustc_variance]
struct TestIndirect<A:'static, B:'static> { //~ ERROR types=[[+, o];[];[]]
m: TestMut<A, B>
}
#[rustc_variance]
struct TestIndirect2<A:'static, B:'static> { //~ ERROR types=[[o, o];[];[]]
n: TestMut<A, B>,
m: TestMut<B, A>
}
#[rustc_variance]
trait Getter<A> { //~ ERROR types=[[+];[-];[]]
fn get(&self) -> A;
}
#[rustc_variance]
trait Setter<A> { //~ ERROR types=[[-];[o];[]]
fn set(&mut self, a: A);
}
#[rustc_variance]
trait GetterSetter<A> { //~ ERROR types=[[o];[o];[]]
fn get(&self) -> A;
fn set(&mut self, a: A);
}
#[rustc_variance]
trait GetterInTypeBound<A> { //~ ERROR types=[[-];[-];[]]
// Here, the use of `A` in the method bound *does* affect
// variance. Think of it as if the method requested a dictionary
// for `T:Getter<A>`. Since this dictionary is an input, it is
// contravariant, and the Getter is covariant w/r/t A, yielding an
// overall contravariant result.
fn do_it<T:Getter<A>>(&self);
}
#[rustc_variance]
trait SetterInTypeBound<A> { //~ ERROR types=[[+];[-];[]]
fn do_it<T:Setter<A>>(&self);
}
#[rustc_variance]
struct TestObject<A, R> { //~ ERROR types=[[-, +];[];[]]
n: Box<Setter<A>+Send>,
m: Box<Getter<R>+Send>,
}
fn main() {}

View file

@ -0,0 +1,51 @@
// 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.
#![deny(bivariance)]
#![allow(dead_code)]
use std::cell::Cell;
// Check that a type parameter which is only used in a trait bound is
// not considered bivariant.
#[rustc_variance]
struct InvariantMut<'a,A:'a,B:'a> { //~ ERROR types=[[o, o];[];[]], regions=[[-];[];[]]
t: &'a mut (A,B)
}
#[rustc_variance]
struct InvariantCell<A> { //~ ERROR types=[[o];[];[]]
t: Cell<A>
}
#[rustc_variance]
struct InvariantIndirect<A> { //~ ERROR types=[[o];[];[]]
t: InvariantCell<A>
}
#[rustc_variance]
struct Covariant<A> { //~ ERROR types=[[+];[];[]]
t: A, u: fn() -> A
}
#[rustc_variance]
struct Contravariant<A> { //~ ERROR types=[[-];[];[]]
t: fn(A)
}
#[rustc_variance]
enum Enum<A,B,C> { //~ ERROR types=[[+, -, o];[];[]]
Foo(Covariant<A>),
Bar(Contravariant<B>),
Zed(Covariant<C>,Contravariant<C>)
}
pub fn main() { }

View file

@ -0,0 +1,17 @@
// 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.
// Test that we report an error for unused type parameters in types.
struct SomeStruct<'a> { x: u32 } //~ ERROR parameter `'a` is never used
enum SomeEnum<'a> { Nothing } //~ ERROR parameter `'a` is never used
trait SomeTrait<'a> { fn foo(&self); } //~ ERROR parameter `'a` is never used
fn main() {}

View file

@ -0,0 +1,36 @@
// 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.
#![allow(dead_code)]
// Test that we report an error for unused type parameters in types and traits,
// and that we offer a helpful suggestion.
struct SomeStruct<A> { x: u32 }
//~^ ERROR parameter `A` is never used
//~| HELP PhantomData
enum SomeEnum<A> { Nothing }
//~^ ERROR parameter `A` is never used
//~| HELP PhantomData
trait SomeTrait<A> { fn foo(&self); }
//~^ ERROR parameter `A` is never used
//~| HELP PhantomFn
// Here T might *appear* used, but in fact it isn't.
enum ListCell<T> {
//~^ ERROR parameter `T` is never used
//~| HELP PhantomData
Cons(Box<ListCell<T>>),
Nil
}
fn main() {}

View file

@ -0,0 +1,24 @@
// Copyright 2015 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 various uses of structs with distint variances to make sure
// they permit lifetimes to be approximated as expected.
struct SomeStruct<T>(fn(T));
fn foo<'min,'max>(v: SomeStruct<&'max ()>)
-> SomeStruct<&'min ()>
where 'max : 'min
{
v //~ ERROR mismatched types
}
#[rustc_error]
fn main() { }

View file

@ -0,0 +1,26 @@
// Copyright 2015 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 various uses of structs with distint variances to make sure
// they permit lifetimes to be approximated as expected.
#![allow(dead_code)]
struct SomeStruct<T>(fn(T));
fn bar<'min,'max>(v: SomeStruct<&'min ()>)
-> SomeStruct<&'max ()>
where 'max : 'min
{
v
}
#[rustc_error]
fn main() { } //~ ERROR compilation successful

View file

@ -0,0 +1,23 @@
// Copyright 2015 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 that a covariant struct does not permit the lifetime of a
// reference to be enlarged.
struct SomeStruct<T>(T);
fn foo<'min,'max>(v: SomeStruct<&'min ()>)
-> SomeStruct<&'max ()>
where 'max : 'min
{
v //~ ERROR mismatched types
}
fn main() { }

View file

@ -0,0 +1,25 @@
// Copyright 2015 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 that a covariant struct permits the lifetime of a reference to
// be shortened.
#![allow(dead_code)]
struct SomeStruct<T>(T);
fn foo<'min,'max>(v: SomeStruct<&'max ()>)
-> SomeStruct<&'min ()>
where 'max : 'min
{
v
}
#[rustc_error] fn main() { } //~ ERROR compilation successful

View file

@ -0,0 +1,31 @@
// Copyright 2015 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 various uses of structs with distint variances to make sure
// they permit lifetimes to be approximated as expected.
struct SomeStruct<T>(*mut T);
fn foo<'min,'max>(v: SomeStruct<&'max ()>)
-> SomeStruct<&'min ()>
where 'max : 'min
{
v //~ ERROR mismatched types
}
fn bar<'min,'max>(v: SomeStruct<&'min ()>)
-> SomeStruct<&'max ()>
where 'max : 'min
{
v //~ ERROR mismatched types
}
#[rustc_error]
fn main() { }

View file

@ -0,0 +1,34 @@
// Copyright 2015 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.
// Elaborated version of the opening example from RFC 738. This failed
// to compile before variance because invariance of `Option` prevented
// us from approximating the lifetimes of `field1` and `field2` to a
// common intersection.
#![allow(dead_code)]
struct List<'l> {
field1: &'l i32,
field2: Option<&'l i32>,
}
fn foo(field1: &i32, field2: Option<&i32>) -> i32 {
let list = List { field1: field1, field2: field2 };
*list.field1 + list.field2.cloned().unwrap_or(0)
}
fn main() {
let x = 22;
let y = Some(3);
let z = None;
assert_eq!(foo(&x, y.as_ref()), 25);
assert_eq!(foo(&x, z.as_ref()), 22);
}

View file

@ -0,0 +1,49 @@
// Copyright 2015 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.
#![allow(dead_code)]
// Get<T> is covariant in T
trait Get<T> {
fn get(&self) -> T;
}
struct Cloner<T:Clone> {
t: T
}
impl<T:Clone> Get<T> for Cloner<T> {
fn get(&self) -> T {
self.t.clone()
}
}
fn get<'a, G>(get: &G) -> i32
where G : Get<&'a i32>
{
// This call only type checks if we can use `G : Get<&'a i32>` as
// evidence that `G : Get<&'b i32>` where `'a : 'b`.
pick(get, &22)
}
fn pick<'b, G>(get: &'b G, if_odd: &'b i32) -> i32
where G : Get<&'b i32>
{
let v = *get.get();
if v % 2 != 0 { v } else { *if_odd }
}
fn main() {
let x = Cloner { t: &23 };
let y = get(&x);
assert_eq!(y, 23);
}

View file

@ -0,0 +1,28 @@
// Copyright 2015 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 that vec is now covariant in its argument type.
#![allow(dead_code)]
fn foo<'a,'b>(v1: Vec<&'a i32>, v2: Vec<&'b i32>) -> i32 {
bar(v1, v2).cloned().unwrap_or(0) // only type checks if we can intersect 'a and 'b
}
fn bar<'c>(v1: Vec<&'c i32>, v2: Vec<&'c i32>) -> Option<&'c i32> {
v1.get(0).cloned().or_else(|| v2.get(0).cloned())
}
fn main() {
let x = 22;
let y = 44;
assert_eq!(foo(vec![&x], vec![&y]), 22);
assert_eq!(foo(vec![&y], vec![&x]), 44);
}