提交 6f99a278 编写于 作者: P Patrick Walton

librustc: Implement lifetime elision.

This implements RFC 39. Omitted lifetimes in return values will now be
inferred to more useful defaults, and an error is reported if a lifetime
in a return type is omitted and one of the two lifetime elision rules
does not specify what it should be.

This primarily breaks two uncommon code patterns. The first is this:

    unsafe fn get_foo_out_of_thin_air() -> &Foo {
        ...
    }

This should be changed to:

    unsafe fn get_foo_out_of_thin_air() -> &'static Foo {
        ...
    }

The second pattern that needs to be changed is this:

    enum MaybeBorrowed<'a> {
        Borrowed(&'a str),
        Owned(String),
    }

    fn foo() -> MaybeBorrowed {
        Owned(format!("hello world"))
    }

Change code like this to:

    enum MaybeBorrowed<'a> {
        Borrowed(&'a str),
        Owned(String),
    }

    fn foo() -> MaybeBorrowed<'static> {
        Owned(format!("hello world"))
    }

Closes #15552.

[breaking-change]
上级 793b1424
......@@ -87,12 +87,14 @@ fn some(n: &mut T) -> Rawlink<T> {
}
/// Convert the `Rawlink` into an Option value
fn resolve_immut(&self) -> Option<&T> {
unsafe { self.p.to_option() }
fn resolve_immut<'a>(&self) -> Option<&'a T> {
unsafe {
mem::transmute(self.p.to_option())
}
}
/// Convert the `Rawlink` into an Option value
fn resolve(&mut self) -> Option<&mut T> {
fn resolve<'a>(&mut self) -> Option<&'a mut T> {
if self.p.is_null() {
None
} else {
......
......@@ -455,12 +455,12 @@ fn pre_escaped_content(self) -> str::MaybeOwned<'a> {
}
/// Puts `prefix` on a line above this label, with a blank line separator.
pub fn prefix_line(self, prefix: LabelText) -> LabelText {
pub fn prefix_line(self, prefix: LabelText) -> LabelText<'static> {
prefix.suffix_line(self)
}
/// Puts `suffix` on a line below this label, with a blank line separator.
pub fn suffix_line(self, suffix: LabelText) -> LabelText {
pub fn suffix_line(self, suffix: LabelText) -> LabelText<'static> {
let prefix = self.pre_escaped_content().into_string();
let suffix = suffix.pre_escaped_content();
EscStr(str::Owned(prefix.append(r"\n\n").append(suffix.as_slice())))
......
......@@ -109,7 +109,7 @@ fn as_slice<'a>(&'a self) -> &'a [T] {
}
impl<'a,T> FromIterator<T> for MaybeOwnedVector<'a,T> {
fn from_iter<I:Iterator<T>>(iterator: I) -> MaybeOwnedVector<T> {
fn from_iter<I:Iterator<T>>(iterator: I) -> MaybeOwnedVector<'a,T> {
// If we are building from scratch, might as well build the
// most flexible variant.
Growable(FromIterator::from_iter(iterator))
......
......@@ -959,13 +959,13 @@ pub fn run(self, sched: &mut Scheduler) {
type UnsafeTaskReceiver = raw::Closure;
trait ClosureConverter {
fn from_fn(|&mut Scheduler, Box<GreenTask>|) -> Self;
fn to_fn(self) -> |&mut Scheduler, Box<GreenTask>|;
fn to_fn(self) -> |&mut Scheduler, Box<GreenTask>|:'static ;
}
impl ClosureConverter for UnsafeTaskReceiver {
fn from_fn(f: |&mut Scheduler, Box<GreenTask>|) -> UnsafeTaskReceiver {
unsafe { mem::transmute(f) }
}
fn to_fn(self) -> |&mut Scheduler, Box<GreenTask>| {
fn to_fn(self) -> |&mut Scheduler, Box<GreenTask>|:'static {
unsafe { mem::transmute(self) }
}
}
......
......@@ -31,7 +31,7 @@ pub fn as_value(self) -> Value {
}
}
pub fn pred_iter(self) -> Preds {
pub fn pred_iter(self) -> Preds<'static> {
self.as_value().user_iter()
.filter(|user| user.is_a_terminator_inst())
.map(|user| user.get_parent().unwrap())
......
......@@ -4872,3 +4872,55 @@ pub enum ExplicitSelfCategory {
ByBoxExplicitSelfCategory,
}
/// Pushes all the lifetimes in the given type onto the given list. A
/// "lifetime in a type" is a lifetime specified by a reference or a lifetime
/// in a list of type substitutions. This does *not* traverse into nominal
/// types, nor does it resolve fictitious types.
pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec<ty::Region>,
typ: t) {
walk_ty(typ, |typ| {
match get(typ).sty {
ty_rptr(region, _) => accumulator.push(region),
ty_enum(_, ref substs) |
ty_trait(box TyTrait {
substs: ref substs,
..
}) |
ty_struct(_, ref substs) => {
match substs.regions {
subst::ErasedRegions => {}
subst::NonerasedRegions(ref regions) => {
for region in regions.iter() {
accumulator.push(*region)
}
}
}
}
ty_closure(ref closure_ty) => {
match closure_ty.store {
RegionTraitStore(region, _) => accumulator.push(region),
UniqTraitStore => {}
}
}
ty_nil |
ty_bot |
ty_bool |
ty_char |
ty_int(_) |
ty_uint(_) |
ty_float(_) |
ty_box(_) |
ty_uniq(_) |
ty_str |
ty_vec(_, _) |
ty_ptr(_) |
ty_bare_fn(_) |
ty_tup(_) |
ty_param(_) |
ty_infer(_) |
ty_unboxed_closure(_) |
ty_err => {}
}
})
}
......@@ -55,6 +55,7 @@
use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs};
use middle::ty;
use middle::ty_fold::TypeFolder;
use middle::typeck::rscope::{ExplicitRscope, ImpliedSingleRscope};
use middle::typeck::rscope::RegionScope;
use middle::typeck::{TypeAndSubsts, infer, lookup_def_tcx, rscope};
use middle::typeck;
......@@ -931,31 +932,45 @@ fn ty_of_method_or_bare_fn<AC:AstConv>(
Option<ty::ExplicitSelfCategory>) {
debug!("ty_of_method_or_bare_fn");
// new region names that appear inside of the fn decl are bound to
// that function type
// New region names that appear inside of the arguments of the function
// declaration are bound to that function type.
let rb = rscope::BindingRscope::new(id);
// `implied_output_region` is the region that will be assumed for any
// region parameters in the return type. In accordance with the rules for
// lifetime elision, we can determine it in two ways. First (determined
// here), if self is by-reference, then the implied output region is the
// region of the self parameter.
let mut explicit_self_category_result = None;
let self_ty = opt_self_info.and_then(|self_info| {
// Figure out and record the explicit self category.
let explicit_self_category =
determine_explicit_self_category(this, &rb, &self_info);
explicit_self_category_result = Some(explicit_self_category);
match explicit_self_category {
ty::StaticExplicitSelfCategory => None,
ty::ByValueExplicitSelfCategory => {
Some(self_info.untransformed_self_ty)
}
ty::ByReferenceExplicitSelfCategory(region, mutability) => {
Some(ty::mk_rptr(this.tcx(), region,
ty::mt {ty: self_info.untransformed_self_ty,
mutbl: mutability}))
}
ty::ByBoxExplicitSelfCategory => {
Some(ty::mk_uniq(this.tcx(), self_info.untransformed_self_ty))
let (self_ty, mut implied_output_region) = match opt_self_info {
None => (None, None),
Some(self_info) => {
// Figure out and record the explicit self category.
let explicit_self_category =
determine_explicit_self_category(this, &rb, &self_info);
explicit_self_category_result = Some(explicit_self_category);
match explicit_self_category {
ty::StaticExplicitSelfCategory => (None, None),
ty::ByValueExplicitSelfCategory => {
(Some(self_info.untransformed_self_ty), None)
}
ty::ByReferenceExplicitSelfCategory(region, mutability) => {
(Some(ty::mk_rptr(this.tcx(),
region,
ty::mt {
ty: self_info.untransformed_self_ty,
mutbl: mutability
})),
Some(region))
}
ty::ByBoxExplicitSelfCategory => {
(Some(ty::mk_uniq(this.tcx(),
self_info.untransformed_self_ty)),
None)
}
}
}
});
};
// HACK(eddyb) replace the fake self type in the AST with the actual type.
let input_tys = if self_ty.is_some() {
......@@ -964,12 +979,47 @@ fn ty_of_method_or_bare_fn<AC:AstConv>(
decl.inputs.as_slice()
};
let input_tys = input_tys.iter().map(|a| ty_of_arg(this, &rb, a, None));
let self_and_input_tys: Vec<_> =
self_ty.move_iter().chain(input_tys).collect();
// Second, if there was exactly one lifetime (either a substitution or a
// reference) in the arguments, then any anonymous regions in the output
// have that lifetime.
if implied_output_region.is_none() {
let mut self_and_input_tys_iter = self_and_input_tys.iter();
if self_ty.is_some() {
// Skip the first argument if `self` is present.
drop(self_and_input_tys_iter.next())
}
let self_and_input_tys = self_ty.move_iter().chain(input_tys).collect();
let mut accumulator = Vec::new();
for input_type in self_and_input_tys_iter {
ty::accumulate_lifetimes_in_type(&mut accumulator, *input_type)
}
if accumulator.len() == 1 {
implied_output_region = Some(*accumulator.get(0));
}
}
let output_ty = match decl.output.node {
ast::TyInfer => this.ty_infer(decl.output.span),
_ => ast_ty_to_ty(this, &rb, &*decl.output)
_ => {
match implied_output_region {
Some(implied_output_region) => {
let rb = ImpliedSingleRscope {
region: implied_output_region,
};
ast_ty_to_ty(this, &rb, &*decl.output)
}
None => {
// All regions must be explicitly specified in the output
// if the lifetime elision rules do not apply. This saves
// the user from potentially-confusing errors.
let rb = ExplicitRscope;
ast_ty_to_ty(this, &rb, &*decl.output)
}
}
}
};
(ty::BareFnTy {
......
......@@ -64,10 +64,24 @@ impl RegionScope for BindingRscope {
fn anon_regions(&self,
_: Span,
count: uint)
-> Result<Vec<ty::Region> , ()> {
-> Result<Vec<ty::Region>, ()> {
let idx = self.anon_bindings.get();
self.anon_bindings.set(idx + count);
Ok(Vec::from_fn(count, |i| ty::ReLateBound(self.binder_id,
ty::BrAnon(idx + i))))
}
}
/// A scope in which we generate one specific region. This occurs after the
/// `->` (i.e. in the return type) of function signatures.
pub struct ImpliedSingleRscope {
pub region: ty::Region,
}
impl RegionScope for ImpliedSingleRscope {
fn anon_regions(&self, _: Span, count: uint)
-> Result<Vec<ty::Region>,()> {
Ok(Vec::from_elem(count, self.region.clone()))
}
}
......@@ -94,7 +94,7 @@ impl<T: 'static> LocalData for T {}
type TLSValue = Box<LocalData + Send>;
// Gets the map from the runtime. Lazily initialises if not done so already.
unsafe fn get_local_map() -> Option<&mut Map> {
unsafe fn get_local_map<'a>() -> Option<&'a mut Map> {
if !Local::exists(None::<Task>) { return None }
let task: *mut Task = Local::unsafe_borrow();
......
......@@ -134,7 +134,7 @@ fn drop(&mut self) {
impl<'a> LocalIo<'a> {
/// Returns the local I/O: either the local scheduler's I/O services or
/// the native I/O services.
pub fn borrow() -> Option<LocalIo> {
pub fn borrow() -> Option<LocalIo<'a>> {
// FIXME(#11053): bad
//
// This is currently very unsafely implemented. We don't actually
......
......@@ -469,7 +469,7 @@ mod test {
use super::super::Loop;
use super::super::local_loop;
fn l() -> &mut Loop { &mut local_loop().loop_ }
fn l() -> &'static mut Loop { &mut local_loop().loop_ }
#[test]
fn file_test_full_simple_sync() {
......
......@@ -15,17 +15,17 @@ struct DerefWithHelper<H, T> {
}
trait Helper<T> {
fn helper_borrow<'a>(&'a self) -> &'a T;
fn helper_borrow(&self) -> &T;
}
impl<T> Helper<T> for Option<T> {
fn helper_borrow<'a>(&'a self) -> &'a T {
fn helper_borrow(&self) -> &T {
self.as_ref().unwrap()
}
}
impl<T, H: Helper<T>> Deref<T> for DerefWithHelper<H, T> {
fn deref<'a>(&'a self) -> &'a T {
fn deref(&self) -> &T {
self.helper.helper_borrow()
}
}
......
......@@ -156,7 +156,7 @@ fn lookup<C:TableCallback>(&mut self, key: Code, c: C) {
}
}
fn iter<'a>(&'a self) -> Items<'a> {
fn iter(&self) -> Items {
Items { cur: None, items: self.items.iter() }
}
}
......
......@@ -13,7 +13,7 @@
struct Foo(int);
fn foo() -> &int {
fn foo<'a>() -> &'a int {
let &Foo(ref x) = &Foo(3); //~ ERROR borrowed value does not live long enough
x
}
......
......@@ -12,7 +12,7 @@
// other `&mut` pointers.
trait Foo {
fn f1<'a>(&'a mut self) -> &'a ();
fn f1(&mut self) -> &();
fn f2(&mut self);
}
......
......@@ -18,13 +18,13 @@ struct Own<T> {
}
impl<T> Deref<T> for Own<T> {
fn deref<'a>(&'a self) -> &'a T {
fn deref(&self) -> &T {
unsafe { &*self.value }
}
}
impl<T> DerefMut<T> for Own<T> {
fn deref_mut<'a>(&'a mut self) -> &'a mut T {
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *self.value }
}
}
......@@ -44,11 +44,11 @@ fn set(&mut self, x: int, y: int) {
self.y = y;
}
fn x_ref<'a>(&'a self) -> &'a int {
fn x_ref(&self) -> &int {
&self.x
}
fn y_mut<'a>(&'a mut self) -> &'a mut int {
fn y_mut(&mut self) -> &mut int {
&mut self.y
}
}
......@@ -65,19 +65,19 @@ fn deref_mut_field2(mut x: Own<Point>) {
let _i = &mut x.y;
}
fn deref_extend_field<'a>(x: &'a Own<Point>) -> &'a int {
fn deref_extend_field(x: &Own<Point>) -> &int {
&x.y
}
fn deref_extend_mut_field1<'a>(x: &'a Own<Point>) -> &'a mut int {
fn deref_extend_mut_field1(x: &Own<Point>) -> &mut int {
&mut x.y //~ ERROR cannot borrow
}
fn deref_extend_mut_field2<'a>(x: &'a mut Own<Point>) -> &'a mut int {
fn deref_extend_mut_field2(x: &mut Own<Point>) -> &mut int {
&mut x.y
}
fn deref_extend_mut_field3<'a>(x: &'a mut Own<Point>) {
fn deref_extend_mut_field3(x: &mut Own<Point>) {
// Hmm, this is unfortunate, because with box it would work,
// but it's presently the expected outcome. See `deref_extend_mut_field4`
// for the workaround.
......@@ -124,15 +124,15 @@ fn deref_mut_method2(mut x: Own<Point>) {
x.set(0, 0);
}
fn deref_extend_method<'a>(x: &'a Own<Point>) -> &'a int {
fn deref_extend_method(x: &Own<Point>) -> &int {
x.x_ref()
}
fn deref_extend_mut_method1<'a>(x: &'a Own<Point>) -> &'a mut int {
fn deref_extend_mut_method1(x: &Own<Point>) -> &mut int {
x.y_mut() //~ ERROR cannot borrow
}
fn deref_extend_mut_method2<'a>(x: &'a mut Own<Point>) -> &'a mut int {
fn deref_extend_mut_method2(x: &mut Own<Point>) -> &mut int {
x.y_mut()
}
......
......@@ -18,7 +18,7 @@ struct Rc<T> {
}
impl<T> Deref<T> for Rc<T> {
fn deref<'a>(&'a self) -> &'a T {
fn deref(&self) -> &T {
unsafe { &*self.value }
}
}
......@@ -38,11 +38,11 @@ fn set(&mut self, x: int, y: int) {
self.y = y;
}
fn x_ref<'a>(&'a self) -> &'a int {
fn x_ref(&self) -> &int {
&self.x
}
fn y_mut<'a>(&'a mut self) -> &'a mut int {
fn y_mut(&mut self) -> &mut int {
&mut self.y
}
}
......@@ -59,15 +59,15 @@ 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 {
fn deref_extend_field(x: &Rc<Point>) -> &int {
&x.y
}
fn deref_extend_mut_field1<'a>(x: &'a Rc<Point>) -> &'a mut int {
fn deref_extend_mut_field1(x: &Rc<Point>) -> &mut int {
&mut x.y //~ ERROR cannot borrow
}
fn deref_extend_mut_field2<'a>(x: &'a mut Rc<Point>) -> &'a mut int {
fn deref_extend_mut_field2(x: &mut Rc<Point>) -> &mut int {
&mut x.y //~ ERROR cannot borrow
}
......@@ -95,15 +95,15 @@ 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 {
fn deref_extend_method(x: &Rc<Point>) -> &int {
x.x_ref()
}
fn deref_extend_mut_method1<'a>(x: &'a Rc<Point>) -> &'a mut int {
fn deref_extend_mut_method1(x: &Rc<Point>) -> &mut int {
x.y_mut() //~ ERROR cannot borrow
}
fn deref_extend_mut_method2<'a>(x: &'a mut Rc<Point>) -> &'a mut int {
fn deref_extend_mut_method2(x: &mut Rc<Point>) -> &mut int {
x.y_mut() //~ ERROR cannot borrow
}
......
......@@ -15,7 +15,7 @@
use std::gc::{GC, Gc};
fn foo<'a>(x: &'a Gc<int>) -> &'a int {
fn foo(x: &Gc<int>) -> &int {
match x {
&ref y => {
&**y // Do not expect an error here
......
......@@ -10,14 +10,14 @@
trait Foo {
fn borrowed<'a>(&'a self) -> &'a ();
fn borrowed(&self) -> &();
}
fn borrowed_receiver<'a>(x: &'a Foo) -> &'a () {
fn borrowed_receiver(x: &Foo) -> &() {
x.borrowed()
}
fn owned_receiver(x: Box<Foo>) -> &() {
fn owned_receiver(x: Box<Foo>) -> &'static () {
x.borrowed() //~ ERROR `*x` does not live long enough
}
......
......@@ -13,7 +13,7 @@ struct MyVec<T> {
}
impl<T> Index<uint, T> for MyVec<T> {
fn index<'a>(&'a self, &i: &uint) -> &'a T {
fn index(&self, &i: &uint) -> &T {
self.data.get(i)
}
}
......
......@@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn a() -> &[int] {
fn a<'a>() -> &'a [int] {
let vec = vec!(1, 2, 3, 4);
let vec: &[int] = vec.as_slice(); //~ ERROR does not live long enough
let tail = match vec {
......@@ -18,7 +18,7 @@ fn a() -> &[int] {
tail
}
fn b() -> &[int] {
fn b<'a>() -> &'a [int] {
let vec = vec!(1, 2, 3, 4);
let vec: &[int] = vec.as_slice(); //~ ERROR does not live long enough
let init = match vec {
......@@ -28,7 +28,7 @@ fn b() -> &[int] {
init
}
fn c() -> &[int] {
fn c<'a>() -> &'a [int] {
let vec = vec!(1, 2, 3, 4);
let vec: &[int] = vec.as_slice(); //~ ERROR does not live long enough
let slice = match vec {
......
......@@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn a() -> &int {
fn a<'a>() -> &'a int {
let vec = vec!(1, 2, 3, 4);
let vec: &[int] = vec.as_slice(); //~ ERROR `vec` does not live long enough
let tail = match vec {
......
......@@ -24,12 +24,12 @@ fn AddFlags(bits: u64) -> AddFlags {
AddFlags { bits: bits }
}
fn arg<'a>(x: &'a AddFlags) -> &'a AddFlags {
fn arg(x: &AddFlags) -> &AddFlags {
x
}
impl AddFlags {
fn get<'a>(&'a self) -> &'a AddFlags {
fn get(&self) -> &AddFlags {
self
}
}
......
......@@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn read_lines_borrowed() -> Vec<&str> {
fn read_lines_borrowed<'a>() -> Vec<&'a str> {
let raw_lines: Vec<String> = vec!("foo ".to_string(), " bar".to_string());
raw_lines.iter().map(|l| l.as_slice().trim()).collect()
//~^ ERROR `raw_lines` does not live long enough
......
......@@ -15,7 +15,7 @@
struct Foo;
impl Deref<Foo> for Foo {
fn deref<'a>(&'a self) -> &'a Foo {
fn deref(&self) -> &Foo {
self
}
}
......
......@@ -18,7 +18,7 @@ impl Drop for Test {
fn drop (&mut self) {}
}
fn createTest() -> &Test {
fn createTest<'a>() -> &'a Test {
let testValue = &Test; //~ ERROR borrowed value does not live long enough
return testValue;
}
......
......@@ -12,7 +12,7 @@ struct thing<'a, Q> {
x: &'a Q
}
fn thing<Q>(x: &Q) -> thing<Q> {
fn thing<'a,Q>(x: &Q) -> thing<'a,Q> {
thing{ x: x } //~ ERROR cannot infer
}
......
......@@ -15,7 +15,7 @@ pub enum TraitWrapper {
A(Box<MyTrait>),
}
fn get_tw_map<'lt>(tw: &'lt TraitWrapper) -> &'lt MyTrait {
fn get_tw_map(tw: &TraitWrapper) -> &MyTrait {
match *tw {
A(box ref map) => map, //~ ERROR cannot be dereferenced
}
......
......@@ -31,7 +31,7 @@ fn make_a<'a>(p: &'a X) -> A<'a> {
A { p: p }
}
fn make_make_a() -> A {
fn make_make_a<'a>() -> A<'a> {
let b: Box<B> = box B {i:1};
let bb: &B = &*b; //~ ERROR does not live long enough
make_a(bb)
......
// 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.
// Lifetime annotation needed because we have no arguments.
fn f() -> &int { //~ ERROR missing lifetime specifier
fail!()
}
// Lifetime annotation needed because we have two by-reference parameters.
fn g(_: &int, _: &int) -> &int { //~ ERROR missing lifetime specifier
fail!()
}
struct Foo<'a> {
x: &'a int,
}
// Lifetime annotation needed because we have two lifetime: one as a parameter
// and one on the reference.
fn h(_: &Foo) -> &int { //~ ERROR missing lifetime specifier
fail!()
}
fn main() {}
......@@ -11,7 +11,7 @@
// ignore-tidy-linelength
struct Foo<'x> { bar: int }
fn foo1(x: &Foo) -> &int {
fn foo1<'a>(x: &Foo) -> &'a int {
//~^ NOTE: consider using an explicit lifetime parameter as shown: fn foo1<'a>(x: &'a Foo) -> &'a int
&x.bar //~ ERROR: cannot infer
}
......@@ -21,34 +21,28 @@ fn foo2<'a, 'b>(x: &'a Foo) -> &'b int {
&x.bar //~ ERROR: cannot infer
}
fn foo3(x: &Foo) -> (&int, &int) {
fn foo3<'a>(x: &Foo) -> (&'a int, &'a int) {
//~^ NOTE: consider using an explicit lifetime parameter as shown: fn foo3<'a>(x: &'a Foo) -> (&'a int, &'a int)
(&x.bar, &x.bar) //~ ERROR: cannot infer
//~^ ERROR: cannot infer
}
fn foo4<'a, 'b>(x: &'a Foo) -> (&'b int, &'a int, &int) {
fn foo4<'a, 'b>(x: &'a Foo) -> (&'b int, &'a int, &'b int) {
//~^ NOTE: consider using an explicit lifetime parameter as shown: fn foo4<'a>(x: &'a Foo) -> (&'a int, &'a int, &'a int)
(&x.bar, &x.bar, &x.bar) //~ ERROR: cannot infer
//~^ ERROR: cannot infer
}
fn foo5(x: &int) -> &int {
//~^ NOTE: consider using an explicit lifetime parameter as shown: fn foo5<'a>(x: &'a int) -> &'a int
x //~ ERROR: mismatched types
//~^ ERROR: cannot infer
}
struct Bar<'x, 'y, 'z> { bar: &'y int, baz: int }
fn bar1(x: &Bar) -> (&int, &int, &int) {
//~^ NOTE: consider using an explicit lifetime parameter as shown: fn bar1<'a, 'b, 'c, 'd>(x: &'d Bar<'b, 'a, 'c>) -> (&'a int, &'d int, &'d int)
fn bar1<'a>(x: &Bar) -> (&'a int, &'a int, &'a int) {
//~^ NOTE: consider using an explicit lifetime parameter as shown: fn bar1<'b, 'c, 'a>(x: &'a Bar<'b, 'a, 'c>) -> (&'a int, &'a int, &'a int)
(x.bar, &x.baz, &x.baz) //~ ERROR: mismatched types
//~^ ERROR: cannot infer
//~^^ ERROR: cannot infer
}
fn bar2<'a, 'b, 'c>(x: &Bar<'a, 'b, 'c>) -> (&int, &int, &int) {
//~^ NOTE: consider using an explicit lifetime parameter as shown: fn bar2<'d, 'a, 'b, 'c>(x: &'d Bar<'a, 'b, 'c>) -> (&'b int, &'d int, &'d int)
fn bar2<'a, 'b, 'c>(x: &Bar<'a, 'b, 'c>) -> (&'a int, &'a int, &'a int) {
//~^ NOTE: consider using an explicit lifetime parameter as shown: fn bar2<'a, 'c>(x: &'a Bar<'a, 'a, 'c>) -> (&'a int, &'a int, &'a int)
(x.bar, &x.baz, &x.baz) //~ ERROR: mismatched types
//~^ ERROR: cannot infer
//~^^ ERROR: cannot infer
......@@ -56,13 +50,9 @@ fn bar2<'a, 'b, 'c>(x: &Bar<'a, 'b, 'c>) -> (&int, &int, &int) {
struct Cat<'x, T> { cat: &'x int, t: T }
struct Dog<'y> { dog: &'y int }
fn cat<'x>(x: Cat<'x, Dog>) -> &int {
//~^ NOTE: consider using an explicit lifetime parameter as shown: fn cat<'a, 'x>(x: Cat<'x, Dog<'a>>) -> &'a int
x.t.dog //~ ERROR: mismatched types
}
fn cat2<'x, 'y>(x: Cat<'x, Dog<'y>>) -> &int {
//~^ NOTE: consider using an explicit lifetime parameter as shown: fn cat2<'x, 'y>(x: Cat<'x, Dog<'y>>) -> &'y int
fn cat2<'x, 'y>(x: Cat<'x, Dog<'y>>) -> &'x int {
//~^ NOTE: consider using an explicit lifetime parameter as shown: fn cat2<'x>(x: Cat<'x, Dog<'x>>) -> &'x int
x.t.dog //~ ERROR: mismatched types
}
......@@ -70,16 +60,11 @@ struct Baz<'x> {
bar: &'x int
}
impl<'x> Baz<'x> {
fn baz1(&self) -> &int {
//~^ NOTE: consider using an explicit lifetime parameter as shown: fn baz1(&self) -> &'x int
self.bar //~ ERROR: mismatched types
}
}
impl<'a> Baz<'a> {
fn baz2(&self, x: &int) -> (&int, &int) {
//~^ NOTE: consider using an explicit lifetime parameter as shown: fn baz2<'b>(&self, x: &'b int) -> (&'a int, &'b int)
fn baz2<'b>(&self, x: &int) -> (&'b int, &'b int) {
// The lifetime that gets assigned to `x` seems somewhat random.
// I have disabled this test for the time being. --pcwalton
(self.bar, x) //~ ERROR: cannot infer
//~^ ERROR: mismatched types
//~^^ ERROR: mismatched types
......
......@@ -27,7 +27,7 @@ fn compute(x: &ast) -> uint {
}
}
fn map_nums(x: &ast, f: |uint| -> uint) -> &ast {
fn map_nums<'a,'b>(x: &ast, f: |uint| -> uint) -> &'a ast<'b> {
match *x {
num(x) => {
return &num(f(x)); //~ ERROR borrowed value does not live long enough
......
......@@ -13,7 +13,7 @@ enum ast<'a> {
add(&'a ast<'a>, &'a ast<'a>)
}
fn mk_add_bad2<'a>(x: &'a ast<'a>, y: &'a ast<'a>, z: &ast) -> ast {
fn mk_add_bad2<'a,'b>(x: &'a ast<'a>, y: &'a ast<'a>, z: &ast) -> ast<'b> {
add(x, y) //~ ERROR cannot infer
}
......
......@@ -40,7 +40,7 @@ fn bar<'a,'b>(x: &'a S) -> &'b S {
}
// Meets F, but not G.
fn baz<'a>(x: &'a S) -> &'a S {
fn baz(x: &S) -> &S {
fail!()
}
......
......@@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn of<T>() -> |T| { fail!(); }
fn of<'a,T>() -> |T|:'a { fail!(); }
fn subtype<T>(x: |T|) { fail!(); }
fn test_fn<'x,'y,'z,T>(_x: &'x T, _y: &'y T, _z: &'z T) {
......
......@@ -20,7 +20,7 @@ struct not_parameterized2 {
g: ||: 'static
}
fn take1(p: parameterized1) -> parameterized1 { p }
fn take1<'a>(p: parameterized1) -> parameterized1<'a> { p }
//~^ ERROR mismatched types
//~^^ ERROR cannot infer
......
......@@ -21,7 +21,7 @@ fn x_coord<'r>(p: &'r point) -> &'r int {
return &p.x;
}
fn foo(p: Gc<point>) -> &int {
fn foo<'a>(p: Gc<point>) -> &'a int {
let xc = x_coord(&*p); //~ ERROR `*p` does not live long enough
assert_eq!(*xc, 3);
return xc;
......
......@@ -12,7 +12,7 @@
use std::gc::Gc;
fn borrow<'r, T>(x: &'r T) -> &'r T {x}
fn borrow<T>(x: &T) -> &T {x}
fn foo(cond: || -> bool, make_box: || -> Gc<int>) {
let mut y: &int;
......
......@@ -22,12 +22,12 @@ struct indirect2<'a> {
g: |direct<'a>|: 'static
}
fn take_direct(p: direct) -> direct { p } //~ ERROR mismatched types
fn take_direct<'a,'b>(p: direct<'a>) -> direct<'b> { p } //~ ERROR mismatched types
//~^ ERROR cannot infer
fn take_indirect1(p: indirect1) -> indirect1 { p }
fn take_indirect2(p: indirect2) -> indirect2 { p } //~ ERROR mismatched types
fn take_indirect2<'a,'b>(p: indirect2<'a>) -> indirect2<'b> { p } //~ ERROR mismatched types
//~^ ERROR cannot infer
fn main() {}
......@@ -18,12 +18,12 @@ enum MyEnum {
Variant1
}
fn structLifetime() -> &Test {
fn structLifetime<'a>() -> &'a Test {
let testValue = &Test; //~ ERROR borrowed value does not live long enough
testValue
}
fn variantLifetime() -> &MyEnum {
fn variantLifetime<'a>() -> &'a MyEnum {
let testValue = &Variant1; //~ ERROR borrowed value does not live long enough
testValue
}
......
......@@ -19,7 +19,7 @@ fn with<R>(f: |x: &int| -> R) -> R {
f(&3)
}
fn return_it() -> &int {
fn return_it<'a>() -> &'a int {
with(|o| o) //~ ERROR mismatched types
//~^ ERROR lifetime of return value does not outlive the function call
//~^^ ERROR cannot infer
......
......@@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn f<'a>(_x : &'a int) -> &'a int {
fn f(_x: &int) -> &int {
return &3; //~ ERROR borrowed value does not live long enough
}
......
......@@ -34,11 +34,11 @@ struct A<'r> {
p: &'r X
}
fn make_a<'r>(p:&'r X) -> A<'r> {
fn make_a(p:&X) -> A {
A{p:p}
}
fn make_make_a() -> A {
fn make_make_a<'a>() -> A<'a> {
let b: Box<B> = box B {
i: 1,
};
......
......@@ -17,7 +17,7 @@ struct Box {
}
impl Box {
fn get<'a>(&'a self) -> &'a uint {
fn get(&self) -> &uint {
&self.x
}
fn set(&mut self, x: uint) {
......
......@@ -60,7 +60,7 @@ fn clear(&mut self) {}
impl<T> Map<int, T> for cat<T> {
fn contains_key(&self, k: &int) -> bool { *k <= self.meows }
fn find<'a>(&'a self, k: &int) -> Option<&'a T> {
fn find(&self, k: &int) -> Option<&T> {
if *k <= self.meows {
Some(&self.name)
} else {
......@@ -75,7 +75,7 @@ fn insert(&mut self, k: int, _: T) -> bool {
true
}
fn find_mut<'a>(&'a mut self, _k: &int) -> Option<&'a mut T> { fail!() }
fn find_mut(&mut self, _k: &int) -> Option<&mut T> { fail!() }
fn remove(&mut self, k: &int) -> bool {
if self.find(k).is_some() {
......@@ -91,7 +91,7 @@ fn swap(&mut self, _k: int, _v: T) -> Option<T> { fail!() }
}
impl<T> cat<T> {
pub fn get<'a>(&'a self, k: &int) -> &'a T {
pub fn get(&self, k: &int) -> &T {
match self.find(k) {
Some(v) => { v }
None => { fail!("epic fail"); }
......
......@@ -42,7 +42,7 @@ fn check_flags(exp: u64) {
}
impl AddFlags {
fn check_flags<'a>(&'a self, exp: u64) -> &'a AddFlags {
fn check_flags(&self, exp: u64) -> &AddFlags {
check_flags(exp);
self
}
......
......@@ -19,7 +19,7 @@ pub fn buf(&self) -> &'a Vec<u8> {
}
}
fn font<'r>(fontbuf: &'r Vec<u8> ) -> font<'r> {
fn font(fontbuf: &Vec<u8> ) -> font {
font {
fontbuf: fontbuf
}
......
......@@ -12,7 +12,7 @@ struct CMap<'a> {
buf: &'a [u8],
}
fn CMap<'r>(buf: &'r [u8]) -> CMap<'r> {
fn CMap(buf: &[u8]) -> CMap {
CMap {
buf: buf
}
......
......@@ -8,6 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn broken<'r>(v: &'r [u8], i: uint, j: uint) -> &'r [u8] { v.slice(i, j) }
fn broken(v: &[u8], i: uint, j: uint) -> &[u8] { v.slice(i, j) }
pub fn main() {}
......@@ -33,7 +33,7 @@ struct Outer<'a> {
}
impl<'a> Outer<'a> {
fn new<'r>(inner: &'r Inner) -> Outer<'r> {
fn new(inner: &Inner) -> Outer {
Outer {
inner: inner
}
......
......@@ -23,17 +23,17 @@ struct Foo { bar: Bar }
impl FooBar for Bar {}
trait Test {
fn get_immut<'r>(&'r self) -> &'r FooBar;
fn get_mut<'r>(&'r mut self) -> &'r mut FooBar;
fn get_immut(&self) -> &FooBar;
fn get_mut(&mut self) -> &mut FooBar;
}
macro_rules! generate_test(($type_:path, $slf:ident, $field:expr) => (
impl Test for $type_ {
fn get_immut<'r>(&'r $slf) -> &'r FooBar {
fn get_immut(&$slf) -> &FooBar {
&$field as &FooBar
}
fn get_mut<'r>(&'r mut $slf) -> &'r mut FooBar {
fn get_mut(&mut $slf) -> &mut FooBar {
&mut $field as &mut FooBar
}
}
......
......@@ -29,7 +29,7 @@ fn is_none(&self) -> bool {
Nothing(..) => true
}
}
fn get_ref<'r>(&'r self) -> (int, &'r T) {
fn get_ref(&self) -> (int, &T) {
match *self {
Nothing(..) => fail!("E::get_ref(Nothing::<{}>)", stringify!(T)),
Thing(x, ref y) => (x, y)
......
......@@ -43,7 +43,7 @@ fn not(&self) -> Point {
}
impl ops::Index<bool,int> for Point {
fn index<'a>(&'a self, x: &bool) -> &'a int {
fn index(&self, x: &bool) -> &int {
if *x {
&self.x
} else {
......
......@@ -33,14 +33,14 @@ fn counts(&self) -> (uint, uint) {
}
impl<T> Deref<T> for DerefCounter<T> {
fn deref<'a>(&'a self) -> &'a T {
fn deref(&self) -> &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 {
fn deref_mut(&mut self) -> &mut T {
self.count_mut += 1;
&mut self.value
}
......
......@@ -22,7 +22,7 @@ fn get_x(self) -> X {
}
impl<X, Y> Deref<Y> for DerefWrapper<X, Y> {
fn deref<'a>(&'a self) -> &'a Y {
fn deref(&self) -> &Y {
&self.y
}
}
......@@ -43,7 +43,7 @@ pub fn new(x: X, y: Y) -> DerefWrapperHideX<X, Y> {
}
impl<X, Y> Deref<Y> for DerefWrapperHideX<X, Y> {
fn deref<'a>(&'a self) -> &'a Y {
fn deref(&self) -> &Y {
&self.y
}
}
......
......@@ -15,17 +15,17 @@ struct DerefWithHelper<H, T> {
}
trait Helper<T> {
fn helper_borrow<'a>(&'a self) -> &'a T;
fn helper_borrow(&self) -> &T;
}
impl<T> Helper<T> for Option<T> {
fn helper_borrow<'a>(&'a self) -> &'a T {
fn helper_borrow(&self) -> &T {
self.as_ref().unwrap()
}
}
impl<T, H: Helper<T>> Deref<T> for DerefWithHelper<H, T> {
fn deref<'a>(&'a self) -> &'a T {
fn deref(&self) -> &T {
self.helper.helper_borrow()
}
}
......
......@@ -33,14 +33,14 @@ fn counts(&self) -> (uint, uint) {
}
impl<T> Deref<T> for DerefCounter<T> {
fn deref<'a>(&'a self) -> &'a T {
fn deref(&self) -> &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 {
fn deref_mut(&mut self) -> &mut T {
self.count_mut += 1;
&mut self.value
}
......
......@@ -14,7 +14,7 @@ struct Foo {
}
impl Index<int,int> for Foo {
fn index<'a>(&'a self, z: &int) -> &'a int {
fn index(&self, z: &int) -> &int {
if *z == 0 {
&self.x
} else {
......@@ -24,7 +24,7 @@ fn index<'a>(&'a self, z: &int) -> &'a int {
}
impl IndexMut<int,int> for Foo {
fn index_mut<'a>(&'a mut self, z: &int) -> &'a mut int {
fn index_mut(&mut self, z: &int) -> &mut int {
if *z == 0 {
&mut self.x
} else {
......
......@@ -18,7 +18,7 @@ struct Character {
pos: Box<Point>,
}
fn get_x<'r>(x: &'r Character) -> &'r int {
fn get_x(x: &Character) -> &int {
// interesting case because the scope of this
// borrow of the unique pointer is in fact
// larger than the fn itself
......
......@@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn f<'a>(x : &'a int) -> &'a int {
fn f(x: &int) -> &int {
return &*x;
}
......
......@@ -12,7 +12,7 @@ struct closure_box<'a> {
cl: ||: 'a,
}
fn box_it<'r>(x: ||: 'r) -> closure_box<'r> {
fn box_it(x: ||) -> closure_box {
closure_box {cl: x}
}
......
......@@ -29,54 +29,54 @@ struct C {
f: int
}
fn get_v1<'v>(a: &'v A) -> &'v int {
fn get_v1(a: &A) -> &int {
// Region inferencer must deduce that &v < L2 < L1
let foo = &a.value; // L1
&foo.v1 // L2
}
fn get_v2<'v>(a: &'v A, i: uint) -> &'v int {
fn get_v2(a: &A, i: uint) -> &int {
let foo = &a.value;
&foo.v2[i]
}
fn get_v3<'v>(a: &'v A, i: uint) -> &'v int {
fn get_v3(a: &A, i: uint) -> &int {
let foo = &a.value;
foo.v3.get(i)
}
fn get_v4<'v>(a: &'v A, _i: uint) -> &'v int {
fn get_v4(a: &A, _i: uint) -> &int {
let foo = &a.value;
&foo.v4.f
}
fn get_v5<'v>(a: &'v A, _i: uint) -> &'v int {
fn get_v5(a: &A, _i: uint) -> &int {
let foo = &a.value;
&foo.v5.f
}
fn get_v6_a<'v>(a: &'v A, _i: uint) -> &'v int {
fn get_v6_a(a: &A, _i: uint) -> &int {
match a.value.v6 {
Some(ref v) => &v.f,
None => fail!()
}
}
fn get_v6_b<'v>(a: &'v A, _i: uint) -> &'v int {
fn get_v6_b(a: &A, _i: uint) -> &int {
match *a {
A { value: B { v6: Some(ref v), .. } } => &v.f,
_ => fail!()
}
}
fn get_v6_c<'v>(a: &'v A, _i: uint) -> &'v int {
fn get_v6_c(a: &A, _i: uint) -> &int {
match a {
&A { value: B { v6: Some(ref v), .. } } => &v.f,
_ => fail!()
}
}
fn get_v5_ref<'v>(a: &'v A, _i: uint) -> &'v int {
fn get_v5_ref(a: &A, _i: uint) -> &int {
match &a.value {
&B {v5: box C {f: ref v}, ..} => v
}
......
......@@ -11,9 +11,9 @@
// Test lifetimes are linked properly when we autoslice a vector.
// Issue #3148.
fn subslice<'r>(v: ||: 'r) -> ||: 'r { v }
fn subslice(v: ||) -> || { v }
fn both<'r>(v: ||: 'r) -> ||: 'r {
fn both(v: ||) -> || {
subslice(subslice(v))
}
......
......@@ -12,7 +12,7 @@
use std::gc::GC;
fn foo<'r>(x: &'r uint) -> &'r uint { x }
fn foo(x: &uint) -> &uint { x }
fn bar(x: &uint) -> uint { *x }
pub fn main() {
......
......@@ -9,7 +9,7 @@
// except according to those terms.
fn view<'r, T>(x: &'r [T]) -> &'r [T] {x}
fn view<T>(x: &[T]) -> &[T] {x}
pub fn main() {
let v = vec!(1i, 2, 3);
......
......@@ -10,7 +10,7 @@
use std::gc::GC;
fn borrow<'r, T>(x: &'r T) -> &'r T {x}
fn borrow<T>(x: &T) -> &T {x}
pub fn main() {
let x = box(GC) 3i;
......
......@@ -14,7 +14,7 @@
struct Point {x: int, y: int}
fn x_coord<'r>(p: &'r Point) -> &'r int {
fn x_coord(p: &Point) -> &int {
return &p.x;
}
......
......@@ -12,7 +12,7 @@ enum roption<'a> {
a, b(&'a uint)
}
fn mk<'r>(cond: bool, ptr: &'r uint) -> roption<'r> {
fn mk(cond: bool, ptr: &uint) -> roption {
if cond {a} else {b(ptr)}
}
......
......@@ -9,7 +9,7 @@
// except according to those terms.
fn region_identity<'r>(x: &'r uint) -> &'r uint { x }
fn region_identity(x: &uint) -> &uint { x }
fn apply<T>(t: T, f: |T| -> T) -> T { f(t) }
......
......@@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn get<'r, T>(opt: &'r Option<T>) -> &'r T {
fn get<T>(opt: &Option<T>) -> &T {
match *opt {
Some(ref v) => v,
None => fail!("none")
......
......@@ -12,7 +12,7 @@ struct closure_box<'a> {
cl: ||: 'a,
}
fn box_it<'r>(x: ||: 'r) -> closure_box<'r> {
fn box_it(x: ||) -> closure_box {
closure_box {cl: x}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册