提交 91b7920c 编写于 作者: T Taylor Cramer 提交者: Niko Matsakis

Implement in-band lifetime bindings

上级 1dc0b573
......@@ -2051,4 +2051,6 @@ fn main() {
E0631, // type mismatch in closure arguments
E0637, // "'_" is not a valid lifetime bound
E0657, // `impl Trait` can only capture lifetimes bound at the fn level
E0687, // in-band lifetimes cannot be used in `fn`/`Fn` syntax
E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders
}
此差异已折叠。
......@@ -222,6 +222,10 @@ pub struct LifetimeDef {
pub lifetime: Lifetime,
pub bounds: HirVec<Lifetime>,
pub pure_wrt_drop: bool,
// Indicates that the lifetime definition was synthetically added
// as a result of an in-band lifetime usage like
// `fn foo(x: &'a u8) -> &'a u8 { x }`
pub in_band: bool,
}
/// A "Path" is essentially Rust's notion of a name; for instance:
......
......@@ -157,7 +157,8 @@ fn hash_stable<W: StableHasherResult>(&self,
impl_stable_hash_for!(struct hir::LifetimeDef {
lifetime,
bounds,
pure_wrt_drop
pure_wrt_drop,
in_band
});
impl_stable_hash_for!(struct hir::Path {
......
......@@ -493,10 +493,15 @@ fn hash_stable<W: StableHasherResult>(&self,
}
}
impl_stable_hash_for!(enum ::middle::resolve_lifetime::LifetimeDefOrigin {
Explicit,
InBand
});
impl_stable_hash_for!(enum ::middle::resolve_lifetime::Region {
Static,
EarlyBound(index, decl),
LateBound(db_index, decl),
EarlyBound(index, decl, is_in_band),
LateBound(db_index, decl, is_in_band),
LateBoundAnon(db_index, anon_index),
Free(call_site_scope_data, decl)
});
......
......@@ -281,7 +281,7 @@ fn visit_ty(&mut self, arg: &'gcx hir::Ty) {
// Find the index of the named region that was part of the
// error. We will then search the function parameters for a bound
// region at the right depth with the same index
(Some(rl::Region::EarlyBound(_, id)), ty::BrNamed(def_id, _)) => {
(Some(rl::Region::EarlyBound(_, id, _)), ty::BrNamed(def_id, _)) => {
debug!("EarlyBound self.infcx.tcx.hir.local_def_id(id)={:?} \
def_id={:?}", id, def_id);
if id == def_id {
......@@ -293,7 +293,10 @@ fn visit_ty(&mut self, arg: &'gcx hir::Ty) {
// Find the index of the named region that was part of the
// error. We will then search the function parameters for a bound
// region at the right depth with the same index
(Some(rl::Region::LateBound(debruijn_index, id)), ty::BrNamed(def_id, _)) => {
(
Some(rl::Region::LateBound(debruijn_index, id, _)),
ty::BrNamed(def_id, _)
) => {
debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}",
debruijn_index.depth);
debug!("self.infcx.tcx.hir.local_def_id(id)={:?}", id);
......@@ -306,8 +309,8 @@ fn visit_ty(&mut self, arg: &'gcx hir::Ty) {
(Some(rl::Region::Static), _) |
(Some(rl::Region::Free(_, _)), _) |
(Some(rl::Region::EarlyBound(_, _)), _) |
(Some(rl::Region::LateBound(_, _)), _) |
(Some(rl::Region::EarlyBound(_, _, _)), _) |
(Some(rl::Region::LateBound(_, _, _)), _) |
(Some(rl::Region::LateBoundAnon(_, _)), _) |
(None, _) => {
debug!("no arg found");
......@@ -368,7 +371,7 @@ fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) {
}
}
(Some(rl::Region::EarlyBound(_, id)), ty::BrNamed(def_id, _)) => {
(Some(rl::Region::EarlyBound(_, id, _)), ty::BrNamed(def_id, _)) => {
debug!("EarlyBound self.infcx.tcx.hir.local_def_id(id)={:?} \
def_id={:?}", id, def_id);
if id == def_id {
......@@ -377,7 +380,7 @@ fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) {
}
}
(Some(rl::Region::LateBound(debruijn_index, id)), ty::BrNamed(def_id, _)) => {
(Some(rl::Region::LateBound(debruijn_index, id, _)), ty::BrNamed(def_id, _)) => {
debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}",
debruijn_index.depth);
debug!("id={:?}", id);
......@@ -389,8 +392,8 @@ fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) {
}
(Some(rl::Region::Static), _) |
(Some(rl::Region::EarlyBound(_, _)), _) |
(Some(rl::Region::LateBound(_, _)), _) |
(Some(rl::Region::EarlyBound(_, _, _)), _) |
(Some(rl::Region::LateBound(_, _, _)), _) |
(Some(rl::Region::LateBoundAnon(_, _)), _) |
(Some(rl::Region::Free(_, _)), _) |
(None, _) => {
......
......@@ -36,11 +36,32 @@
use hir;
use hir::intravisit::{self, Visitor, NestedVisitorMap};
/// The origin of a named lifetime definition.
///
/// This is used to prevent the usage of in-band lifetimes in `Fn`/`fn` syntax.
#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
pub enum LifetimeDefOrigin {
// Explicit binders like `fn foo<'a>(x: &'a u8)`
Explicit,
// In-band declarations like `fn foo(x: &'a u8)`
InBand,
}
impl LifetimeDefOrigin {
fn from_is_in_band(is_in_band: bool) -> Self {
if is_in_band {
LifetimeDefOrigin::InBand
} else {
LifetimeDefOrigin::Explicit
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
pub enum Region {
Static,
EarlyBound(/* index */ u32, /* lifetime decl */ DefId),
LateBound(ty::DebruijnIndex, /* lifetime decl */ DefId),
EarlyBound(/* index */ u32, /* lifetime decl */ DefId, LifetimeDefOrigin),
LateBound(ty::DebruijnIndex, /* lifetime decl */ DefId, LifetimeDefOrigin),
LateBoundAnon(ty::DebruijnIndex, /* anon index */ u32),
Free(DefId, /* lifetime decl */ DefId),
}
......@@ -52,14 +73,16 @@ fn early(hir_map: &Map, index: &mut u32, def: &hir::LifetimeDef)
let i = *index;
*index += 1;
let def_id = hir_map.local_def_id(def.lifetime.id);
let origin = LifetimeDefOrigin::from_is_in_band(def.in_band);
debug!("Region::early: index={} def_id={:?}", i, def_id);
(def.lifetime.name, Region::EarlyBound(i, def_id))
(def.lifetime.name, Region::EarlyBound(i, def_id, origin))
}
fn late(hir_map: &Map, def: &hir::LifetimeDef) -> (hir::LifetimeName, Region) {
let depth = ty::DebruijnIndex::new(1);
let def_id = hir_map.local_def_id(def.lifetime.id);
(def.lifetime.name, Region::LateBound(depth, def_id))
let origin = LifetimeDefOrigin::from_is_in_band(def.in_band);
(def.lifetime.name, Region::LateBound(depth, def_id, origin))
}
fn late_anon(index: &Cell<u32>) -> Region {
......@@ -74,16 +97,16 @@ fn id(&self) -> Option<DefId> {
Region::Static |
Region::LateBoundAnon(..) => None,
Region::EarlyBound(_, id) |
Region::LateBound(_, id) |
Region::EarlyBound(_, id, _) |
Region::LateBound(_, id, _) |
Region::Free(_, id) => Some(id)
}
}
fn shifted(self, amount: u32) -> Region {
match self {
Region::LateBound(depth, id) => {
Region::LateBound(depth.shifted(amount), id)
Region::LateBound(depth, id, origin) => {
Region::LateBound(depth.shifted(amount), id, origin)
}
Region::LateBoundAnon(depth, index) => {
Region::LateBoundAnon(depth.shifted(amount), index)
......@@ -94,10 +117,10 @@ fn shifted(self, amount: u32) -> Region {
fn from_depth(self, depth: u32) -> Region {
match self {
Region::LateBound(debruijn, id) => {
Region::LateBound(debruijn, id, origin) => {
Region::LateBound(ty::DebruijnIndex {
depth: debruijn.depth - (depth - 1)
}, id)
}, id, origin)
}
Region::LateBoundAnon(debruijn, index) => {
Region::LateBoundAnon(ty::DebruijnIndex {
......@@ -110,7 +133,7 @@ fn from_depth(self, depth: u32) -> Region {
fn subst(self, params: &[hir::Lifetime], map: &NamedRegionMap)
-> Option<Region> {
if let Region::EarlyBound(index, _) = self {
if let Region::EarlyBound(index, _, _) = self {
params.get(index as usize).and_then(|lifetime| {
map.defs.get(&lifetime.id).cloned()
})
......@@ -187,6 +210,9 @@ struct LifetimeContext<'a, 'tcx: 'a> {
// I'm sorry.
trait_ref_hack: bool,
// Used to disallow the use of in-band lifetimes in `fn` or `Fn` syntax.
is_in_fn_syntax: bool,
// List of labels in the function/method currently under analysis.
labels_in_fn: Vec<(ast::Name, Span)>,
......@@ -280,6 +306,7 @@ pub fn krate(sess: &Session,
map: &mut map,
scope: ROOT_SCOPE,
trait_ref_hack: false,
is_in_fn_syntax: false,
labels_in_fn: vec![],
xcrate_object_lifetime_defaults: DefIdMap(),
};
......@@ -384,6 +411,8 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
match ty.node {
hir::TyBareFn(ref c) => {
let next_early_index = self.next_early_index();
let was_in_fn_syntax = self.is_in_fn_syntax;
self.is_in_fn_syntax = true;
let scope = Scope::Binder {
lifetimes: c.lifetimes.iter().map(|def| {
Region::late(self.hir_map, def)
......@@ -397,6 +426,7 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
this.check_lifetime_defs(old_scope, &c.lifetimes);
intravisit::walk_ty(this, ty);
});
self.is_in_fn_syntax = was_in_fn_syntax;
}
hir::TyTraitObject(ref bounds, ref lifetime) => {
for bound in bounds {
......@@ -430,7 +460,7 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
// well-supported at the moment, so this doesn't work.
// In the future, this should be fixed and this error should be removed.
let def = self.map.defs.get(&lifetime.id);
if let Some(&Region::LateBound(_, def_id)) = def {
if let Some(&Region::LateBound(_, def_id, _)) = def {
if let Some(node_id) = self.hir_map.as_local_node_id(def_id) {
// Ensure that the parent of the def is an item, not HRTB
let parent_id = self.hir_map.get_parent_node(node_id);
......@@ -528,6 +558,7 @@ fn visit_fn_decl(&mut self, fd: &'tcx hir::FnDecl) {
}
fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
check_mixed_explicit_and_in_band_defs(&self.sess, &generics.lifetimes);
for ty_param in generics.ty_params.iter() {
walk_list!(self, visit_ty_param_bound, &ty_param.bounds);
if let Some(ref ty) = ty_param.default {
......@@ -639,6 +670,22 @@ fn desc(&self) -> &'static str {
}
}
fn check_mixed_explicit_and_in_band_defs(
sess: &Session,
lifetime_defs: &[hir::LifetimeDef],
) {
let oob_def = lifetime_defs.iter().find(|lt| !lt.in_band);
let in_band_def = lifetime_defs.iter().find(|lt| lt.in_band);
if let (Some(oob_def), Some(in_band_def)) = (oob_def, in_band_def) {
struct_span_err!(sess, in_band_def.lifetime.span, E0688,
"cannot mix in-band and explicit lifetime definitions")
.span_label(in_band_def.lifetime.span, "in-band lifetime definition here")
.span_label(oob_def.lifetime.span, "explicit lifetime definition here")
.emit();
}
}
fn signal_shadowing_problem(sess: &Session, name: ast::Name, orig: Original, shadower: Shadower) {
let mut err = if let (ShadowKind::Lifetime, ShadowKind::Lifetime) = (orig.kind, shadower.kind) {
// lifetime/lifetime shadowing is an error
......@@ -767,7 +814,7 @@ fn compute_object_lifetime_defaults(sess: &Session, hir_map: &Map)
match *set {
Set1::Empty => "BaseDefault".to_string(),
Set1::One(Region::Static) => "'static".to_string(),
Set1::One(Region::EarlyBound(i, _)) => {
Set1::One(Region::EarlyBound(i, _, _)) => {
generics.lifetimes[i as usize].lifetime.name.name().to_string()
}
Set1::One(_) => bug!(),
......@@ -837,7 +884,8 @@ fn add_bounds(set: &mut Set1<hir::LifetimeName>, bounds: &[hir::TyParamBound]) {
def.lifetime.name == name
}).map_or(Set1::Many, |(i, def)| {
let def_id = hir_map.local_def_id(def.lifetime.id);
Set1::One(Region::EarlyBound(i as u32, def_id))
let origin = LifetimeDefOrigin::from_is_in_band(def.in_band);
Set1::One(Region::EarlyBound(i as u32, def_id, origin))
})
}
}
......@@ -868,6 +916,7 @@ fn with<F>(&mut self, wrap_scope: Scope, f: F) where
map: *map,
scope: &wrap_scope,
trait_ref_hack: self.trait_ref_hack,
is_in_fn_syntax: self.is_in_fn_syntax,
labels_in_fn,
xcrate_object_lifetime_defaults,
};
......@@ -1020,6 +1069,28 @@ fn resolve_lifetime_ref(&mut self, lifetime_ref: &hir::Lifetime) {
_ => {}
}
}
// Check for fn-syntax conflicts with in-band lifetime definitions
if self.is_in_fn_syntax {
match def {
Region::EarlyBound(_, _, LifetimeDefOrigin::InBand) |
Region::LateBound(_, _, LifetimeDefOrigin::InBand) => {
struct_span_err!(self.sess, lifetime_ref.span, E0687,
"lifetimes used in `fn` or `Fn` syntax must be \
explicitly declared using `<...>` binders")
.span_label(lifetime_ref.span,
"in-band lifetime definition")
.emit();
},
Region::Static |
Region::EarlyBound(_, _, LifetimeDefOrigin::Explicit) |
Region::LateBound(_, _, LifetimeDefOrigin::Explicit) |
Region::LateBoundAnon(..) |
Region::Free(..) => {}
}
}
self.insert_lifetime(lifetime_ref, def);
} else {
struct_span_err!(self.sess, lifetime_ref.span, E0261,
......@@ -1033,8 +1104,12 @@ fn visit_segment_parameters(&mut self,
def: Def,
depth: usize,
params: &'tcx hir::PathParameters) {
if params.parenthesized {
let was_in_fn_syntax = self.is_in_fn_syntax;
self.is_in_fn_syntax = true;
self.visit_fn_like_elision(params.inputs(), Some(&params.bindings[0].ty));
self.is_in_fn_syntax = was_in_fn_syntax;
return;
}
......@@ -1355,7 +1430,7 @@ fn visit_lifetime_def(&mut self, lifetime_def: &hir::LifetimeDef) {
fn visit_lifetime(&mut self, lifetime_ref: &hir::Lifetime) {
if let Some(&lifetime) = self.map.defs.get(&lifetime_ref.id) {
match lifetime {
Region::LateBound(debruijn, _) |
Region::LateBound(debruijn, _, _) |
Region::LateBoundAnon(debruijn, _)
if debruijn.depth < self.binder_depth => {
self.have_bound_regions = true;
......
......@@ -110,7 +110,7 @@ pub fn ast_region_to_region(&self,
tcx.types.re_static
}
Some(rl::Region::LateBound(debruijn, id)) => {
Some(rl::Region::LateBound(debruijn, id, _)) => {
let name = lifetime_name(id);
tcx.mk_region(ty::ReLateBound(debruijn,
ty::BrNamed(id, name)))
......@@ -120,7 +120,7 @@ pub fn ast_region_to_region(&self,
tcx.mk_region(ty::ReLateBound(debruijn, ty::BrAnon(index)))
}
Some(rl::Region::EarlyBound(index, id)) => {
Some(rl::Region::EarlyBound(index, id, _)) => {
let name = lifetime_name(id);
tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
def_id: id,
......
......@@ -784,7 +784,7 @@ fn visit_lifetime(&mut self, lt: &'tcx hir::Lifetime) {
let hir_id = self.tcx.hir.node_to_hir_id(lt.id);
match self.tcx.named_region(hir_id) {
Some(rl::Region::Static) | Some(rl::Region::EarlyBound(..)) => {}
Some(rl::Region::LateBound(debruijn, _)) |
Some(rl::Region::LateBound(debruijn, _, _)) |
Some(rl::Region::LateBoundAnon(debruijn, _))
if debruijn.depth < self.binder_depth => {}
_ => self.has_late_bound_regions = Some(lt.span),
......
......@@ -1008,8 +1008,8 @@ fn clean(&self, cx: &DocContext) -> Lifetime {
let hir_id = cx.tcx.hir.node_to_hir_id(self.id);
let def = cx.tcx.named_region(hir_id);
match def {
Some(rl::Region::EarlyBound(_, node_id)) |
Some(rl::Region::LateBound(_, node_id)) |
Some(rl::Region::EarlyBound(_, node_id, _)) |
Some(rl::Region::LateBound(_, node_id, _)) |
Some(rl::Region::Free(_, node_id)) => {
if let Some(lt) = cx.lt_substs.borrow().get(&node_id).cloned() {
return lt;
......
......@@ -425,6 +425,9 @@ pub fn new() -> Features {
// `crate` in paths
(active, crate_in_paths, "1.23.0", Some(45477)),
// In-band lifetime bindings (e.g. `fn foo(x: &'a u8) -> &'a u8`)
(active, in_band_lifetimes, "1.23.0", Some(44524)),
);
declare_features! (
......
// Copyright 2017 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(warnings)]
fn foo(x: &'x u8) -> &'x u8 { x }
//~^ ERROR use of undeclared lifetime name
//~^^ ERROR use of undeclared lifetime name
struct X<'a>(&'a u8);
impl<'a> X<'a> {
fn inner(&self) -> &'a u8 {
self.0
}
}
impl<'a> X<'b> {
//~^ ERROR use of undeclared lifetime name
fn inner_2(&self) -> &'b u8 {
//~^ ERROR use of undeclared lifetime name
self.0
}
}
impl X<'b> {
//~^ ERROR use of undeclared lifetime name
fn inner_3(&self) -> &'b u8 {
//~^ ERROR use of undeclared lifetime name
self.0
}
}
struct Y<T>(T);
impl Y<&'a u8> {
//~^ ERROR use of undeclared lifetime name
fn inner(&self) -> &'a u8 {
//~^ ERROR use of undeclared lifetime name
self.0
}
}
trait MyTrait<'a> {
fn my_lifetime(&self) -> &'a u8;
fn any_lifetime() -> &'b u8;
//~^ ERROR use of undeclared lifetime name
fn borrowed_lifetime(&'b self) -> &'b u8;
//~^ ERROR use of undeclared lifetime name
//~^^ ERROR use of undeclared lifetime name
}
impl MyTrait<'a> for Y<&'a u8> {
//~^ ERROR use of undeclared lifetime name
//~^^ ERROR use of undeclared lifetime name
fn my_lifetime(&self) -> &'a u8 { self.0 }
//~^ ERROR use of undeclared lifetime name
fn any_lifetime() -> &'b u8 { &0 }
//~^ ERROR use of undeclared lifetime name
fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 }
//~^ ERROR use of undeclared lifetime name
//~^^ ERROR use of undeclared lifetime name
}
fn main() {}
// Copyright 2017 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(warnings)]
#![feature(in_band_lifetimes, universal_impl_trait)]
fn foo(x: &'x u8) -> &'x u8 { x }
fn foo2(x: &'a u8, y: &u8) -> &'a u8 { x }
fn check_in_band_can_be_late_bound() {
let _: for<'x> fn(&'x u8, &u8) -> &'x u8 = foo2;
}
struct ForInherentNoParams;
impl ForInherentNoParams {
fn foo(x: &'a u32, y: &u32) -> &'a u32 { x }
}
struct X<'a>(&'a u8);
impl<'a> X<'a> {
fn inner(&self) -> &'a u8 {
self.0
}
fn same_lifetime_as_parameter(&mut self, x: &'a u8) {
self.0 = x;
}
}
impl X<'b> {
fn inner_2(&self) -> &'b u8 {
self.0
}
fn reference_already_introduced_in_band_from_method_with_explicit_binders<'a>(
&'b self, x: &'a u32
) {}
}
struct Y<T>(T);
impl Y<&'a u8> {
fn inner(&self) -> &'a u8 {
self.0
}
}
trait MyTrait<'a> {
fn my_lifetime(&self) -> &'a u8;
fn any_lifetime() -> &'b u8;
fn borrowed_lifetime(&'b self) -> &'b u8;
fn default_impl(&self, x: &'b u32, y: &u32) -> &'b u32 { x }
fn in_band_def_explicit_impl(&self, x: &'b u8);
}
impl MyTrait<'a> for Y<&'a u8> {
fn my_lifetime(&self) -> &'a u8 { self.0 }
fn any_lifetime() -> &'b u8 { &0 }
fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 }
fn in_band_def_explicit_impl<'b>(&self, x: &'b u8) {}
}
fn test_hrtb_defined_lifetime_where<F>(_: F) where for<'a> F: Fn(&'a u8) {}
fn test_hrtb_defined_lifetime_polytraitref<F>(_: F) where F: for<'a> Fn(&'a u8) {}
fn reference_in_band_from_locals(x: &'test u32) -> &'test u32 {
let y: &'test u32 = x;
y
}
fn in_generics_in_band<T: MyTrait<'a>>(x: &T) {}
fn where_clause_in_band<T>(x: &T) where T: MyTrait<'a> {}
fn impl_trait_in_band(x: &impl MyTrait<'a>) {}
fn main() {}
// Copyright 2017 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(warnings)]
#![feature(in_band_lifetimes)]
fn foo(x: fn(&'a u32)) {}
fn bar(x: &Fn(&'a u32)) {}
fn baz(x: fn(&'a u32), y: &'a u32) {}
struct Foo<'a> { x: &'a u32 }
impl Foo<'a> {
fn bar(&self, x: fn(&'a u32)) {}
}
fn main() {}
error[E0687]: lifetimes used in `fn` or `Fn` syntax must be explicitly declared using `<...>` binders
--> $DIR/E0687.rs:14:15
|
14 | fn foo(x: fn(&'a u32)) {}
| ^^ in-band lifetime definition
error[E0687]: lifetimes used in `fn` or `Fn` syntax must be explicitly declared using `<...>` binders
--> $DIR/E0687.rs:16:16
|
16 | fn bar(x: &Fn(&'a u32)) {}
| ^^ in-band lifetime definition
error[E0687]: lifetimes used in `fn` or `Fn` syntax must be explicitly declared using `<...>` binders
--> $DIR/E0687.rs:18:15
|
18 | fn baz(x: fn(&'a u32), y: &'a u32) {}
| ^^ in-band lifetime definition
error[E0687]: lifetimes used in `fn` or `Fn` syntax must be explicitly declared using `<...>` binders
--> $DIR/E0687.rs:23:26
|
23 | fn bar(&self, x: fn(&'a u32)) {}
| ^^ in-band lifetime definition
error: aborting due to 4 previous errors
// Copyright 2017 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(warnings)]
#![feature(in_band_lifetimes, universal_impl_trait)]
fn bar<F>(x: &F) where F: Fn(&'a u32) {}
fn baz(x: &impl Fn(&'a u32)) {}
fn main() {}
error[E0687]: lifetimes used in `fn` or `Fn` syntax must be explicitly declared using `<...>` binders
--> $DIR/E0687_where.rs:14:31
|
14 | fn bar<F>(x: &F) where F: Fn(&'a u32) {}
| ^^ in-band lifetime definition
error[E0687]: lifetimes used in `fn` or `Fn` syntax must be explicitly declared using `<...>` binders
--> $DIR/E0687_where.rs:16:21
|
16 | fn baz(x: &impl Fn(&'a u32)) {}
| ^^ in-band lifetime definition
error: aborting due to 2 previous errors
// Copyright 2017 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(warnings)]
#![feature(in_band_lifetimes)]
fn foo<'a>(x: &'a u32, y: &'b u32) {}
struct Foo<'a> { x: &'a u32 }
impl Foo<'a> {
fn bar<'b>(x: &'a u32, y: &'b u32, z: &'c u32) {}
}
impl<'b> Foo<'a> {
fn baz() {}
}
fn main() {}
error[E0688]: cannot mix in-band and explicit lifetime definitions
--> $DIR/E0688.rs:14:28
|
14 | fn foo<'a>(x: &'a u32, y: &'b u32) {}
| -- ^^ in-band lifetime definition here
| |
| explicit lifetime definition here
error[E0688]: cannot mix in-band and explicit lifetime definitions
--> $DIR/E0688.rs:19:44
|
19 | fn bar<'b>(x: &'a u32, y: &'b u32, z: &'c u32) {}
| -- ^^ in-band lifetime definition here
| |
| explicit lifetime definition here
error[E0688]: cannot mix in-band and explicit lifetime definitions
--> $DIR/E0688.rs:22:14
|
22 | impl<'b> Foo<'a> {
| -- ^^ in-band lifetime definition here
| |
| explicit lifetime definition here
error: aborting due to 3 previous errors
// Copyright 2017 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(warnings)]
#![feature(in_band_lifetimes)]
fn foo(x: &'a u32, y: &u32) -> &'a u32 { y }
fn foo2(x: &'a u32, y: &'b u32) -> &'a u32 { y }
fn main() {}
error[E0621]: explicit lifetime required in the type of `y`
--> $DIR/mismatched.rs:14:42
|
14 | fn foo(x: &'a u32, y: &u32) -> &'a u32 { y }
| - ^ lifetime `'a` required
| |
| consider changing the type of `y` to `&'a u32`
error[E0623]: lifetime mismatch
--> $DIR/mismatched.rs:16:46
|
16 | fn foo2(x: &'a u32, y: &'b u32) -> &'a u32 { y }
| ------- ------- ^ ...but data from `y` is returned here
| |
| this parameter and the return type are declared with different lifetimes...
error: aborting due to 2 previous errors
// Copyright 2017 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(warnings)]
#![feature(in_band_lifetimes)]
trait Get {
fn baz(&self, x: &'a u32, y: &u32) -> &'a u32 {
y
}
}
fn main() {}
error[E0621]: explicit lifetime required in the type of `y`
--> $DIR/mismatched_trait.rs:16:9
|
15 | fn baz(&self, x: &'a u32, y: &u32) -> &'a u32 {
| - consider changing the type of `y` to `&'a u32`
16 | y
| ^ lifetime `'a` required
error: aborting due to previous error
// Copyright 2017 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(warnings)]
#![feature(in_band_lifetimes)]
trait Get {
fn foo(&self, x: &'a u32, y: &u32) -> &'a u32;
}
impl Get for i32 {
fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
x
}
}
fn main() {}
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'a in generic type due to conflicting requirements
--> $DIR/mismatched_trait_impl.rs:19:5
|
19 | / fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
20 | | x
21 | | }
| |_____^
|
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 19:5...
--> $DIR/mismatched_trait_impl.rs:19:5
|
19 | / fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
20 | | x
21 | | }
| |_____^
note: ...so that method type is compatible with trait (expected fn(&i32, &'a u32, &u32) -> &'a u32, found fn(&i32, &u32, &u32) -> &u32)
--> $DIR/mismatched_trait_impl.rs:19:5
|
19 | / fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
20 | | x
21 | | }
| |_____^
note: but, the lifetime must be valid for the lifetime 'a as defined on the method body at 19:5...
--> $DIR/mismatched_trait_impl.rs:19:5
|
19 | / fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
20 | | x
21 | | }
| |_____^
note: ...so that method type is compatible with trait (expected fn(&i32, &'a u32, &u32) -> &'a u32, found fn(&i32, &u32, &u32) -> &u32)
--> $DIR/mismatched_trait_impl.rs:19:5
|
19 | / fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
20 | | x
21 | | }
| |_____^
error: aborting due to previous error
// Copyright 2017 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(warnings)]
#![feature(in_band_lifetimes)]
fn foo(x: &'a u32) -> &'a u32 { x }
fn main() {
let mut p = 3;
let r = foo(&p);
p += 1;
println!("{}", r);
}
error[E0506]: cannot assign to `p` because it is borrowed
--> $DIR/mut_while_borrow.rs:19:5
|
18 | let r = foo(&p);
| - borrow of `p` occurs here
19 | p += 1;
| ^^^^^^ assignment to borrowed `p` occurs here
error: aborting due to previous error
// Copyright 2017 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(warnings)]
#![feature(in_band_lifetimes)]
struct Foo {
x: &'test u32,
}
enum Bar {
Baz(&'test u32),
}
fn main() {}
error[E0261]: use of undeclared lifetime name `'test`
--> $DIR/no_in_band_in_struct.rs:15:9
|
15 | x: &'test u32,
| ^^^^^ undeclared lifetime
error[E0261]: use of undeclared lifetime name `'test`
--> $DIR/no_in_band_in_struct.rs:19:10
|
19 | Baz(&'test u32),
| ^^^^^ undeclared lifetime
error: aborting due to 2 previous errors
// Copyright 2017 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(warnings)]
#![feature(in_band_lifetimes)]
fn foo(x: &u32) {
let y: &'test u32 = x;
}
fn foo2(x: &u32) {}
fn bar() {
let y: fn(&'test u32) = foo2;
}
fn main() {}
error[E0261]: use of undeclared lifetime name `'test`
--> $DIR/no_introducing_in_band_in_locals.rs:15:13
|
15 | let y: &'test u32 = x;
| ^^^^^ undeclared lifetime
error[E0261]: use of undeclared lifetime name `'test`
--> $DIR/no_introducing_in_band_in_locals.rs:20:16
|
20 | let y: fn(&'test u32) = foo2;
| ^^^^^ undeclared lifetime
error: aborting due to 2 previous errors
// Copyright 2017 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(warnings)]
#![feature(in_band_lifetimes)]
struct Foo<T>(T);
impl Foo<&'s u8> {
fn bar<'s>(&self, x: &'s u8) {}
fn baz(x: for<'s> fn(&'s u32)) {}
}
fn main() {}
error[E0496]: lifetime name `'s` shadows a lifetime name that is already in scope
--> $DIR/shadow.rs:17:12
|
16 | impl Foo<&'s u8> {
| -- first declared here
17 | fn bar<'s>(&self, x: &'s u8) {}
| ^^ lifetime 's already in scope
error[E0496]: lifetime name `'s` shadows a lifetime name that is already in scope
--> $DIR/shadow.rs:18:19
|
16 | impl Foo<&'s u8> {
| -- first declared here
17 | fn bar<'s>(&self, x: &'s u8) {}
18 | fn baz(x: for<'s> fn(&'s u32)) {}
| ^^ lifetime 's already in scope
error: aborting due to 2 previous errors
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册