提交 ba1849da 编写于 作者: E Eduard-Mihai Burtescu

rustc: move most of lifetime elision to resolve_lifetimes.

上级 bbc34142
......@@ -327,6 +327,69 @@ struct ListNode {
This works because `Box` is a pointer, so its size is well-known.
"##,
E0106: r##"
This error indicates that a lifetime is missing from a type. If it is an error
inside a function signature, the problem may be with failing to adhere to the
lifetime elision rules (see below).
Here are some simple examples of where you'll run into this error:
```compile_fail,E0106
struct Foo { x: &bool } // error
struct Foo<'a> { x: &'a bool } // correct
enum Bar { A(u8), B(&bool), } // error
enum Bar<'a> { A(u8), B(&'a bool), } // correct
type MyStr = &str; // error
type MyStr<'a> = &'a str; // correct
```
Lifetime elision is a special, limited kind of inference for lifetimes in
function signatures which allows you to leave out lifetimes in certain cases.
For more background on lifetime elision see [the book][book-le].
The lifetime elision rules require that any function signature with an elided
output lifetime must either have
- exactly one input lifetime
- or, multiple input lifetimes, but the function must also be a method with a
`&self` or `&mut self` receiver
In the first case, the output lifetime is inferred to be the same as the unique
input lifetime. In the second case, the lifetime is instead inferred to be the
same as the lifetime on `&self` or `&mut self`.
Here are some examples of elision errors:
```compile_fail,E0106
// error, no input lifetimes
fn foo() -> &str { }
// error, `x` and `y` have distinct lifetimes inferred
fn bar(x: &str, y: &str) -> &str { }
// error, `y`'s lifetime is inferred to be distinct from `x`'s
fn baz<'a>(x: &'a str, y: &str) -> &str { }
```
Here's an example that is currently an error, but may work in a future version
of Rust:
```compile_fail,E0106
struct Foo<'a>(&'a str);
trait Quux { }
impl Quux for Foo { }
```
Lifetime elision in implementation headers was part of the lifetime elision
RFC. It is, however, [currently unimplemented][iss15872].
[book-le]: https://doc.rust-lang.org/nightly/book/lifetimes.html#lifetime-elision
[iss15872]: https://github.com/rust-lang/rust/issues/15872
"##,
E0109: r##"
You tried to give a type parameter to a type which doesn't need it. Erroneous
code example:
......
......@@ -314,9 +314,10 @@ fn lower_ty(&mut self, t: &Ty) -> P<hir::Ty> {
TyKind::Slice(ref ty) => hir::TySlice(self.lower_ty(ty)),
TyKind::Ptr(ref mt) => hir::TyPtr(self.lower_mt(mt)),
TyKind::Rptr(ref region, ref mt) => {
let span = Span { hi: t.span.lo, ..t.span };
let lifetime = match *region {
Some(ref lt) => self.lower_lifetime(lt),
None => self.elided_lifetime(t.span)
None => self.elided_lifetime(span)
};
hir::TyRptr(lifetime, self.lower_mt(mt))
}
......
此差异已折叠。
......@@ -97,7 +97,7 @@
use rustc::ty::fold::{BottomUpFolder, TypeFoldable};
use rustc::ty::util::{Representability, IntTypeExt};
use require_c_abi_if_variadic;
use rscope::{ElisionFailureInfo, RegionScope};
use rscope::RegionScope;
use session::{Session, CompileResult};
use CrateCtxt;
use TypeAndSubsts;
......@@ -1410,6 +1410,15 @@ fn get_type_parameter_bounds(&self,
Ok(r)
}
fn re_infer(&self, span: Span, def: Option<&ty::RegionParameterDef>)
-> &'tcx ty::Region {
let v = match def {
Some(def) => infer::EarlyBoundRegion(span, def.name),
None => infer::MiscVariable(span)
};
self.next_region_var(v)
}
fn ty_infer(&self, span: Span) -> Ty<'tcx> {
self.next_ty_var(TypeVariableOrigin::TypeInference(span))
}
......@@ -1465,15 +1474,6 @@ fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
// be some expression).
*self.next_region_var(infer::MiscVariable(span))
}
fn anon_region(&self, span: Span, def: Option<&ty::RegionParameterDef>)
-> Result<ty::Region, Option<Vec<ElisionFailureInfo>>> {
let v = match def {
Some(def) => infer::EarlyBoundRegion(span, def.name),
None => infer::MiscVariable(span)
};
Ok(*self.next_region_var(v))
}
}
/// Controls whether the arguments are tupled. This is used for the call
......@@ -4408,7 +4408,11 @@ pub fn instantiate_value_path(&self,
None => &[]
};
AstConv::opt_ast_region_to_region(self, self, span, lifetimes.get(i), Some(def))
if let Some(lifetime) = lifetimes.get(i) {
AstConv::ast_region_to_region(self, lifetime, Some(def))
} else {
self.re_infer(span, Some(def))
}
}, |def, substs| {
let mut i = def.index as usize;
......
......@@ -437,6 +437,11 @@ fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
None
}
fn re_infer(&self, span: Span, _def: Option<&ty::RegionParameterDef>)
-> &'tcx ty::Region {
span_bug!(span, "unelided lifetime in signature");
}
fn ty_infer(&self, span: Span) -> Ty<'tcx> {
struct_span_err!(
self.tcx().sess,
......@@ -639,8 +644,6 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
container: AssociatedItemContainer,
id: ast::NodeId,
sig: &hir::MethodSig,
untransformed_rcvr_ty: Ty<'tcx>,
body: Option<hir::BodyId>,
rcvr_ty_predicates: &ty::GenericPredicates<'tcx>,) {
let def_id = ccx.tcx.hir.local_def_id(id);
let ty_generics = generics_of_def_id(ccx, def_id);
......@@ -652,14 +655,8 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
ImplContainer(_) => Some(AnonTypeScope::new(def_id)),
TraitContainer(_) => None
};
let assoc_item = ccx.tcx.associated_item(def_id);
let self_value_ty = if assoc_item.method_has_self_argument {
Some(untransformed_rcvr_ty)
} else {
None
};
let fty = AstConv::ty_of_method(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
sig, self_value_ty, body, anon_scope);
let fty = AstConv::ty_of_fn(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
sig.unsafety, sig.abi, &sig.decl, anon_scope);
let substs = mk_item_substs(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
ccx.tcx.hir.span(id), def_id);
......@@ -876,14 +873,9 @@ fn convert_trait_item(ccx: &CrateCtxt, trait_item: &hir::TraitItem) {
convert_associated_type(ccx, TraitContainer(trait_def_id), trait_item.id, typ);
}
hir::TraitItemKind::Method(ref sig, ref method) => {
let body = match *method {
hir::TraitMethod::Required(_) => None,
hir::TraitMethod::Provided(body) => Some(body)
};
hir::TraitItemKind::Method(ref sig, _) => {
convert_method(ccx, TraitContainer(trait_def_id),
trait_item.id, sig, tcx.mk_self_type(),
body, &trait_predicates);
trait_item.id, sig, &trait_predicates);
}
}
}
......@@ -896,7 +888,6 @@ fn convert_impl_item(ccx: &CrateCtxt, impl_item: &hir::ImplItem) {
let impl_def_id = tcx.hir.get_parent_did(impl_item.id);
let impl_predicates = tcx.item_predicates(impl_def_id);
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id);
let impl_self_ty = tcx.item_type(impl_def_id);
match impl_item.node {
hir::ImplItemKind::Const(ref ty, _) => {
......@@ -923,10 +914,8 @@ fn convert_impl_item(ccx: &CrateCtxt, impl_item: &hir::ImplItem) {
convert_associated_type(ccx, ImplContainer(impl_def_id), impl_item.id, Some(typ));
}
hir::ImplItemKind::Method(ref sig, body) => {
convert_method(ccx, ImplContainer(impl_def_id),
impl_item.id, sig, impl_self_ty,
Some(body), &impl_predicates);
hir::ImplItemKind::Method(ref sig, _) => {
convert_method(ccx, ImplContainer(impl_def_id), impl_item.id, sig, &impl_predicates);
}
}
}
......@@ -1472,7 +1461,7 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
index: own_start + i as u32,
def_id: tcx.hir.local_def_id(l.lifetime.id),
bounds: l.bounds.iter().map(|l| {
AstConv::ast_region_to_region(&ccx.icx(&()), l)
AstConv::ast_region_to_region(&ccx.icx(&()), l, None)
}).collect(),
pure_wrt_drop: l.pure_wrt_drop,
}
......@@ -1545,11 +1534,11 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
NodeItem(item) => {
match item.node {
ItemStatic(ref t, ..) | ItemConst(ref t, _) => {
ccx.icx(&()).to_ty(&StaticRscope::new(&ccx.tcx), &t)
ccx.icx(&()).to_ty(&ExplicitRscope, &t)
}
ItemFn(ref decl, unsafety, _, abi, ref generics, body) => {
let tofd = AstConv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &decl,
body, Some(AnonTypeScope::new(def_id)));
ItemFn(ref decl, unsafety, _, abi, ref generics, _) => {
let tofd = AstConv::ty_of_fn(&ccx.icx(generics), unsafety, abi, &decl,
Some(AnonTypeScope::new(def_id)));
let substs = mk_item_substs(&ccx.icx(generics), item.span, def_id);
ccx.tcx.mk_fn_def(def_id, substs, tofd)
}
......@@ -1765,7 +1754,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
name: param.lifetime.name
}));
for bound in &param.bounds {
let bound_region = AstConv::ast_region_to_region(&ccx.icx(&()), bound);
let bound_region = AstConv::ast_region_to_region(&ccx.icx(&()), bound, None);
let outlives = ty::Binder(ty::OutlivesPredicate(region, bound_region));
predicates.push(outlives.to_predicate());
}
......@@ -1816,7 +1805,9 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
}
&hir::TyParamBound::RegionTyParamBound(ref lifetime) => {
let region = AstConv::ast_region_to_region(&ccx.icx(&()), lifetime);
let region = AstConv::ast_region_to_region(&ccx.icx(&()),
lifetime,
None);
let pred = ty::Binder(ty::OutlivesPredicate(ty, region));
predicates.push(ty::Predicate::TypeOutlives(pred))
}
......@@ -1825,9 +1816,9 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
}
&hir::WherePredicate::RegionPredicate(ref region_pred) => {
let r1 = AstConv::ast_region_to_region(&ccx.icx(&()), &region_pred.lifetime);
let r1 = AstConv::ast_region_to_region(&ccx.icx(&()), &region_pred.lifetime, None);
for bound in &region_pred.bounds {
let r2 = AstConv::ast_region_to_region(&ccx.icx(&()), bound);
let r2 = AstConv::ast_region_to_region(&ccx.icx(&()), bound, None);
let pred = ty::Binder(ty::OutlivesPredicate(r1, r2));
predicates.push(ty::Predicate::RegionOutlives(pred))
}
......@@ -1935,7 +1926,7 @@ fn from_bounds<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
hir::TraitTyParamBound(..) =>
None,
hir::RegionTyParamBound(ref lifetime) =>
Some(AstConv::ast_region_to_region(&ccx.icx(&()), lifetime)),
Some(AstConv::ast_region_to_region(&ccx.icx(&()), lifetime, None)),
}
})
.collect()
......@@ -1997,7 +1988,7 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
}).collect();
let region_bounds = region_bounds.into_iter().map(|r| {
astconv.ast_region_to_region(r)
astconv.ast_region_to_region(r, None)
}).collect();
trait_bounds.sort_by(|a,b| a.def_id().cmp(&b.def_id()));
......@@ -2039,7 +2030,7 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
.collect()
}
hir::RegionTyParamBound(ref lifetime) => {
let region = astconv.ast_region_to_region(lifetime);
let region = astconv.ast_region_to_region(lifetime, None);
let pred = ty::Binder(ty::OutlivesPredicate(param_ty, region));
vec![ty::Predicate::TypeOutlives(pred)]
}
......@@ -2057,18 +2048,7 @@ fn compute_type_of_foreign_fn_decl<'a, 'tcx>(
abi: abi::Abi)
-> Ty<'tcx>
{
let rb = BindingRscope::new();
let input_tys = decl.inputs
.iter()
.map(|a| AstConv::ty_of_arg(&ccx.icx(ast_generics), &rb, a, None))
.collect::<Vec<_>>();
let output = match decl.output {
hir::Return(ref ty) =>
AstConv::ast_ty_to_ty(&ccx.icx(ast_generics), &rb, &ty),
hir::DefaultReturn(..) =>
ccx.tcx.mk_nil(),
};
let fty = AstConv::ty_of_fn(&ccx.icx(ast_generics), hir::Unsafety::Unsafe, abi, decl, None);
// feature gate SIMD types in FFI, since I (huonw) am not sure the
// ABIs are handled at all correctly.
......@@ -2084,21 +2064,17 @@ fn compute_type_of_foreign_fn_decl<'a, 'tcx>(
.emit();
}
};
for (input, ty) in decl.inputs.iter().zip(&input_tys) {
for (input, ty) in decl.inputs.iter().zip(*fty.sig.inputs().skip_binder()) {
check(&input, ty)
}
if let hir::Return(ref ty) = decl.output {
check(&ty, output)
check(&ty, *fty.sig.output().skip_binder())
}
}
let id = ccx.tcx.hir.as_local_node_id(def_id).unwrap();
let substs = mk_item_substs(&ccx.icx(ast_generics), ccx.tcx.hir.span(id), def_id);
ccx.tcx.mk_fn_def(def_id, substs, ccx.tcx.mk_bare_fn(ty::BareFnTy {
abi: abi,
unsafety: hir::Unsafety::Unsafe,
sig: ty::Binder(ccx.tcx.mk_fn_sig(input_tys.into_iter(), output, decl.variadic)),
}))
ccx.tcx.mk_fn_def(def_id, substs, fty)
}
pub fn mk_item_substs<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
......
......@@ -1412,85 +1412,19 @@ fn main() {
```
"##,
E0106: r##"
This error indicates that a lifetime is missing from a type. If it is an error
inside a function signature, the problem may be with failing to adhere to the
lifetime elision rules (see below).
Here are some simple examples of where you'll run into this error:
```compile_fail,E0106
struct Foo { x: &bool } // error
struct Foo<'a> { x: &'a bool } // correct
enum Bar { A(u8), B(&bool), } // error
enum Bar<'a> { A(u8), B(&'a bool), } // correct
type MyStr = &str; // error
type MyStr<'a> = &'a str; // correct
```
Lifetime elision is a special, limited kind of inference for lifetimes in
function signatures which allows you to leave out lifetimes in certain cases.
For more background on lifetime elision see [the book][book-le].
The lifetime elision rules require that any function signature with an elided
output lifetime must either have
- exactly one input lifetime
- or, multiple input lifetimes, but the function must also be a method with a
`&self` or `&mut self` receiver
In the first case, the output lifetime is inferred to be the same as the unique
input lifetime. In the second case, the lifetime is instead inferred to be the
same as the lifetime on `&self` or `&mut self`.
Here are some examples of elision errors:
```compile_fail,E0106
// error, no input lifetimes
fn foo() -> &str { }
// error, `x` and `y` have distinct lifetimes inferred
fn bar(x: &str, y: &str) -> &str { }
// error, `y`'s lifetime is inferred to be distinct from `x`'s
fn baz<'a>(x: &'a str, y: &str) -> &str { }
```
[book-le]: https://doc.rust-lang.org/nightly/book/lifetimes.html#lifetime-elision
"##,
E0107: r##"
This error means that an incorrect number of lifetime parameters were provided
for a type (like a struct or enum) or trait.
Some basic examples include:
for a type (like a struct or enum) or trait:
```compile_fail,E0107
struct Foo<'a>(&'a str);
struct Foo<'a, 'b>(&'a str, &'b str);
enum Bar { A, B, C }
struct Baz<'a> {
foo: Foo, // error: expected 1, found 0
foo: Foo<'a>, // error: expected 2, found 1
bar: Bar<'a>, // error: expected 0, found 1
}
```
Here's an example that is currently an error, but may work in a future version
of Rust:
```compile_fail,E0107
struct Foo<'a>(&'a str);
trait Quux { }
impl Quux for Foo { } // error: expected 1, found 0
```
Lifetime elision in implementation headers was part of the lifetime elision
RFC. It is, however, [currently unimplemented][iss15872].
[iss15872]: https://github.com/rust-lang/rust/issues/15872
"##,
E0116: r##"
......
......@@ -8,28 +8,14 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use rustc::hir;
use rustc::hir::def_id::DefId;
use rustc::ty;
use rustc::ty::subst::Substs;
use astconv::AstConv;
use std::cell::Cell;
use syntax_pos::Span;
#[derive(Clone)]
pub struct ElisionFailureInfo {
/// Where we can find the argument pattern.
pub parent: Option<hir::BodyId>,
/// The index of the argument in the original definition.
pub index: usize,
pub lifetime_count: usize,
pub have_bound_regions: bool
}
pub type ElidedLifetime = Result<ty::Region, Option<Vec<ElisionFailureInfo>>>;
/// Defines strategies for handling regions that are omitted. For
/// example, if one writes the type `&Foo`, then the lifetime of
/// this reference has been omitted. When converting this
......@@ -41,9 +27,6 @@ pub struct ElisionFailureInfo {
/// can return `Err(())` to indicate that this is not a scope in which
/// regions can legally be omitted.
pub trait RegionScope {
fn anon_region(&self, span: Span, def: Option<&ty::RegionParameterDef>)
-> Result<ty::Region, Option<Vec<ElisionFailureInfo>>>;
/// If an object omits any explicit lifetime bound, and none can
/// be derived from the object traits, what should we use? If
/// `None` is returned, an explicit annotation is required.
......@@ -115,11 +98,6 @@ fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
self.base_scope.object_lifetime_default(span)
}
fn anon_region(&self, span: Span, def: Option<&ty::RegionParameterDef>)
-> Result<ty::Region, Option<Vec<ElisionFailureInfo>>> {
self.base_scope.anon_region(span, def)
}
fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
self.base_scope.base_object_lifetime_default(span)
}
......@@ -135,105 +113,6 @@ fn anon_type_scope(&self) -> Option<AnonTypeScope> {
pub struct ExplicitRscope;
impl RegionScope for ExplicitRscope {
fn anon_region(&self, _span: Span, _: Option<&ty::RegionParameterDef>)
-> Result<ty::Region, Option<Vec<ElisionFailureInfo>>> {
Err(None)
}
fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
Some(self.base_object_lifetime_default(span))
}
fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
ty::ReStatic
}
}
// Same as `ExplicitRscope`, but provides some extra information for diagnostics
pub struct UnelidableRscope(Option<Vec<ElisionFailureInfo>>);
impl UnelidableRscope {
pub fn new(v: Option<Vec<ElisionFailureInfo>>) -> UnelidableRscope {
UnelidableRscope(v)
}
}
impl RegionScope for UnelidableRscope {
fn anon_region(&self, _span: Span, _: Option<&ty::RegionParameterDef>)
-> Result<ty::Region, Option<Vec<ElisionFailureInfo>>> {
Err(self.0.clone())
}
fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
Some(self.base_object_lifetime_default(span))
}
fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
ty::ReStatic
}
}
// A scope in which omitted anonymous region defaults to
// `default`. This is used after the `->` in function signatures. The
// latter use may go away. Note that object-lifetime defaults work a
// bit differently, as specified in RFC #599.
pub struct ElidableRscope {
default: ty::Region,
}
impl ElidableRscope {
pub fn new(r: ty::Region) -> ElidableRscope {
ElidableRscope { default: r }
}
}
impl RegionScope for ElidableRscope {
fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
// Per RFC #599, object-lifetimes default to 'static unless
// overridden by context, and this takes precedence over
// lifetime elision.
Some(self.base_object_lifetime_default(span))
}
fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
ty::ReStatic
}
fn anon_region(&self, _span: Span, _: Option<&ty::RegionParameterDef>)
-> Result<ty::Region, Option<Vec<ElisionFailureInfo>>>
{
Ok(self.default)
}
}
/// A scope that behaves as an ElidabeRscope with a `'static` default region
/// that should also warn if the `static_in_const` feature is unset.
#[derive(Copy, Clone)]
pub struct StaticRscope<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
tcx: &'a ty::TyCtxt<'a, 'gcx, 'tcx>,
}
impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> StaticRscope<'a, 'gcx, 'tcx> {
/// create a new StaticRscope from a reference to the `TyCtxt`
pub fn new(tcx: &'a ty::TyCtxt<'a, 'gcx, 'tcx>) -> Self {
StaticRscope { tcx: tcx }
}
}
impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> RegionScope for StaticRscope<'a, 'gcx, 'tcx> {
fn anon_region(&self, span: Span, _: Option<&ty::RegionParameterDef>)
-> Result<ty::Region, Option<Vec<ElisionFailureInfo>>> {
if !self.tcx.sess.features.borrow().static_in_const {
self.tcx
.sess
.struct_span_err(span,
"this needs a `'static` lifetime or the \
`static_in_const` feature, see #35897")
.emit();
}
Ok(ty::ReStatic)
}
fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
Some(self.base_object_lifetime_default(span))
}
......@@ -243,41 +122,6 @@ fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
}
}
/// A scope in which we generate anonymous, late-bound regions for
/// omitted regions. This occurs in function signatures.
pub struct BindingRscope {
anon_bindings: Cell<u32>,
}
impl BindingRscope {
pub fn new() -> BindingRscope {
BindingRscope {
anon_bindings: Cell::new(0),
}
}
}
impl RegionScope for BindingRscope {
fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
// Per RFC #599, object-lifetimes default to 'static unless
// overridden by context, and this takes precedence over the
// binding defaults in a fn signature.
Some(self.base_object_lifetime_default(span))
}
fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
ty::ReStatic
}
fn anon_region(&self, _: Span, _: Option<&ty::RegionParameterDef>)
-> Result<ty::Region, Option<Vec<ElisionFailureInfo>>>
{
let idx = self.anon_bindings.get();
self.anon_bindings.set(idx + 1);
Ok(ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrAnon(idx)))
}
}
/// A scope which overrides the default object lifetime but has no other effect.
pub struct ObjectLifetimeDefaultRscope<'r> {
base_scope: &'r (RegionScope+'r),
......@@ -315,12 +159,6 @@ fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
self.base_scope.base_object_lifetime_default(span)
}
fn anon_region(&self, span: Span, def: Option<&ty::RegionParameterDef>)
-> Result<ty::Region, Option<Vec<ElisionFailureInfo>>>
{
self.base_scope.anon_region(span, def)
}
fn anon_type_scope(&self) -> Option<AnonTypeScope> {
self.base_scope.anon_type_scope()
}
......@@ -348,12 +186,6 @@ fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
ty::fold::shift_region(self.base_scope.base_object_lifetime_default(span), 1)
}
fn anon_region(&self, span: Span, def: Option<&ty::RegionParameterDef>)
-> Result<ty::Region, Option<Vec<ElisionFailureInfo>>>
{
self.base_scope.anon_region(span, def).map(|r| ty::fold::shift_region(r, 1))
}
fn anon_type_scope(&self) -> Option<AnonTypeScope> {
self.base_scope.anon_type_scope()
}
......
......@@ -23,5 +23,17 @@ enum Bar {
//~^ ERROR E0106
//~| NOTE expected lifetime parameter
struct Baz<'a>(&'a str);
struct Buzz<'a, 'b>(&'a str, &'b str);
struct Quux {
baz: Baz,
//~^ ERROR E0106
//~| expected lifetime parameter
buzz: Buzz,
//~^ ERROR E0106
//~| expected 2 lifetime parameters
}
fn main() {
}
......@@ -18,9 +18,6 @@ enum Bar {
}
struct Baz<'a, 'b, 'c> {
foo: Foo,
//~^ ERROR E0107
//~| expected 1 lifetime parameter
buzz: Buzz<'a>,
//~^ ERROR E0107
//~| expected 2 lifetime parameters
......
......@@ -22,10 +22,11 @@ struct SomeStruct<I : for<'x> Foo<&'x isize>> {
//~^ ERROR cannot extract an associated type from a higher-ranked trait bound in this context
}
struct AnotherStruct<I : for<'x> Foo<&'x isize>> {
field: <I as Foo<&isize>>::A
//~^ ERROR missing lifetime specifier
}
// FIXME(eddyb) This one doesn't even compile because of the unsupported syntax.
// struct AnotherStruct<I : for<'x> Foo<&'x isize>> {
// field: <I as for<'y> Foo<&'y isize>>::A
// }
struct YetAnotherStruct<'a, I : for<'x> Foo<&'x isize>> {
field: <I as Foo<&'a isize>>::A
......
......@@ -38,4 +38,28 @@ fn i(_x: isize) -> &isize { //~ ERROR missing lifetime specifier
panic!()
}
// Cases which used to work but now don't.
type StaticStr = &'static str; // hides 'static
trait WithLifetime<'a> {
type Output; // can hide 'a
}
// This worked because the type of the first argument contains
// 'static, although StaticStr doesn't even have parameters.
fn j(_x: StaticStr) -> &isize { //~ ERROR missing lifetime specifier
//~^ HELP this function's return type contains a borrowed value
//~| HELP consider giving it an explicit bounded or 'static lifetime
panic!()
}
// This worked because the compiler resolved the argument type
// to <T as WithLifetime<'a>>::Output which has the hidden 'a.
fn k<'a, T: WithLifetime<'a>>(_x: T::Output) -> &isize {
//~^ ERROR missing lifetime specifier
//~| HELP this function's return type contains a borrowed value
//~| HELP consider giving it an explicit bounded or 'static lifetime
panic!()
}
fn main() {}
......@@ -15,8 +15,10 @@ fn non_elidable<'a, 'b>(a: &'a u8, b: &'b u8) -> &'a u8 {
}
// the boundaries of elision
static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 = &(non_elidable as fn(&u8, &u8) -> &u8);
static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 =
//~^ ERROR missing lifetime specifier [E0106]
&(non_elidable as fn(&u8, &u8) -> &u8);
//~^ ERROR missing lifetime specifier [E0106]
struct SomeStruct<'x, 'y, 'z: 'x> {
foo: &'x Foo<'z>,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册