提交 369adaf5 编写于 作者: N Niko Matsakis

Implement the rules for RFC 599, and add various tests.

Fixes #22211.
上级 ab579883
......@@ -438,23 +438,25 @@ fn convert_angle_bracketed_parameters<'tcx>(this: &AstConv<'tcx>,
{
let regions: Vec<_> =
data.lifetimes.iter()
.map(|l| ast_region_to_region(this.tcx(), l))
.collect();
.map(|l| ast_region_to_region(this.tcx(), l))
.collect();
let region_substs =
create_region_substs(this, rscope, span, decl_generics, regions);
let types: Vec<_> =
data.types.iter()
.map(|t| ast_ty_to_ty(this, rscope, &**t))
.collect();
.enumerate()
.map(|(i,t)| ast_ty_arg_to_ty(this, rscope, decl_generics,
i, &region_substs, t))
.collect();
let assoc_bindings: Vec<_> =
data.bindings.iter()
.map(|b| ConvertedBinding { item_name: b.ident.name,
ty: ast_ty_to_ty(this, rscope, &*b.ty),
span: b.span })
.collect();
.map(|b| ConvertedBinding { item_name: b.ident.name,
ty: ast_ty_to_ty(this, rscope, &*b.ty),
span: b.span })
.collect();
(region_substs, types, assoc_bindings)
}
......@@ -525,9 +527,11 @@ fn convert_parenthesized_parameters<'tcx>(this: &AstConv<'tcx>,
create_region_substs(this, rscope, span, decl_generics, Vec::new());
let binding_rscope = BindingRscope::new();
let inputs = data.inputs.iter()
.map(|a_t| ast_ty_to_ty(this, &binding_rscope, &**a_t))
.collect::<Vec<Ty<'tcx>>>();
let inputs =
data.inputs.iter()
.map(|a_t| ast_ty_arg_to_ty(this, &binding_rscope, decl_generics,
0, &region_substs, a_t))
.collect::<Vec<Ty<'tcx>>>();
let input_params: Vec<_> = repeat(String::new()).take(inputs.len()).collect();
let (implied_output_region,
......@@ -655,7 +659,7 @@ fn ast_path_to_trait_ref<'a,'tcx>(
let (regions, types, assoc_bindings) = match path.segments.last().unwrap().parameters {
ast::AngleBracketedParameters(ref data) => {
// For now, require that parenthetical5D notation be used
// For now, require that parenthetical notation be used
// only with `Fn()` etc.
if !this.tcx().sess.features.borrow().unboxed_closures && trait_def.paren_sugar {
span_err!(this.tcx().sess, path.span, E0215,
......@@ -1070,10 +1074,45 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
qpath.item_path.identifier.name);
}
// Parses the programmer's textual representation of a type into our
// internal notion of a type.
pub fn ast_ty_to_ty<'tcx>(
this: &AstConv<'tcx>, rscope: &RegionScope, ast_ty: &ast::Ty) -> Ty<'tcx>
/// Convert a type supplied as value for a type argument from AST into our
/// our internal representation. This is the same as `ast_ty_to_ty` but that
/// it applies the object lifetime default.
///
/// # Parameters
///
/// * `this`, `rscope`: the surrounding context
/// * `decl_generics`: the generics of the struct/enum/trait declaration being
/// referenced
/// * `index`: the index of the type parameter being instantiated from the list
/// (we assume it is in the `TypeSpace`)
/// * `region_substs`: a partial substitution consisting of
/// only the region type parameters being supplied to this type.
/// * `ast_ty`: the ast representation of the type being supplied
pub fn ast_ty_arg_to_ty<'tcx>(this: &AstConv<'tcx>,
rscope: &RegionScope,
decl_generics: &ty::Generics<'tcx>,
index: usize,
region_substs: &Substs<'tcx>,
ast_ty: &ast::Ty)
-> Ty<'tcx>
{
let tcx = this.tcx();
if let Some(def) = decl_generics.types.opt_get(TypeSpace, index) {
let object_lifetime_default = def.object_lifetime_default.subst(tcx, region_substs);
let rscope1 = &ObjectLifetimeDefaultRscope::new(rscope, object_lifetime_default);
ast_ty_to_ty(this, rscope1, ast_ty)
} else {
ast_ty_to_ty(this, rscope, ast_ty)
}
}
/// Parses the programmer's textual representation of a type into our
/// internal notion of a type.
pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
rscope: &RegionScope,
ast_ty: &ast::Ty)
-> Ty<'tcx>
{
debug!("ast_ty_to_ty(ast_ty={})",
ast_ty.repr(this.tcx()));
......
......@@ -12,7 +12,7 @@
use std::vec;
pub struct Container<'a> {
reader: &'a mut Reader //~ ERROR explicit lifetime bound required
reader: &'a mut Reader
}
impl<'a> Container<'a> {
......@@ -33,5 +33,5 @@ pub fn for_stdin<'a>() -> Container<'a> {
fn main() {
let mut c = for_stdin();
let mut v = Vec::new();
c.read_to(v);
c.read_to(v); //~ ERROR mismatched types
}
......@@ -9,12 +9,12 @@
// except according to those terms.
fn f() { }
struct S(Box<FnMut()>); //~ ERROR explicit lifetime bound required
pub static C: S = S(f);
struct S(Box<FnMut()>);
pub static C: S = S(f); //~ ERROR mismatched types
fn g() { }
type T = Box<FnMut()>; //~ ERROR explicit lifetime bound required
pub static D: T = g;
type T = Box<FnMut()>;
pub static D: T = g; //~ ERROR mismatched types
fn main() {}
// 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 if a struct declares multiple region bounds for a given
// type parameter, an explicit lifetime bound is required on object
// lifetimes within.
#![allow(dead_code)]
trait Test {
fn foo(&self) { }
}
struct Ref0<T:?Sized> {
r: *mut T
}
struct Ref1<'a,T:'a+?Sized> {
r: &'a T
}
struct Ref2<'a,'b:'a,T:'a+'b+?Sized> {
r: &'a &'b T
}
fn a<'a,'b>(t: Ref2<'a,'b,Test>) {
//~^ ERROR lifetime bound for this object type cannot be deduced from context
}
fn b(t: Ref2<Test>) {
//~^ ERROR lifetime bound for this object type cannot be deduced from context
}
fn c(t: Ref2<&Test>) {
// In this case, the &'a overrides.
}
fn d(t: Ref2<Ref1<Test>>) {
// In this case, the lifetime parameter from the Ref1 overrides.
}
fn e(t: Ref2<Ref0<Test>>) {
//~^ ERROR lifetime bound for this object type cannot be deduced from context
//
// In this case, Ref0 just inherits.
}
fn f(t: &Ref2<Test>) {
//~^ ERROR lifetime bound for this object type cannot be deduced from context
}
fn main() {
}
// 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 cases where the old rules under lifetime elision
// yield slightly different results than the new rules.
#![allow(dead_code)]
trait SomeTrait {
fn dummy(&self) { }
}
struct SomeStruct<'a> {
r: Box<SomeTrait+'a>
}
fn deref<T>(ss: &T) -> T {
// produces the type of a deref without worrying about whether a
// move out would actually be legal
loop { }
}
fn load0<'a>(ss: &'a Box<SomeTrait>) -> Box<SomeTrait> {
// Under old rules, the fully elaborated types of input/output were:
//
// for<'a,'b> fn(&'a Box<SomeTrait+'b>) -> Box<SomeTrait+'a>
//
// Under new rules the result is:
//
// for<'a> fn(&'a Box<SomeTrait+'a>) -> Box<SomeTrait+'static>
//
// Therefore, we get a type error attempting to return `deref(ss)`
// since `SomeTrait+'a <: SomeTrait+'static` does not hold.
deref(ss)
//~^ ERROR cannot infer
}
fn load1(ss: &SomeTrait) -> &SomeTrait {
// Under old rules, the fully elaborated types of input/output were:
//
// for<'a,'b> fn(&'a (SomeTrait+'b)) -> &'a (SomeTrait+'a)
//
// Under new rules the result is:
//
// for<'a> fn(&'a (SomeTrait+'a)) -> &'a (SomeTrait+'a)
//
// In both cases, returning `ss` is legal.
ss
}
fn load2<'a>(ss: &'a SomeTrait) -> &SomeTrait {
// Same as `load1` but with an explicit name thrown in for fun.
ss
}
fn load3<'a,'b>(ss: &'a SomeTrait) -> &'b SomeTrait {
// Under old rules, the fully elaborated types of input/output were:
//
// for<'a,'b,'c>fn(&'a (SomeTrait+'c)) -> &'b (SomeTrait+'a)
//
// Based on the input/output types, the compiler could infer that
// 'c : 'a
// 'b : 'a
// must hold, and therefore it permitted `&'a (Sometrait+'c)` to be
// coerced to `&'b (SomeTrait+'a)`.
//
// Under the newer defaults, though, we get:
//
// for<'a,'b> fn(&'a (SomeTrait+'a)) -> &'b (SomeTrait+'b)
//
// which fails to type check.
ss
//~^ ERROR cannot infer
//~| ERROR mismatched types
}
fn main() {
}
// 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 cases where the defaults should lead to errors being
// reported.
#![allow(dead_code)]
trait SomeTrait {
fn dummy(&self) { }
}
struct SomeStruct<'a> {
r: Box<SomeTrait+'a>
}
fn load(ss: &mut SomeStruct) -> Box<SomeTrait> {
// `Box<SomeTrait>` defaults to a `'static` bound, so this return
// is illegal.
ss.r //~ ERROR mismatched types
}
fn store(ss: &mut SomeStruct, b: Box<SomeTrait>) {
// No error: b is bounded by 'static which outlives the
// (anonymous) lifetime on the struct.
ss.r = b;
}
fn store1<'b>(ss: &mut SomeStruct, b: Box<SomeTrait+'b>) {
// Here we override the lifetimes explicitly, and so naturally we get an error.
ss.r = b; //~ ERROR mismatched types
}
fn main() {
}
// 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 a "pass-through" object-lifetime-default that produces errors.
#![allow(dead_code)]
trait SomeTrait {
fn dummy(&self) { }
}
struct MyBox<T:?Sized> {
r: Box<T>
}
fn deref<T>(ss: &T) -> T {
// produces the type of a deref without worrying about whether a
// move out would actually be legal
loop { }
}
fn load0(ss: &MyBox<SomeTrait>) -> MyBox<SomeTrait> {
deref(ss) //~ ERROR cannot infer
}
fn load1<'a,'b>(a: &'a MyBox<SomeTrait>,
b: &'b MyBox<SomeTrait>)
-> &'b MyBox<SomeTrait>
{
a
//~^ ERROR cannot infer
//~| ERROR mismatched types
//~| ERROR mismatched types
}
fn main() {
}
......@@ -25,7 +25,7 @@ struct Foo<'a,'b,'c> {
c: Box<Is<'a>>,
d: Box<IsSend>,
e: Box<Is<'a>+Send>, // we can derive two bounds, but one is 'static, so ok
f: Box<SomeTrait>, //~ ERROR explicit lifetime bound required
f: Box<SomeTrait>, // OK, defaults to 'static due to RFC 599.
g: Box<SomeTrait+'a>,
z: Box<Is<'a>+'b+'c>, //~ ERROR only a single explicit lifetime bound is permitted
......
......@@ -11,6 +11,8 @@
// Various tests related to testing how region inference works
// with respect to the object receivers.
#![allow(warnings)]
trait Foo {
fn borrowed<'a>(&'a self) -> &'a ();
}
......@@ -21,29 +23,6 @@ fn borrowed_receiver_same_lifetime<'a>(x: &'a Foo) -> &'a () {
x.borrowed()
}
// Borrowed receiver but two distinct lifetimes, we get an error.
fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a Foo) -> &'b () {
x.borrowed() //~ ERROR cannot infer
}
// Borrowed receiver with two distinct lifetimes, but we know that
// 'b:'a, hence &'a () is permitted.
fn borrowed_receiver_related_lifetimes<'a,'b>(x: &'a (Foo+'b)) -> &'a () {
x.borrowed()
}
// Here we have two distinct lifetimes, but we try to return a pointer
// with the longer lifetime when (from the signature) we only know
// that it lives as long as the shorter lifetime. Therefore, error.
fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (Foo+'b)) -> &'b () {
x.borrowed() //~ ERROR cannot infer
}
// Here, the object is bounded by an anonymous lifetime and returned
// as `&'static`, so you get an error.
fn owned_receiver(x: Box<Foo>) -> &'static () {
x.borrowed() //~ ERROR cannot infer
}
fn main() {}
#[rustc_error]
fn main() {} //~ ERROR compilation successful
// Copyright 2012-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.
// Various tests related to testing how region inference works
// with respect to the object receivers.
trait Foo {
fn borrowed<'a>(&'a self) -> &'a ();
}
// Borrowed receiver but two distinct lifetimes, we get an error.
fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a Foo) -> &'b () {
x.borrowed() //~ ERROR cannot infer
}
fn main() {}
// Copyright 2012-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.
// Various tests related to testing how region inference works
// with respect to the object receivers.
#![allow(warnings)]
trait Foo {
fn borrowed<'a>(&'a self) -> &'a ();
}
// Borrowed receiver with two distinct lifetimes, but we know that
// 'b:'a, hence &'a () is permitted.
fn borrowed_receiver_related_lifetimes<'a,'b>(x: &'a (Foo+'b)) -> &'a () {
x.borrowed()
}
#[rustc_error]
fn main() {} //~ ERROR compilation successful
// Copyright 2012-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.
// Various tests related to testing how region inference works
// with respect to the object receivers.
trait Foo {
fn borrowed<'a>(&'a self) -> &'a ();
}
// Here we have two distinct lifetimes, but we try to return a pointer
// with the longer lifetime when (from the signature) we only know
// that it lives as long as the shorter lifetime. Therefore, error.
fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (Foo+'b)) -> &'b () {
x.borrowed() //~ ERROR cannot infer
}
fn main() {}
// Copyright 2012-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.
// Various tests related to testing how region inference works
// with respect to the object receivers.
trait Foo {
fn borrowed<'a>(&'a self) -> &'a ();
}
// Here, the object is bounded by an anonymous lifetime and returned
// as `&'static`, so you get an error.
fn owned_receiver(x: Box<Foo>) -> &'static () {
x.borrowed() //~ ERROR `*x` does not live long enough
}
fn main() {}
......@@ -26,7 +26,9 @@ fn b(v: &[u8]) -> Box<Foo + 'static> {
}
fn c(v: &[u8]) -> Box<Foo> {
box v // OK thanks to lifetime elision
// same as previous case due to RFC 599
box v //~ ERROR declared lifetime bound not satisfied
}
fn d<'a,'b>(v: &'a [u8]) -> Box<Foo+'b> {
......
......@@ -9,6 +9,7 @@
// except according to those terms.
#![feature(box_syntax)]
#![allow(warnings)]
trait A<T> {}
struct B<'a, T>(&'a (A<T>+'a));
......@@ -17,19 +18,7 @@ trait X {}
impl<'a, T> X for B<'a, T> {}
fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
box B(&*v) as Box<X>
}
fn g<'a, T: 'static>(v: Box<A<T>>) -> Box<X+'static> {
box B(&*v) as Box<X> //~ ERROR cannot infer
}
fn h<'a, T, U>(v: Box<A<U>+'static>) -> Box<X+'static> {
box B(&*v) as Box<X>
}
fn i<'a, T, U>(v: Box<A<U>>) -> Box<X+'static> {
box B(&*v) as Box<X> //~ ERROR cannot infer
box B(&*v) as Box<X> //~ ERROR `*v` does not live long enough
}
fn main() {}
......
// 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.
#![feature(box_syntax)]
trait A<T> {}
struct B<'a, T>(&'a (A<T>+'a));
trait X {}
impl<'a, T> X for B<'a, T> {}
fn g<'a, T: 'static>(v: Box<A<T>+'a>) -> Box<X+'static> {
box B(&*v) as Box<X> //~ ERROR cannot infer
}
fn main() { }
// 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.
#![feature(box_syntax)]
#![allow(warnings)]
trait A<T> {}
struct B<'a, T>(&'a (A<T>+'a));
trait X {}
impl<'a, T> X for B<'a, T> {}
fn h<'a, T, U>(v: Box<A<U>+'static>) -> Box<X+'static> {
box B(&*v) as Box<X> //~ ERROR `*v` does not live long enough
}
fn main() {}
// 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.
#![feature(box_syntax)]
trait A<T> {}
struct B<'a, T>(&'a (A<T>+'a));
trait X {}
impl<'a, T> X for B<'a, T> {}
fn i<'a, T, U>(v: Box<A<U>+'a>) -> Box<X+'static> {
box B(&*v) as Box<X> //~ ERROR cannot infer
}
fn main() {}
......@@ -14,7 +14,7 @@ trait seq { }
impl<T> seq<T> for Vec<T> { //~ ERROR wrong number of type arguments
/* ... */
}
impl seq<bool> for u32 {
impl seq<bool> for u32 { //~ ERROR wrong number of type arguments
/* Treat the integer as a sequence of bits */
}
......
......@@ -57,6 +57,7 @@ fn main() {
let pt3 = PointF::<i32> {
//~^ ERROR wrong number of type arguments
//~| ERROR structure constructor specifies a structure of type
x: 9i32,
y: 10i32,
};
......
......@@ -22,7 +22,7 @@ fn c(x: Box<Foo+Sync+Send>) {
fn d(x: Box<Foo>) {
a(x); //~ ERROR mismatched types
//~| expected `Box<Foo + Send>`
//~| found `Box<Foo>`
//~| found `Box<Foo + 'static>`
//~| expected bounds `Send`
//~| found no bounds
}
......
......@@ -24,8 +24,7 @@ fn c(x: Box<Foo+Sync>) {
}
fn d(x: &'static (Foo+Sync)) {
b(x); //~ ERROR cannot infer
//~^ ERROR mismatched types
b(x);
}
fn main() {}
......@@ -12,7 +12,9 @@
trait Three<A,B,C> { fn dummy(&self) -> (A,B,C); }
fn foo(_: &Three()) //~ ERROR wrong number of type arguments
fn foo(_: &Three())
//~^ ERROR wrong number of type arguments
//~| ERROR no associated type `Output`
{}
fn main() { }
......@@ -12,7 +12,9 @@
trait Zero { fn dummy(&self); }
fn foo(_: Zero()) //~ ERROR wrong number of type arguments
fn foo(_: Zero())
//~^ ERROR wrong number of type arguments
//~| ERROR no associated type `Output` defined in `Zero`
{}
fn main() { }
......@@ -14,6 +14,7 @@ trait Trait {}
fn f<F:Trait(isize) -> isize>(x: F) {}
//~^ ERROR wrong number of type arguments: expected 0, found 1
//~| ERROR no associated type `Output`
fn main() {}
// 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 the lifetime of the enclosing `&` is used for the object
// lifetime bound.
#![allow(dead_code)]
trait Test {
fn foo(&self) { }
}
struct Ref<'a,T:'a+?Sized> {
r: &'a T
}
struct SomeStruct<'a> {
t: Ref<'a,Test>,
u: Ref<'a,Test+'a>,
}
fn a<'a>(t: Ref<'a,Test>, mut ss: SomeStruct<'a>) {
ss.t = t;
}
fn b<'a>(t: Ref<'a,Test>, mut ss: SomeStruct<'a>) {
ss.u = t;
}
fn c<'a>(t: Ref<'a,Test+'a>, mut ss: SomeStruct<'a>) {
ss.t = t;
}
fn d<'a>(t: Ref<'a,Test+'a>, mut ss: SomeStruct<'a>) {
ss.u = t;
}
fn main() {
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册