Implement outlives requirements inference for dyn and projections.
Add tests, documentation and attr for feature.
This commit is contained in:
parent
b86d909f86
commit
3da712381d
45 changed files with 675 additions and 724 deletions
|
|
@ -0,0 +1,67 @@
|
|||
# `infer_outlives_requirements`
|
||||
|
||||
The tracking issue for this feature is: [#44493]
|
||||
|
||||
[#44493]: https://github.com/rust-lang/rust/issues/44493
|
||||
|
||||
------------------------
|
||||
The `infer_outlives_requirements` feature indicates that certain
|
||||
outlives requirements can be infered by the compiler rather than
|
||||
stating them explicitly.
|
||||
|
||||
For example, currently generic struct definitions that contain
|
||||
references, require where-clauses of the form T: 'a. By using
|
||||
this feature the outlives predicates will be infered, although
|
||||
they may still be written explicitly.
|
||||
|
||||
```rust,ignore (pseudo-Rust)
|
||||
struct Foo<'a, T>
|
||||
where T: 'a // <-- currently required
|
||||
{
|
||||
bar: &'a T,
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Examples:
|
||||
|
||||
|
||||
```rust,ignore (pseudo-Rust)
|
||||
#![feature(infer_outlives_requirements)]
|
||||
|
||||
// Implicitly infer T: 'a
|
||||
struct Foo<'a, T> {
|
||||
bar: &'a T,
|
||||
}
|
||||
```
|
||||
|
||||
```rust,ignore (pseudo-Rust)
|
||||
#![feature(infer_outlives_requirements)]
|
||||
|
||||
// Implicitly infer `U: 'b`
|
||||
struct Foo<'b, U> {
|
||||
bar: Bar<'b, U>
|
||||
}
|
||||
|
||||
struct Bar<'a, T> where T: 'a {
|
||||
x: &'a (),
|
||||
y: T,
|
||||
}
|
||||
```
|
||||
|
||||
```rust,ignore (pseudo-Rust)
|
||||
#![feature(infer_outlives_requirements)]
|
||||
|
||||
// Implicitly infer `b': 'a`
|
||||
struct Foo<'a, 'b, T> {
|
||||
x: &'a &'b T
|
||||
}
|
||||
```
|
||||
|
||||
```rust,ignore (pseudo-Rust)
|
||||
#![feature(infer_outlives_requirements)]
|
||||
|
||||
// Implicitly infer `<T as std::iter::Iterator>::Item : 'a`
|
||||
struct Foo<'a, T: Iterator> {
|
||||
bar: &'a T::Item
|
||||
```
|
||||
|
|
@ -8,21 +8,19 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use hir::map as hir_map;
|
||||
use rustc::hir;
|
||||
use rustc::hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
|
||||
use rustc::hir::def_id::{CrateNum, DefId};
|
||||
use rustc::hir::itemlikevisit::ItemLikeVisitor;
|
||||
use rustc::ty::maps::Providers;
|
||||
use rustc::ty::{self, CratePredicatesMap, TyCtxt};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
use util::nodemap::FxHashMap;
|
||||
|
||||
use super::utils::*;
|
||||
|
||||
pub fn explicit_predicates<'tcx>(
|
||||
tcx: TyCtxt<'_, 'tcx, 'tcx>,
|
||||
crate_num: CrateNum,
|
||||
) -> FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>> {
|
||||
assert_eq!(crate_num, LOCAL_CRATE);
|
||||
let mut predicates: FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>> = FxHashMap();
|
||||
) -> FxHashMap<DefId, RequiredPredicates<'tcx>> {
|
||||
let mut predicates = FxHashMap::default();
|
||||
|
||||
// iterate over the entire crate
|
||||
tcx.hir.krate().visit_all_item_likes(&mut ExplicitVisitor {
|
||||
|
|
@ -36,7 +34,7 @@ pub fn explicit_predicates<'tcx>(
|
|||
|
||||
pub struct ExplicitVisitor<'cx, 'tcx: 'cx> {
|
||||
tcx: TyCtxt<'cx, 'tcx, 'tcx>,
|
||||
explicit_predicates: &'cx mut FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>>,
|
||||
explicit_predicates: &'cx mut FxHashMap<DefId, RequiredPredicates<'tcx>>,
|
||||
crate_num: CrateNum,
|
||||
}
|
||||
|
||||
|
|
@ -47,13 +45,25 @@ impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for ExplicitVisitor<'cx, 'tcx> {
|
|||
index: item.hir_id.owner,
|
||||
};
|
||||
|
||||
let local_explicit_predicate = self.tcx.explicit_predicates_of(def_id);
|
||||
let mut required_predicates = RequiredPredicates::default();
|
||||
let local_explicit_predicate = self.tcx.explicit_predicates_of(def_id).predicates;
|
||||
|
||||
let filtered_predicates = local_explicit_predicate
|
||||
.predicates
|
||||
.into_iter()
|
||||
.filter(|pred| match pred {
|
||||
ty::Predicate::TypeOutlives(..) | ty::Predicate::RegionOutlives(..) => true,
|
||||
for pred in local_explicit_predicate.into_iter() {
|
||||
match pred {
|
||||
ty::Predicate::TypeOutlives(predicate) => {
|
||||
let ty::OutlivesPredicate(ref ty, ref reg) = predicate.skip_binder();
|
||||
insert_outlives_predicate(self.tcx, (*ty).into(), reg, &mut required_predicates)
|
||||
}
|
||||
|
||||
ty::Predicate::RegionOutlives(predicate) => {
|
||||
let ty::OutlivesPredicate(ref reg1, ref reg2) = predicate.skip_binder();
|
||||
insert_outlives_predicate(
|
||||
self.tcx,
|
||||
(*reg1).into(),
|
||||
reg2,
|
||||
&mut required_predicates,
|
||||
)
|
||||
}
|
||||
|
||||
ty::Predicate::Trait(..)
|
||||
| ty::Predicate::Projection(..)
|
||||
|
|
@ -61,22 +71,14 @@ impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for ExplicitVisitor<'cx, 'tcx> {
|
|||
| ty::Predicate::ObjectSafe(..)
|
||||
| ty::Predicate::ClosureKind(..)
|
||||
| ty::Predicate::Subtype(..)
|
||||
| ty::Predicate::ConstEvaluatable(..) => false,
|
||||
})
|
||||
.collect();
|
||||
|
||||
match item.node {
|
||||
hir::ItemStruct(..) | hir::ItemEnum(..) => {
|
||||
self.tcx.adt_def(def_id);
|
||||
| ty::Predicate::ConstEvaluatable(..) => (),
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
self.explicit_predicates
|
||||
.insert(def_id, Lrc::new(filtered_predicates));
|
||||
self.explicit_predicates.insert(def_id, required_predicates);
|
||||
}
|
||||
|
||||
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {}
|
||||
fn visit_trait_item(&mut self, _trait_item: &'tcx hir::TraitItem) {}
|
||||
|
||||
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {}
|
||||
fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem) {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,52 +0,0 @@
|
|||
// Copyright 2013 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.
|
||||
|
||||
use hir::map as hir_map;
|
||||
use rustc::hir;
|
||||
use rustc::hir::def_id::{self, CrateNum, DefId, LOCAL_CRATE};
|
||||
use rustc::hir::itemlikevisit::ItemLikeVisitor;
|
||||
use rustc::ty::maps::Providers;
|
||||
use rustc::ty::{self, CratePredicatesMap, TyCtxt};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use util::nodemap::FxHashMap;
|
||||
|
||||
// Create the sets of inferred predicates for each type. These sets
|
||||
// are initially empty but will grow during the inference step.
|
||||
pub fn empty_predicate_map<'tcx>(
|
||||
tcx: TyCtxt<'_, 'tcx, 'tcx>,
|
||||
) -> FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>> {
|
||||
let mut predicates = FxHashMap();
|
||||
|
||||
// iterate over the entire crate
|
||||
tcx.hir
|
||||
.krate()
|
||||
.visit_all_item_likes(&mut EmptyImplicitVisitor {
|
||||
tcx,
|
||||
predicates: &mut predicates,
|
||||
});
|
||||
|
||||
predicates
|
||||
}
|
||||
|
||||
pub struct EmptyImplicitVisitor<'cx, 'tcx: 'cx> {
|
||||
tcx: TyCtxt<'cx, 'tcx, 'tcx>,
|
||||
predicates: &'cx mut FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>>,
|
||||
}
|
||||
|
||||
impl<'a, 'p, 'v> ItemLikeVisitor<'v> for EmptyImplicitVisitor<'a, 'p> {
|
||||
fn visit_item(&mut self, item: &hir::Item) {
|
||||
self.predicates
|
||||
.insert(self.tcx.hir.local_def_id(item.id), Lrc::new(Vec::new()));
|
||||
}
|
||||
|
||||
fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {}
|
||||
|
||||
fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) {}
|
||||
}
|
||||
|
|
@ -8,24 +8,14 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(unused)]
|
||||
|
||||
use rustc::hir;
|
||||
use rustc::hir::def::{CtorKind, Def};
|
||||
use rustc::hir::def_id::{self, CrateNum, DefId, LOCAL_CRATE};
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::hir::itemlikevisit::ItemLikeVisitor;
|
||||
use rustc::hir::map as hir_map;
|
||||
use rustc::ty::Slice;
|
||||
use rustc::ty::maps::Providers;
|
||||
use rustc::ty::outlives::Component;
|
||||
use rustc::ty::subst::{Kind, Subst, UnpackedKind};
|
||||
use rustc::ty::{self, AdtKind, CratePredicatesMap, Region, RegionKind, ReprOptions,
|
||||
ToPolyTraitRef, ToPredicate, Ty, TyCtxt};
|
||||
use rustc::util::nodemap::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_target::spec::abi;
|
||||
use syntax::ast;
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::util::nodemap::FxHashMap;
|
||||
|
||||
use super::utils::*;
|
||||
|
||||
/// Infer predicates for the items in the crate.
|
||||
///
|
||||
|
|
@ -34,7 +24,7 @@ use syntax_pos::{Span, DUMMY_SP};
|
|||
/// now be filled with inferred predicates.
|
||||
pub fn infer_predicates<'tcx>(
|
||||
tcx: TyCtxt<'_, 'tcx, 'tcx>,
|
||||
explicit_map: &FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>>,
|
||||
explicit_map: &FxHashMap<DefId, RequiredPredicates<'tcx>>,
|
||||
) -> FxHashMap<DefId, RequiredPredicates<'tcx>> {
|
||||
debug!("infer_predicates");
|
||||
|
||||
|
|
@ -65,20 +55,17 @@ pub struct InferVisitor<'cx, 'tcx: 'cx> {
|
|||
tcx: TyCtxt<'cx, 'tcx, 'tcx>,
|
||||
global_inferred_outlives: &'cx mut FxHashMap<DefId, RequiredPredicates<'tcx>>,
|
||||
predicates_added: &'cx mut bool,
|
||||
explicit_map: &'cx FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>>,
|
||||
explicit_map: &'cx FxHashMap<DefId, RequiredPredicates<'tcx>>,
|
||||
}
|
||||
|
||||
/// Tracks the `T: 'a` or `'a: 'a` predicates that we have inferred
|
||||
/// must be added to the struct header.
|
||||
type RequiredPredicates<'tcx> = FxHashSet<ty::OutlivesPredicate<Kind<'tcx>, ty::Region<'tcx>>>;
|
||||
|
||||
impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for InferVisitor<'cx, 'tcx> {
|
||||
fn visit_item(&mut self, item: &hir::Item) {
|
||||
let item_did = self.tcx.hir.local_def_id(item.id);
|
||||
|
||||
debug!("InferVisitor::visit_item(item={:?})", item_did);
|
||||
|
||||
let node_id = self.tcx
|
||||
let node_id = self
|
||||
.tcx
|
||||
.hir
|
||||
.as_local_node_id(item_did)
|
||||
.expect("expected local def-id");
|
||||
|
|
@ -120,7 +107,8 @@ impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for InferVisitor<'cx, 'tcx> {
|
|||
// Therefore mark `predicates_added` as true and which will ensure
|
||||
// we walk the crates again and re-calculate predicates for all
|
||||
// items.
|
||||
let item_predicates_len: usize = self.global_inferred_outlives
|
||||
let item_predicates_len: usize = self
|
||||
.global_inferred_outlives
|
||||
.get(&item_did)
|
||||
.map(|p| p.len())
|
||||
.unwrap_or(0);
|
||||
|
|
@ -131,9 +119,9 @@ impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for InferVisitor<'cx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {}
|
||||
fn visit_trait_item(&mut self, _trait_item: &'tcx hir::TraitItem) {}
|
||||
|
||||
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {}
|
||||
fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem) {}
|
||||
}
|
||||
|
||||
fn insert_required_predicates_to_be_wf<'tcx>(
|
||||
|
|
@ -141,7 +129,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
|
|||
field_ty: Ty<'tcx>,
|
||||
global_inferred_outlives: &FxHashMap<DefId, RequiredPredicates<'tcx>>,
|
||||
required_predicates: &mut RequiredPredicates<'tcx>,
|
||||
explicit_map: &FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>>,
|
||||
explicit_map: &FxHashMap<DefId, RequiredPredicates<'tcx>>,
|
||||
) {
|
||||
for ty in field_ty.walk() {
|
||||
match ty.sty {
|
||||
|
|
@ -150,6 +138,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
|
|||
//
|
||||
// We also want to calculate potential predicates for the T
|
||||
ty::TyRef(region, rty, _) => {
|
||||
debug!("TyRef");
|
||||
insert_outlives_predicate(tcx, rty.into(), region, required_predicates);
|
||||
}
|
||||
|
||||
|
|
@ -157,7 +146,6 @@ fn insert_required_predicates_to_be_wf<'tcx>(
|
|||
// can load the current set of inferred and explicit
|
||||
// predicates from `global_inferred_outlives` and filter the
|
||||
// ones that are TypeOutlives.
|
||||
//
|
||||
ty::TyAdt(def, substs) => {
|
||||
// First check the inferred predicates
|
||||
//
|
||||
|
|
@ -177,6 +165,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
|
|||
// round we will get `U: 'b`. We then apply the substitution
|
||||
// `['b => 'a, U => T]` and thus get the requirement that `T:
|
||||
// 'a` holds for `Foo`.
|
||||
debug!("TyAdt");
|
||||
if let Some(unsubstituted_predicates) = global_inferred_outlives.get(&def.did) {
|
||||
for unsubstituted_predicate in unsubstituted_predicates {
|
||||
// `unsubstituted_predicate` is `U: 'b` in the
|
||||
|
|
@ -195,33 +184,51 @@ fn insert_required_predicates_to_be_wf<'tcx>(
|
|||
// Check if the type has any explicit predicates that need
|
||||
// to be added to `required_predicates`
|
||||
// let _: () = substs.region_at(0);
|
||||
check_explicit_predicates(tcx, &def.did, substs, required_predicates, explicit_map);
|
||||
check_explicit_predicates(
|
||||
tcx,
|
||||
&def.did,
|
||||
substs,
|
||||
required_predicates,
|
||||
explicit_map,
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
ty::TyDynamic(obj, region) => {
|
||||
// FIXME This corresponds to `dyn Trait<..>`. In this
|
||||
// case, we should use the explicit predicates as
|
||||
// well.
|
||||
if let Some(p) = obj.principal() {
|
||||
ty::TyDynamic(obj, ..) => {
|
||||
// This corresponds to `dyn Trait<..>`. In this case, we should
|
||||
// use the explicit predicates as well.
|
||||
|
||||
// We are passing type `ty` as a placeholder value with the function
|
||||
// `with_self_ty`, since there is no concrete type `Self` for a
|
||||
// `dyn Trait` at this stage. Therefore when checking explicit
|
||||
// predicates in `check_explicit_predicates` we need to ignore
|
||||
// checking the explicit_map for Self type.
|
||||
debug!("TyDynamic");
|
||||
debug!("field_ty = {}", &field_ty);
|
||||
debug!("ty in field = {}", &ty);
|
||||
if let Some(ex_trait_ref) = obj.principal() {
|
||||
check_explicit_predicates(
|
||||
tcx,
|
||||
&p.skip_binder().def_id,
|
||||
&[region.into()],
|
||||
&ex_trait_ref.skip_binder().def_id,
|
||||
ex_trait_ref.with_self_ty(tcx, ty).skip_binder().substs,
|
||||
required_predicates,
|
||||
explicit_map,
|
||||
true,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ty::TyProjection(obj) => {
|
||||
// FIXME This corresponds to `<T as Foo<'a>>::Bar`. In this case, we should use the
|
||||
// This corresponds to `<T as Foo<'a>>::Bar`. In this case, we should use the
|
||||
// explicit predicates as well.
|
||||
debug!("TyProjection");
|
||||
check_explicit_predicates(
|
||||
tcx,
|
||||
&obj.item_def_id,
|
||||
&tcx.associated_item(obj.item_def_id).container.id(),
|
||||
obj.substs,
|
||||
required_predicates,
|
||||
explicit_map,
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -245,199 +252,58 @@ fn insert_required_predicates_to_be_wf<'tcx>(
|
|||
/// will give us `U: 'static` and `U: Foo`. The latter we
|
||||
/// can ignore, but we will want to process `U: 'static`,
|
||||
/// applying the substitution as above.
|
||||
fn check_explicit_predicates<'tcx>(
|
||||
pub fn check_explicit_predicates<'tcx>(
|
||||
tcx: TyCtxt<'_, 'tcx, 'tcx>,
|
||||
def_id: &DefId,
|
||||
substs: &[Kind<'tcx>],
|
||||
required_predicates: &mut RequiredPredicates<'tcx>,
|
||||
explicit_map: &FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>>,
|
||||
explicit_map: &FxHashMap<DefId, RequiredPredicates<'tcx>>,
|
||||
ignore_self_ty: bool,
|
||||
) {
|
||||
if let Some(general_predicates) = explicit_map.get(def_id) {
|
||||
for general_predicate in general_predicates.iter() {
|
||||
match general_predicate {
|
||||
// `poly` is `PolyTypeOutlivesPredicate<OutlivesPredicate<Ty>>`
|
||||
// where OutlivesPredicate<type1, region1> is the predicate
|
||||
// we want to add.
|
||||
ty::Predicate::TypeOutlives(poly) => {
|
||||
let predicate = poly.skip_binder().subst(tcx, substs);
|
||||
insert_outlives_predicate(
|
||||
tcx,
|
||||
predicate.0.into(),
|
||||
predicate.1,
|
||||
required_predicates,
|
||||
);
|
||||
}
|
||||
debug!("def_id = {:?}", &def_id);
|
||||
debug!("substs = {:?}", &substs);
|
||||
debug!("explicit_map = {:?}", explicit_map);
|
||||
debug!("required_predicates = {:?}", required_predicates);
|
||||
if let Some(explicit_predicates) = explicit_map.get(def_id) {
|
||||
for outlives_predicate in explicit_predicates.iter() {
|
||||
debug!("outlives_predicate = {:?}", &outlives_predicate);
|
||||
|
||||
// `poly` is `PolyRegionOutlivesPredicate<OutlivesPredicate<Ty>>`
|
||||
// where OutlivesPredicate<region1, region2> is the predicate
|
||||
// we want to add.
|
||||
ty::Predicate::RegionOutlives(poly) => {
|
||||
let predicate = poly.skip_binder().subst(tcx, substs);
|
||||
insert_outlives_predicate(
|
||||
tcx,
|
||||
predicate.0.into(),
|
||||
predicate.1,
|
||||
required_predicates,
|
||||
);
|
||||
}
|
||||
|
||||
ty::Predicate::Trait(..)
|
||||
| ty::Predicate::Projection(..)
|
||||
| ty::Predicate::WellFormed(..)
|
||||
| ty::Predicate::ObjectSafe(..)
|
||||
| ty::Predicate::ClosureKind(..)
|
||||
| ty::Predicate::Subtype(..)
|
||||
| ty::Predicate::ConstEvaluatable(..) => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Given a requirement `T: 'a` or `'b: 'a`, deduce the
|
||||
/// outlives_component and add it to `required_predicates`
|
||||
fn insert_outlives_predicate<'tcx>(
|
||||
tcx: TyCtxt<'_, 'tcx, 'tcx>,
|
||||
kind: Kind<'tcx>,
|
||||
outlived_region: Region<'tcx>,
|
||||
required_predicates: &mut RequiredPredicates<'tcx>,
|
||||
) {
|
||||
// If the `'a` region is bound within the field type itself, we
|
||||
// don't want to propagate this constraint to the header.
|
||||
if !is_free_region(outlived_region) {
|
||||
return;
|
||||
}
|
||||
|
||||
match kind.unpack() {
|
||||
UnpackedKind::Type(ty) => {
|
||||
// `T: 'outlived_region` for some type `T`
|
||||
// But T could be a lot of things:
|
||||
// e.g., if `T = &'b u32`, then `'b: 'outlived_region` is
|
||||
// what we want to add.
|
||||
// Careful: If we are inferring the effects of a `dyn Trait<..>`
|
||||
// type, then when we look up the predicates for `Trait`,
|
||||
// we may find some that reference `Self`. e.g., perhaps the
|
||||
// definition of `Trait` was:
|
||||
//
|
||||
// Or if within `struct Foo<U>` you had `T = Vec<U>`, then
|
||||
// we would want to add `U: 'outlived_region`
|
||||
for component in tcx.outlives_components(ty) {
|
||||
match component {
|
||||
Component::Region(r) => {
|
||||
// This would arise from something like:
|
||||
//
|
||||
// ```
|
||||
// struct Foo<'a, 'b> {
|
||||
// x: &'a &'b u32
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// Here `outlived_region = 'a` and `kind = &'b
|
||||
// u32`. Decomposing `&'b u32` into
|
||||
// components would yield `'b`, and we add the
|
||||
// where clause that `'b: 'a`.
|
||||
insert_outlives_predicate(
|
||||
tcx,
|
||||
r.into(),
|
||||
outlived_region,
|
||||
required_predicates,
|
||||
);
|
||||
}
|
||||
|
||||
Component::Param(param_ty) => {
|
||||
// param_ty: ty::ParamTy
|
||||
// This would arise from something like:
|
||||
//
|
||||
// ```
|
||||
// struct Foo<'a, U> {
|
||||
// x: &'a Vec<U>
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// Here `outlived_region = 'a` and `kind =
|
||||
// Vec<U>`. Decomposing `Vec<U>` into
|
||||
// components would yield `U`, and we add the
|
||||
// where clause that `U: 'a`.
|
||||
let ty: Ty<'tcx> = tcx.mk_ty_param(param_ty.idx, param_ty.name);
|
||||
required_predicates
|
||||
.insert(ty::OutlivesPredicate(ty.into(), outlived_region));
|
||||
}
|
||||
|
||||
Component::Projection(proj_ty) => {
|
||||
// This would arise from something like:
|
||||
//
|
||||
// ```
|
||||
// struct Foo<'a, T: Iterator> {
|
||||
// x: &'a <T as Iterator>::Item
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// Here we want to add an explicit `where <T as Iterator>::Item: 'a`.
|
||||
let ty: Ty<'tcx> = tcx.mk_projection(proj_ty.item_def_id, proj_ty.substs);
|
||||
required_predicates
|
||||
.insert(ty::OutlivesPredicate(ty.into(), outlived_region));
|
||||
}
|
||||
|
||||
Component::EscapingProjection(_) => {
|
||||
// As above, but the projection involves
|
||||
// late-bound regions. Therefore, the WF
|
||||
// requirement is not checked in type definition
|
||||
// but at fn call site, so ignore it.
|
||||
//
|
||||
// ```
|
||||
// struct Foo<'a, T: Iterator> {
|
||||
// x: for<'b> fn(<&'b T as Iterator>::Item)
|
||||
// // ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// Since `'b` is not in scope on `Foo`, can't
|
||||
// do anything here, ignore it.
|
||||
}
|
||||
|
||||
Component::UnresolvedInferenceVariable(_) => bug!("not using infcx"),
|
||||
// ```
|
||||
// trait Trait<'a, T> where Self: 'a { .. }
|
||||
// ```
|
||||
//
|
||||
// we want to ignore such predicates here, because
|
||||
// there is no type parameter for them to affect. Consider
|
||||
// a struct containing `dyn Trait`:
|
||||
//
|
||||
// ```
|
||||
// struct MyStruct<'x, X> { field: Box<dyn Trait<'x, X>> }
|
||||
// ```
|
||||
//
|
||||
// The `where Self: 'a` predicate refers to the *existential, hidden type*
|
||||
// that is represented by the `dyn Trait`, not to the `X` type parameter
|
||||
// (or any other generic parameter) declared on `MyStruct`.
|
||||
//
|
||||
// Note that we do this check for self **before** applying `substs`. In the
|
||||
// case that `substs` come from a `dyn Trait` type, our caller will have
|
||||
// included `Self = dyn Trait<'x, X>` as the value for `Self`. If we were
|
||||
// to apply the substs, and not filter this predicate, we might then falsely
|
||||
// conclude that e.g. `X: 'x` was a reasonable inferred requirement.
|
||||
if let UnpackedKind::Type(ty) = outlives_predicate.0.unpack() {
|
||||
if ty.is_self() && ignore_self_ty {
|
||||
debug!("skipping self ty = {:?}", &ty);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UnpackedKind::Lifetime(r) => {
|
||||
if !is_free_region(r) {
|
||||
return;
|
||||
}
|
||||
required_predicates.insert(ty::OutlivesPredicate(kind, outlived_region));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_free_region(region: Region<'_>) -> bool {
|
||||
// First, screen for regions that might appear in a type header.
|
||||
match region {
|
||||
// *These* correspond to `T: 'a` relationships where `'a` is
|
||||
// either declared on the type or `'static`:
|
||||
//
|
||||
// struct Foo<'a, T> {
|
||||
// field: &'a T, // this would generate a ReEarlyBound referencing `'a`
|
||||
// field2: &'static T, // this would generate a ReStatic
|
||||
// }
|
||||
//
|
||||
// We care about these, so fall through.
|
||||
RegionKind::ReStatic | RegionKind::ReEarlyBound(_) => true,
|
||||
|
||||
// Late-bound regions can appear in `fn` types:
|
||||
//
|
||||
// struct Foo<T> {
|
||||
// field: for<'b> fn(&'b T) // e.g., 'b here
|
||||
// }
|
||||
//
|
||||
// The type above might generate a `T: 'b` bound, but we can
|
||||
// ignore it. We can't put it on the struct header anyway.
|
||||
RegionKind::ReLateBound(..) => false,
|
||||
|
||||
// These regions don't appear in types from type declarations:
|
||||
RegionKind::ReEmpty
|
||||
| RegionKind::ReErased
|
||||
| RegionKind::ReClosureBound(..)
|
||||
| RegionKind::ReCanonical(..)
|
||||
| RegionKind::ReScope(..)
|
||||
| RegionKind::ReVar(..)
|
||||
| RegionKind::ReSkolemized(..)
|
||||
| RegionKind::ReFree(..) => {
|
||||
bug!("unexpected region in outlives inference: {:?}", region);
|
||||
let predicate = outlives_predicate.subst(tcx, substs);
|
||||
debug!("predicate = {:?}", &predicate);
|
||||
insert_outlives_predicate(tcx, predicate.0.into(), predicate.1, required_predicates);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,24 +7,20 @@
|
|||
// <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(unused)]
|
||||
#[allow(dead_code)]
|
||||
|
||||
use hir::map as hir_map;
|
||||
use rustc::dep_graph::DepKind;
|
||||
use rustc::hir;
|
||||
use rustc::hir::Ty_::*;
|
||||
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
||||
use rustc::ty::maps::Providers;
|
||||
use rustc::ty::subst::UnpackedKind;
|
||||
use rustc::ty::{self, CratePredicatesMap, TyCtxt};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use util::nodemap::FxHashMap;
|
||||
|
||||
mod explicit;
|
||||
mod implicit_empty;
|
||||
mod implicit_infer;
|
||||
/// Code to write unit test for outlives.
|
||||
pub mod test;
|
||||
mod utils;
|
||||
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
*providers = Providers {
|
||||
|
|
@ -38,7 +34,8 @@ fn inferred_outlives_of<'a, 'tcx>(
|
|||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
item_def_id: DefId,
|
||||
) -> Lrc<Vec<ty::Predicate<'tcx>>> {
|
||||
let id = tcx.hir
|
||||
let id = tcx
|
||||
.hir
|
||||
.as_local_node_id(item_def_id)
|
||||
.expect("expected local def-id");
|
||||
|
||||
|
|
@ -46,14 +43,34 @@ fn inferred_outlives_of<'a, 'tcx>(
|
|||
hir_map::NodeItem(item) => match item.node {
|
||||
hir::ItemStruct(..) | hir::ItemEnum(..) | hir::ItemUnion(..) => {
|
||||
let crate_map = tcx.inferred_outlives_crate(LOCAL_CRATE);
|
||||
let dep_node = item_def_id.to_dep_node(tcx, DepKind::InferredOutlivesOf);
|
||||
tcx.dep_graph.read(dep_node);
|
||||
|
||||
crate_map
|
||||
let predicates = crate_map
|
||||
.predicates
|
||||
.get(&item_def_id)
|
||||
.unwrap_or(&crate_map.empty_predicate)
|
||||
.clone()
|
||||
.clone();
|
||||
|
||||
if tcx.has_attr(item_def_id, "rustc_outlives") {
|
||||
let mut pred: Vec<String> = predicates
|
||||
.iter()
|
||||
.map(|out_pred| match out_pred {
|
||||
ty::Predicate::RegionOutlives(p) => format!("{}", &p),
|
||||
|
||||
ty::Predicate::TypeOutlives(p) => format!("{}", &p),
|
||||
|
||||
err => bug!("unexpected predicate {:?}", err),
|
||||
})
|
||||
.collect();
|
||||
pred.sort();
|
||||
|
||||
let span = tcx.def_span(item_def_id);
|
||||
let mut err = tcx.sess.struct_span_err(span, "rustc_outlives");
|
||||
for p in &pred {
|
||||
err.note(p);
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
predicates
|
||||
}
|
||||
|
||||
_ => Lrc::new(Vec::new()),
|
||||
|
|
@ -76,17 +93,18 @@ fn inferred_outlives_crate<'tcx>(
|
|||
|
||||
// Compute the inferred predicates
|
||||
let exp = explicit::explicit_predicates(tcx, crate_num);
|
||||
let mut global_inferred_outlives = implicit_infer::infer_predicates(tcx, &exp);
|
||||
let global_inferred_outlives = implicit_infer::infer_predicates(tcx, &exp);
|
||||
|
||||
// Convert the inferred predicates into the "collected" form the
|
||||
// global data structure expects.
|
||||
//
|
||||
// FIXME -- consider correcting impedance mismatch in some way,
|
||||
// probably by updating the global data structure.
|
||||
let mut predicates = global_inferred_outlives
|
||||
let predicates = global_inferred_outlives
|
||||
.iter()
|
||||
.map(|(&def_id, set)| {
|
||||
let vec: Vec<ty::Predicate<'tcx>> = set.iter()
|
||||
let vec: Vec<ty::Predicate<'tcx>> = set
|
||||
.iter()
|
||||
.map(
|
||||
|ty::OutlivesPredicate(kind1, region2)| match kind1.unpack() {
|
||||
UnpackedKind::Type(ty1) => ty::Predicate::TypeOutlives(ty::Binder::bind(
|
||||
|
|
|
|||
167
src/librustc_typeck/outlives/utils.rs
Normal file
167
src/librustc_typeck/outlives/utils.rs
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
// Copyright 2013 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.
|
||||
|
||||
use rustc::ty::outlives::Component;
|
||||
use rustc::ty::subst::{Kind, UnpackedKind};
|
||||
use rustc::ty::{self, Region, RegionKind, Ty, TyCtxt};
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
/// Tracks the `T: 'a` or `'a: 'a` predicates that we have inferred
|
||||
/// must be added to the struct header.
|
||||
pub type RequiredPredicates<'tcx> = BTreeSet<ty::OutlivesPredicate<Kind<'tcx>, ty::Region<'tcx>>>;
|
||||
|
||||
/// Given a requirement `T: 'a` or `'b: 'a`, deduce the
|
||||
/// outlives_component and add it to `required_predicates`
|
||||
pub fn insert_outlives_predicate<'tcx>(
|
||||
tcx: TyCtxt<'_, 'tcx, 'tcx>,
|
||||
kind: Kind<'tcx>,
|
||||
outlived_region: Region<'tcx>,
|
||||
required_predicates: &mut RequiredPredicates<'tcx>,
|
||||
) {
|
||||
// If the `'a` region is bound within the field type itself, we
|
||||
// don't want to propagate this constraint to the header.
|
||||
if !is_free_region(outlived_region) {
|
||||
return;
|
||||
}
|
||||
|
||||
match kind.unpack() {
|
||||
UnpackedKind::Type(ty) => {
|
||||
// `T: 'outlived_region` for some type `T`
|
||||
// But T could be a lot of things:
|
||||
// e.g., if `T = &'b u32`, then `'b: 'outlived_region` is
|
||||
// what we want to add.
|
||||
//
|
||||
// Or if within `struct Foo<U>` you had `T = Vec<U>`, then
|
||||
// we would want to add `U: 'outlived_region`
|
||||
for component in tcx.outlives_components(ty) {
|
||||
match component {
|
||||
Component::Region(r) => {
|
||||
// This would arise from something like:
|
||||
//
|
||||
// ```
|
||||
// struct Foo<'a, 'b> {
|
||||
// x: &'a &'b u32
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// Here `outlived_region = 'a` and `kind = &'b
|
||||
// u32`. Decomposing `&'b u32` into
|
||||
// components would yield `'b`, and we add the
|
||||
// where clause that `'b: 'a`.
|
||||
insert_outlives_predicate(
|
||||
tcx,
|
||||
r.into(),
|
||||
outlived_region,
|
||||
required_predicates,
|
||||
);
|
||||
}
|
||||
|
||||
Component::Param(param_ty) => {
|
||||
// param_ty: ty::ParamTy
|
||||
// This would arise from something like:
|
||||
//
|
||||
// ```
|
||||
// struct Foo<'a, U> {
|
||||
// x: &'a Vec<U>
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// Here `outlived_region = 'a` and `kind =
|
||||
// Vec<U>`. Decomposing `Vec<U>` into
|
||||
// components would yield `U`, and we add the
|
||||
// where clause that `U: 'a`.
|
||||
let ty: Ty<'tcx> = param_ty.to_ty(tcx);
|
||||
required_predicates
|
||||
.insert(ty::OutlivesPredicate(ty.into(), outlived_region));
|
||||
}
|
||||
|
||||
Component::Projection(proj_ty) => {
|
||||
// This would arise from something like:
|
||||
//
|
||||
// ```
|
||||
// struct Foo<'a, T: Iterator> {
|
||||
// x: &'a <T as Iterator>::Item
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// Here we want to add an explicit `where <T as Iterator>::Item: 'a`.
|
||||
let ty: Ty<'tcx> = tcx.mk_projection(proj_ty.item_def_id, proj_ty.substs);
|
||||
required_predicates
|
||||
.insert(ty::OutlivesPredicate(ty.into(), outlived_region));
|
||||
}
|
||||
|
||||
Component::EscapingProjection(_) => {
|
||||
// As above, but the projection involves
|
||||
// late-bound regions. Therefore, the WF
|
||||
// requirement is not checked in type definition
|
||||
// but at fn call site, so ignore it.
|
||||
//
|
||||
// ```
|
||||
// struct Foo<'a, T: Iterator> {
|
||||
// x: for<'b> fn(<&'b T as Iterator>::Item)
|
||||
// // ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// Since `'b` is not in scope on `Foo`, can't
|
||||
// do anything here, ignore it.
|
||||
}
|
||||
|
||||
Component::UnresolvedInferenceVariable(_) => bug!("not using infcx"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UnpackedKind::Lifetime(r) => {
|
||||
if !is_free_region(r) {
|
||||
return;
|
||||
}
|
||||
required_predicates.insert(ty::OutlivesPredicate(kind, outlived_region));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_free_region(region: Region<'_>) -> bool {
|
||||
// First, screen for regions that might appear in a type header.
|
||||
match region {
|
||||
// *These* correspond to `T: 'a` relationships where `'a` is
|
||||
// either declared on the type or `'static`:
|
||||
//
|
||||
// struct Foo<'a, T> {
|
||||
// field: &'a T, // this would generate a ReEarlyBound referencing `'a`
|
||||
// field2: &'static T, // this would generate a ReStatic
|
||||
// }
|
||||
//
|
||||
// We care about these, so fall through.
|
||||
RegionKind::ReStatic | RegionKind::ReEarlyBound(_) => true,
|
||||
|
||||
// Late-bound regions can appear in `fn` types:
|
||||
//
|
||||
// struct Foo<T> {
|
||||
// field: for<'b> fn(&'b T) // e.g., 'b here
|
||||
// }
|
||||
//
|
||||
// The type above might generate a `T: 'b` bound, but we can
|
||||
// ignore it. We can't put it on the struct header anyway.
|
||||
RegionKind::ReLateBound(..) => false,
|
||||
|
||||
// These regions don't appear in types from type declarations:
|
||||
RegionKind::ReEmpty
|
||||
| RegionKind::ReErased
|
||||
| RegionKind::ReClosureBound(..)
|
||||
| RegionKind::ReCanonical(..)
|
||||
| RegionKind::ReScope(..)
|
||||
| RegionKind::ReVar(..)
|
||||
| RegionKind::ReSkolemized(..)
|
||||
| RegionKind::ReFree(..) => {
|
||||
bug!("unexpected region in outlives inference: {:?}", region);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -795,6 +795,12 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
|
|||
attribute is an experimental \
|
||||
feature",
|
||||
cfg_fn!(needs_panic_runtime))),
|
||||
("rustc_outlives", Normal, Gated(Stability::Unstable,
|
||||
"rustc_attrs",
|
||||
"the `#[rustc_outlives]` attribute \
|
||||
is just used for rustc unit tests \
|
||||
and will never be stable",
|
||||
cfg_fn!(rustc_attrs))),
|
||||
("rustc_variance", Normal, Gated(Stability::Unstable,
|
||||
"rustc_attrs",
|
||||
"the `#[rustc_variance]` attribute \
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
// 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.
|
||||
|
||||
// ignore-tidy-linelength
|
||||
|
||||
// Test that the outlives computation runs for now...
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
//todo add all the test cases
|
||||
// https://github.com/rust-lang/rfcs/blob/master/text/2093-infer-outlives.md#example-1-a-reference
|
||||
|
||||
#[rustc_outlives]
|
||||
struct Direct<'a, T> { //~ ERROR 21:1: 23:2: [Binder(OutlivesPredicate(T, ReEarlyBound(0, 'a)))] [E0640]
|
||||
field: &'a T
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
|
@ -8,12 +8,17 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Needs an explicit where clause stating outlives condition. (RFC 2093)
|
||||
#![feature(dyn_trait)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(infer_outlives_requirements)]
|
||||
|
||||
// Lifetime 'b needs to outlive lifetime 'a
|
||||
struct Foo<'a,'b,T> {
|
||||
x: &'a &'b T //~ ERROR reference has a longer lifetime than the data it references [E0491]
|
||||
trait Trait<'x, T> where T: 'x {
|
||||
}
|
||||
|
||||
#[rustc_outlives]
|
||||
struct Foo<'a, A> //~ ERROR 19:1: 22:2: rustc_outlives
|
||||
{
|
||||
foo: Box<dyn Trait<'a, A>>
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
||||
13
src/test/ui/rfc-2093-infer-outlives/explicit-dyn.stderr
Normal file
13
src/test/ui/rfc-2093-infer-outlives/explicit-dyn.stderr
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
error: rustc_outlives
|
||||
--> $DIR/explicit-dyn.rs:19:1
|
||||
|
|
||||
LL | / struct Foo<'a, A> //~ ERROR 19:1: 22:2: rustc_outlives
|
||||
LL | | {
|
||||
LL | | foo: Box<dyn Trait<'a, A>>
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
= note: A : 'a
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
@ -8,16 +8,18 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-pass
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(infer_outlives_requirements)]
|
||||
// Outlives requirementes are inferred (RFC 2093)
|
||||
|
||||
// projections: infer <Iterator>::Item: 'a
|
||||
struct ProjFoo<'a, T: Iterator> {
|
||||
bar: &'a T::Item
|
||||
#[rustc_outlives]
|
||||
enum Foo<'a, U> { //~ ERROR 15:1: 17:2: rustc_outlives
|
||||
One(Bar<'a, U>)
|
||||
}
|
||||
|
||||
struct Bar<'x, T> where T: 'x {
|
||||
x: &'x (),
|
||||
y: T,
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
||||
12
src/test/ui/rfc-2093-infer-outlives/explicit-enum.stderr
Normal file
12
src/test/ui/rfc-2093-infer-outlives/explicit-enum.stderr
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
error: rustc_outlives
|
||||
--> $DIR/explicit-enum.rs:15:1
|
||||
|
|
||||
LL | / enum Foo<'a, U> { //~ ERROR 15:1: 17:2: rustc_outlives
|
||||
LL | | One(Bar<'a, U>)
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
= note: U : 'a
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
// 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.
|
||||
|
||||
// ignore-test
|
||||
// compile-pass
|
||||
|
||||
#![feature(infer_outlives_requirements)]
|
||||
// Outlives requirementes are inferred (RFC 2093)
|
||||
|
||||
trait MakeRef<'a>: 'a {
|
||||
type Type;
|
||||
}
|
||||
impl<'a, T> MakeRef<'a> for Vec<T>
|
||||
where T: 'a,
|
||||
{
|
||||
type Type = &'a T;
|
||||
}
|
||||
// explicit-impl: T: 'a
|
||||
struct Foo<'a, T> {
|
||||
foo: <Vec<T> as MakeRef<'a>>::Type,
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
// 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.
|
||||
|
||||
// ignore-test
|
||||
// compile-pass
|
||||
|
||||
#![feature(infer_outlives_requirements)]
|
||||
// Outlives requirementes are inferred (RFC 2093)
|
||||
|
||||
trait MakeRef<'a> {
|
||||
type Type;
|
||||
}
|
||||
impl<'a, T> MakeRef<'a> for Vec<T>
|
||||
where T: 'a,
|
||||
{
|
||||
type Type = &'a T;
|
||||
}
|
||||
// explicit-impl: T: 'a
|
||||
struct Foo<'a, T> {
|
||||
foo: <Vec<T> as MakeRef<'a>>::Type,
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
// 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.
|
||||
|
||||
// ignore-tidy-linelength
|
||||
|
||||
// Needs an explicit where clause stating outlives condition. (RFC 2093)
|
||||
|
||||
trait MakeRef<'a> {
|
||||
type Type;
|
||||
}
|
||||
|
||||
impl<'a, T> MakeRef<'a> for Vec<T>
|
||||
where T: 'a
|
||||
{
|
||||
type Type = &'a T;
|
||||
}
|
||||
|
||||
// Type T needs to outlive lifetime 'a, as stated in impl.
|
||||
struct Foo<'a, T> {
|
||||
foo: <Vec<T> as MakeRef<'a>>::Type //~ Error the parameter type `T` may not live long enough [E0309]
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
error[E0309]: the parameter type `T` may not live long enough
|
||||
--> $DIR/explicit-impl.rs:27:5
|
||||
|
|
||||
LL | struct Foo<'a, T> {
|
||||
| - help: consider adding an explicit lifetime bound `T: 'a`...
|
||||
LL | foo: <Vec<T> as MakeRef<'a>>::Type //~ Error the parameter type `T` may not live long enough [E0309]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...so that the type `T` will meet its required lifetime bounds
|
||||
--> $DIR/explicit-impl.rs:27:5
|
||||
|
|
||||
LL | foo: <Vec<T> as MakeRef<'a>>::Type //~ Error the parameter type `T` may not live long enough [E0309]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0309`.
|
||||
24
src/test/ui/rfc-2093-infer-outlives/explicit-projection.rs
Normal file
24
src/test/ui/rfc-2093-infer-outlives/explicit-projection.rs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
// Copyright 2018 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(rustc_attrs)]
|
||||
#![feature(infer_outlives_requirements)]
|
||||
|
||||
trait Trait<'x, T> where T: 'x {
|
||||
type Type;
|
||||
}
|
||||
|
||||
#[rustc_outlives]
|
||||
struct Foo<'a, A, B> where A: Trait<'a, B> //~ ERROR rustc_outlives
|
||||
{
|
||||
foo: <A as Trait<'a, B>>::Type
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
error: rustc_outlives
|
||||
--> $DIR/explicit-projection.rs:19:1
|
||||
|
|
||||
LL | / struct Foo<'a, A, B> where A: Trait<'a, B> //~ ERROR rustc_outlives
|
||||
LL | | {
|
||||
LL | | foo: <A as Trait<'a, B>>::Type
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
= note: B : 'a
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
@ -8,20 +8,18 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-pass
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(infer_outlives_requirements)]
|
||||
// Outlives requirementes are inferred (RFC 2093)
|
||||
|
||||
// explicit-where: infer U: 'b
|
||||
struct ExFoo<'b, U> {
|
||||
bar: ExBar<'b, U>
|
||||
#[rustc_outlives]
|
||||
struct Foo<'b, U> { //~ ERROR 15:1: 17:2: rustc_outlives
|
||||
bar: Bar<'b, U>
|
||||
}
|
||||
struct ExBar<'a, T> where T: 'a {
|
||||
|
||||
struct Bar<'a, T> where T: 'a {
|
||||
x: &'a (),
|
||||
y: T,
|
||||
}
|
||||
|
||||
|
||||
fn main() {}
|
||||
|
||||
12
src/test/ui/rfc-2093-infer-outlives/explicit-struct.stderr
Normal file
12
src/test/ui/rfc-2093-infer-outlives/explicit-struct.stderr
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
error: rustc_outlives
|
||||
--> $DIR/explicit-struct.rs:15:1
|
||||
|
|
||||
LL | / struct Foo<'b, U> { //~ ERROR 15:1: 17:2: rustc_outlives
|
||||
LL | | bar: Bar<'b, U>
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
= note: U : 'b
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
@ -8,17 +8,20 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-pass
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(infer_outlives_requirements)]
|
||||
// Outlives requirementes are inferred (RFC 2093)
|
||||
#![feature(untagged_unions)]
|
||||
#![allow(unions_with_drop_fields)]
|
||||
|
||||
// nested-structs: infer U: 'b and therefore T: 'a
|
||||
struct NestFoo<'a, T> {
|
||||
field1: NestBar<'a, T>
|
||||
|
||||
#[rustc_outlives]
|
||||
union Foo<'b, U> { //~ ERROR 18:1: 20:2: rustc_outlives
|
||||
bar: Bar<'b, U>
|
||||
}
|
||||
struct NestBar<'b, U> {
|
||||
field2: &'b U
|
||||
|
||||
union Bar<'a, T> where T: 'a {
|
||||
x: &'a (),
|
||||
y: T,
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
12
src/test/ui/rfc-2093-infer-outlives/explicit-union.stderr
Normal file
12
src/test/ui/rfc-2093-infer-outlives/explicit-union.stderr
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
error: rustc_outlives
|
||||
--> $DIR/explicit-union.rs:18:1
|
||||
|
|
||||
LL | / union Foo<'b, U> { //~ ERROR 18:1: 20:2: rustc_outlives
|
||||
LL | | bar: Bar<'b, U>
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
= note: U : 'b
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
// 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.
|
||||
|
||||
// Needs an explicit where clause stating outlives condition. (RFC 2093)
|
||||
|
||||
// Type U needs to outlive lifetime 'b.
|
||||
struct Foo<'b, U> {
|
||||
bar: Bar<'b, U> //~ Error the parameter type `U` may not live long enough [E0309]
|
||||
}
|
||||
|
||||
struct Bar<'a, T> where T: 'a {
|
||||
x: &'a (),
|
||||
y: T,
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
error[E0309]: the parameter type `U` may not live long enough
|
||||
--> $DIR/explicit-where.rs:15:5
|
||||
|
|
||||
LL | struct Foo<'b, U> {
|
||||
| - help: consider adding an explicit lifetime bound `U: 'b`...
|
||||
LL | bar: Bar<'b, U> //~ Error the parameter type `U` may not live long enough [E0309]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...so that the type `U` will meet its required lifetime bounds
|
||||
--> $DIR/explicit-where.rs:15:5
|
||||
|
|
||||
LL | bar: Bar<'b, U> //~ Error the parameter type `U` may not live long enough [E0309]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0309`.
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
error[E0491]: in type `&'a &'b T`, reference has a longer lifetime than the data it references
|
||||
--> $DIR/multiple-regions.rs:15:5
|
||||
|
|
||||
LL | x: &'a &'b T //~ ERROR reference has a longer lifetime than the data it references [E0491]
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
note: the pointer is valid for the lifetime 'a as defined on the struct at 14:1
|
||||
--> $DIR/multiple-regions.rs:14:1
|
||||
|
|
||||
LL | struct Foo<'a,'b,T> {
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
note: but the referenced data is only valid for the lifetime 'b as defined on the struct at 14:1
|
||||
--> $DIR/multiple-regions.rs:14:1
|
||||
|
|
||||
LL | struct Foo<'a,'b,T> {
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0491`.
|
||||
|
|
@ -8,31 +8,18 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-pass
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(infer_outlives_requirements)]
|
||||
|
||||
// Type T needs to outlive lifetime 'a.
|
||||
enum Foo<'a, T> {
|
||||
|
||||
#[rustc_outlives]
|
||||
enum Foo<'a, T> { //~ ERROR 16:1: 19:2: rustc_outlives
|
||||
|
||||
One(Bar<'a, T>)
|
||||
}
|
||||
|
||||
// Type U needs to outlive lifetime 'b
|
||||
struct Bar<'b, U> {
|
||||
field2: &'b U
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Type K needs to outlive lifetime 'c.
|
||||
enum Ying<'c, K> {
|
||||
One(&'c Yang<K>)
|
||||
}
|
||||
|
||||
struct Yang<V> {
|
||||
field2: V
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
||||
13
src/test/ui/rfc-2093-infer-outlives/nested-enum.stderr
Normal file
13
src/test/ui/rfc-2093-infer-outlives/nested-enum.stderr
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
error: rustc_outlives
|
||||
--> $DIR/nested-enum.rs:16:1
|
||||
|
|
||||
LL | / enum Foo<'a, T> { //~ ERROR 16:1: 19:2: rustc_outlives
|
||||
LL | |
|
||||
LL | | One(Bar<'a, T>)
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
= note: T : 'a
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
@ -8,15 +8,12 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-pass
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(infer_outlives_requirements)]
|
||||
// Outlives requirementes are inferred (RFC 2093)
|
||||
|
||||
// multiple-regions: infer 'b: 'a
|
||||
struct MultiFoo<'a, 'b, T> {
|
||||
#[rustc_outlives]
|
||||
struct Foo<'a, 'b, T> { //~ ERROR 15:1: 17:2: rustc_outlives
|
||||
x: &'a &'b T
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
||||
14
src/test/ui/rfc-2093-infer-outlives/nested-regions.stderr
Normal file
14
src/test/ui/rfc-2093-infer-outlives/nested-regions.stderr
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
error: rustc_outlives
|
||||
--> $DIR/nested-regions.rs:15:1
|
||||
|
|
||||
LL | / struct Foo<'a, 'b, T> { //~ ERROR 15:1: 17:2: rustc_outlives
|
||||
LL | | x: &'a &'b T
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
= note: 'b : 'a
|
||||
= note: T : 'a
|
||||
= note: T : 'b
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// 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.
|
||||
//
|
||||
|
|
@ -8,19 +8,16 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Needs an explicit where clause stating outlives condition. (RFC 2093)
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(infer_outlives_requirements)]
|
||||
|
||||
|
||||
// Type T needs to outlive lifetime 'a. This is not reported due to
|
||||
// a compilation error in Bar.
|
||||
struct Foo<'a, T> {
|
||||
#[rustc_outlives]
|
||||
struct Foo<'a, T> { //~ ERROR 15:1: 17:2: rustc_outlives
|
||||
field1: Bar<'a, T>
|
||||
}
|
||||
|
||||
// Type U needs to outlive lifetime 'b
|
||||
struct Bar<'b, U> {
|
||||
field2: &'b U //~ ERROR the parameter type `U` may not live long enough [E0309]
|
||||
field2: &'b U
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,17 +1,12 @@
|
|||
error[E0309]: the parameter type `U` may not live long enough
|
||||
--> $DIR/nested-structs.rs:22:5
|
||||
error: rustc_outlives
|
||||
--> $DIR/nested-structs.rs:15:1
|
||||
|
|
||||
LL | struct Bar<'b, U> {
|
||||
| - help: consider adding an explicit lifetime bound `U: 'b`...
|
||||
LL | field2: &'b U //~ ERROR the parameter type `U` may not live long enough [E0309]
|
||||
| ^^^^^^^^^^^^^
|
||||
LL | / struct Foo<'a, T> { //~ ERROR 15:1: 17:2: rustc_outlives
|
||||
LL | | field1: Bar<'a, T>
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
note: ...so that the reference type `&'b U` does not outlive the data it points at
|
||||
--> $DIR/nested-structs.rs:22:5
|
||||
|
|
||||
LL | field2: &'b U //~ ERROR the parameter type `U` may not live long enough [E0309]
|
||||
| ^^^^^^^^^^^^^
|
||||
= note: T : 'a
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0309`.
|
||||
|
|
|
|||
|
|
@ -8,15 +8,14 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-pass
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(infer_outlives_requirements)]
|
||||
#![feature(untagged_unions)]
|
||||
#![allow(unions_with_drop_fields)]
|
||||
|
||||
// Type T needs to outlive lifetime 'a. This is not reported due to
|
||||
// a compilation error in Bar.
|
||||
union Foo<'a, T> {
|
||||
|
||||
#[rustc_outlives]
|
||||
union Foo<'a, T> { //~ ERROR 18:1: 20:2: rustc_outlives
|
||||
field1: Bar<'a, T>
|
||||
}
|
||||
|
||||
|
|
@ -25,15 +24,4 @@ union Bar<'b, U> {
|
|||
field2: &'b U
|
||||
}
|
||||
|
||||
|
||||
// Type K needs to outlive lifetime 'c.
|
||||
union Ying<'c, K> {
|
||||
field1: &'c Yang<K>
|
||||
}
|
||||
|
||||
union Yang<V> {
|
||||
field2: V
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
||||
12
src/test/ui/rfc-2093-infer-outlives/nested-union.stderr
Normal file
12
src/test/ui/rfc-2093-infer-outlives/nested-union.stderr
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
error: rustc_outlives
|
||||
--> $DIR/nested-union.rs:18:1
|
||||
|
|
||||
LL | / union Foo<'a, T> { //~ ERROR 18:1: 20:2: rustc_outlives
|
||||
LL | | field1: Bar<'a, T>
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
= note: T : 'a
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
@ -8,16 +8,13 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-pass
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(infer_outlives_requirements)]
|
||||
// Outlives requirementes are inferred (RFC 2093)
|
||||
|
||||
// reference: infer T: 'a
|
||||
struct RefFoo<'a, T> {
|
||||
bar: &'a [T]
|
||||
#[rustc_outlives]
|
||||
struct Foo<'a, T: Iterator> { //~ ERROR rustc_outlives
|
||||
bar: &'a T::Item
|
||||
}
|
||||
|
||||
|
||||
fn main() {}
|
||||
|
||||
12
src/test/ui/rfc-2093-infer-outlives/projection.stderr
Normal file
12
src/test/ui/rfc-2093-infer-outlives/projection.stderr
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
error: rustc_outlives
|
||||
--> $DIR/projection.rs:15:1
|
||||
|
|
||||
LL | / struct Foo<'a, T: Iterator> { //~ ERROR rustc_outlives
|
||||
LL | | bar: &'a T::Item
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
= note: <T as std::iter::Iterator>::Item : 'a
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
// 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.
|
||||
|
||||
// ignore-tidy-linelength
|
||||
|
||||
// Needs an explicit where clause stating outlives condition. RFC 2093
|
||||
|
||||
// Associated type <Iterator>::Item needs to outlives lifetime 'a.
|
||||
struct Foo<'a, T: Iterator> {
|
||||
bar: &'a T::Item //~ Error the associated type `<T as std::iter::Iterator>::Item` may not live long enough [E0309]
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
error[E0309]: the associated type `<T as std::iter::Iterator>::Item` may not live long enough
|
||||
--> $DIR/projections.rs:17:5
|
||||
|
|
||||
LL | bar: &'a T::Item //~ Error the associated type `<T as std::iter::Iterator>::Item` may not live long enough [E0309]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider adding an explicit lifetime bound `<T as std::iter::Iterator>::Item: 'a`...
|
||||
note: ...so that the reference type `&'a <T as std::iter::Iterator>::Item` does not outlive the data it points at
|
||||
--> $DIR/projections.rs:17:5
|
||||
|
|
||||
LL | bar: &'a T::Item //~ Error the associated type `<T as std::iter::Iterator>::Item` may not live long enough [E0309]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0309`.
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
|
|
@ -8,11 +8,12 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Needs an explicit where clause stating outlives condition. (RFC 2093)
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(infer_outlives_requirements)]
|
||||
|
||||
// Type T needs to outlive lifetime 'a.
|
||||
struct Foo<'a, T> {
|
||||
bar: &'a [T] //~ ERROR the parameter type `T` may not live long enough [E0309]
|
||||
#[rustc_outlives]
|
||||
struct Foo<'a, T> { //~ ERROR rustc_outlives
|
||||
bar: &'a T,
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,12 @@
|
|||
error[E0309]: the parameter type `T` may not live long enough
|
||||
--> $DIR/reference.rs:15:5
|
||||
error: rustc_outlives
|
||||
--> $DIR/reference.rs:15:1
|
||||
|
|
||||
LL | struct Foo<'a, T> {
|
||||
| - help: consider adding an explicit lifetime bound `T: 'a`...
|
||||
LL | bar: &'a [T] //~ ERROR the parameter type `T` may not live long enough [E0309]
|
||||
| ^^^^^^^^^^^^
|
||||
LL | / struct Foo<'a, T> { //~ ERROR rustc_outlives
|
||||
LL | | bar: &'a T,
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
note: ...so that the reference type `&'a [T]` does not outlive the data it points at
|
||||
--> $DIR/reference.rs:15:5
|
||||
|
|
||||
LL | bar: &'a [T] //~ ERROR the parameter type `T` may not live long enough [E0309]
|
||||
| ^^^^^^^^^^^^
|
||||
= note: T : 'a
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0309`.
|
||||
|
|
|
|||
25
src/test/ui/rfc-2093-infer-outlives/self-dyn.rs
Normal file
25
src/test/ui/rfc-2093-infer-outlives/self-dyn.rs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright 2018 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(dyn_trait)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(infer_outlives_requirements)]
|
||||
|
||||
trait Trait<'x, 's, T> where T: 'x,
|
||||
's: {
|
||||
}
|
||||
|
||||
#[rustc_outlives]
|
||||
struct Foo<'a, 'b, A> //~ ERROR 20:1: 23:2: rustc_outlives
|
||||
{
|
||||
foo: Box<dyn Trait<'a, 'b, A>>
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
13
src/test/ui/rfc-2093-infer-outlives/self-dyn.stderr
Normal file
13
src/test/ui/rfc-2093-infer-outlives/self-dyn.stderr
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
error: rustc_outlives
|
||||
--> $DIR/self-dyn.rs:20:1
|
||||
|
|
||||
LL | / struct Foo<'a, 'b, A> //~ ERROR 20:1: 23:2: rustc_outlives
|
||||
LL | | {
|
||||
LL | | foo: Box<dyn Trait<'a, 'b, A>>
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
= note: A : 'a
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
24
src/test/ui/rfc-2093-infer-outlives/self-structs.rs
Normal file
24
src/test/ui/rfc-2093-infer-outlives/self-structs.rs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(infer_outlives_requirements)]
|
||||
|
||||
#[rustc_outlives]
|
||||
struct Foo<'a, 'b, T> { //~ ERROR 15:1: 17:2: rustc_outlives
|
||||
field1: Bar<'a, 'b, T>
|
||||
}
|
||||
|
||||
trait Bar<'x, 's, U>
|
||||
where U: 'x,
|
||||
Self:'s
|
||||
{}
|
||||
|
||||
fn main() {}
|
||||
12
src/test/ui/rfc-2093-infer-outlives/self-structs.stderr
Normal file
12
src/test/ui/rfc-2093-infer-outlives/self-structs.stderr
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
error: rustc_outlives
|
||||
--> $DIR/self-structs.rs:15:1
|
||||
|
|
||||
LL | / struct Foo<'a, 'b, T> { //~ ERROR 15:1: 17:2: rustc_outlives
|
||||
LL | | field1: Bar<'a, 'b, T>
|
||||
LL | | }
|
||||
| |_^
|
||||
|
|
||||
= note: T : 'a
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
// Copyright 2018 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.
|
||||
|
||||
// ignore-tidy-linelength
|
||||
|
||||
// Needs an explicit where clause stating outlives condition. (RFC 2093)
|
||||
|
||||
#![feature(untagged_unions)]
|
||||
|
||||
// Type T needs to outlive lifetime 'a. This is not reported due to
|
||||
// a compilation error in Bar.
|
||||
union Foo<'a, T> {
|
||||
field1: Bar<'a, T>
|
||||
}
|
||||
|
||||
// Type U needs to outlive lifetime 'b
|
||||
union Bar<'b, U> {
|
||||
field2: &'b U //~ ERROR 25:5: 25:18: the parameter type `U` may not live long enough [E0309]
|
||||
}
|
||||
|
||||
|
||||
// Type K needs to outlive lifetime 'c.
|
||||
union Ying<'c, K> {
|
||||
field1: &'c Yang<K> //~ ERROR 31:5: 31:24: the parameter type `K` may not live long enough [E0309]
|
||||
}
|
||||
|
||||
union Yang<V> {
|
||||
field2: V
|
||||
}
|
||||
|
||||
|
||||
fn main() {}
|
||||
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
error[E0309]: the parameter type `U` may not live long enough
|
||||
--> $DIR/union.rs:25:5
|
||||
|
|
||||
LL | union Bar<'b, U> {
|
||||
| - help: consider adding an explicit lifetime bound `U: 'b`...
|
||||
LL | field2: &'b U //~ ERROR 25:5: 25:18: the parameter type `U` may not live long enough [E0309]
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...so that the reference type `&'b U` does not outlive the data it points at
|
||||
--> $DIR/union.rs:25:5
|
||||
|
|
||||
LL | field2: &'b U //~ ERROR 25:5: 25:18: the parameter type `U` may not live long enough [E0309]
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error[E0309]: the parameter type `K` may not live long enough
|
||||
--> $DIR/union.rs:31:5
|
||||
|
|
||||
LL | union Ying<'c, K> {
|
||||
| - help: consider adding an explicit lifetime bound `K: 'c`...
|
||||
LL | field1: &'c Yang<K> //~ ERROR 31:5: 31:24: the parameter type `K` may not live long enough [E0309]
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...so that the reference type `&'c Yang<K>` does not outlive the data it points at
|
||||
--> $DIR/union.rs:31:5
|
||||
|
|
||||
LL | field1: &'c Yang<K> //~ ERROR 31:5: 31:24: the parameter type `K` may not live long enough [E0309]
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0309`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue