mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-21 22:34:05 +00:00
Implement inferring outlives requirements for references, structs, enum, union, and projection types. added a feature gate and tests for these scenarios.
This commit is contained in:
parent
9afed64645
commit
6a229cbfac
1
.gitignore
vendored
1
.gitignore
vendored
@ -83,6 +83,7 @@ __pycache__/
|
||||
/src/libstd_unicode/UnicodeData.txt
|
||||
/stage[0-9]+/
|
||||
/target
|
||||
target/
|
||||
/test/
|
||||
/tmp/
|
||||
TAGS
|
||||
|
@ -500,6 +500,7 @@ define_dep_nodes!( <'tcx>
|
||||
[] GenericsOfItem(DefId),
|
||||
[] PredicatesOfItem(DefId),
|
||||
[] InferredOutlivesOf(DefId),
|
||||
[] InferredOutlivesCrate(CrateNum),
|
||||
[] SuperPredicatesOfItem(DefId),
|
||||
[] TraitDefOfItem(DefId),
|
||||
[] AdtDefOfItem(DefId),
|
||||
|
@ -1100,6 +1100,20 @@ impl<'a> HashStable<StableHashingContext<'a>> for ty::CrateVariancesMap {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for ty::CratePredicatesMap<'gcx> {
|
||||
fn hash_stable<W: StableHasherResult>(&self,
|
||||
hcx: &mut StableHashingContext<'a>,
|
||||
hasher: &mut StableHasher<W>) {
|
||||
let ty::CratePredicatesMap {
|
||||
ref predicates,
|
||||
// This is just an irrelevant helper value.
|
||||
empty_predicate: _,
|
||||
} = *self;
|
||||
|
||||
predicates.hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
|
||||
impl_stable_hash_for!(struct ty::AssociatedItem {
|
||||
def_id,
|
||||
name,
|
||||
|
@ -155,6 +155,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::crate_variances<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::inferred_outlives_crate<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
|
||||
format!("computing the inferred outlives predicates for items in this crate")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::mir_shims<'tcx> {
|
||||
fn describe(tcx: TyCtxt, def: ty::InstanceDef<'tcx>) -> String {
|
||||
format!("generating MIR shim for `{}`",
|
||||
|
@ -102,6 +102,7 @@ define_maps! { <'tcx>
|
||||
/// associated generics and predicates.
|
||||
[] fn generics_of: GenericsOfItem(DefId) -> &'tcx ty::Generics,
|
||||
[] fn predicates_of: PredicatesOfItem(DefId) -> ty::GenericPredicates<'tcx>,
|
||||
[] fn explicit_predicates_of: PredicatesOfItem(DefId) -> ty::GenericPredicates<'tcx>,
|
||||
|
||||
/// Maps from the def-id of a trait to the list of
|
||||
/// super-predicates. This is a subset of the full list of
|
||||
@ -139,7 +140,11 @@ define_maps! { <'tcx>
|
||||
[] fn variances_of: ItemVariances(DefId) -> Lrc<Vec<ty::Variance>>,
|
||||
|
||||
/// Maps from def-id of a type to its (inferred) outlives.
|
||||
[] fn inferred_outlives_of: InferredOutlivesOf(DefId) -> Vec<ty::Predicate<'tcx>>,
|
||||
[] fn inferred_outlives_of: InferredOutlivesOf(DefId) -> Lrc<Vec<ty::Predicate<'tcx>>>,
|
||||
|
||||
/// Maps from def-id of a type to its (inferred) outlives.
|
||||
[] fn inferred_outlives_crate: InferredOutlivesCrate(CrateNum)
|
||||
-> Lrc<ty::CratePredicatesMap<'tcx>>,
|
||||
|
||||
/// Maps from an impl/trait def-id to a list of the def-ids of its items
|
||||
[] fn associated_item_def_ids: AssociatedItemDefIds(DefId) -> Lrc<Vec<DefId>>,
|
||||
|
@ -1007,6 +1007,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
|
||||
DepKind::GenericsOfItem => { force!(generics_of, def_id!()); }
|
||||
DepKind::PredicatesOfItem => { force!(predicates_of, def_id!()); }
|
||||
DepKind::InferredOutlivesOf => { force!(inferred_outlives_of, def_id!()); }
|
||||
DepKind::InferredOutlivesCrate => { force!(inferred_outlives_crate, LOCAL_CRATE); }
|
||||
DepKind::SuperPredicatesOfItem => { force!(super_predicates_of, def_id!()); }
|
||||
DepKind::TraitDefOfItem => { force!(trait_def, def_id!()); }
|
||||
DepKind::AdtDefOfItem => { force!(adt_def, def_id!()); }
|
||||
|
@ -956,6 +956,22 @@ pub enum Predicate<'tcx> {
|
||||
ConstEvaluatable(DefId, &'tcx Substs<'tcx>),
|
||||
}
|
||||
|
||||
/// The crate outlives map is computed during typeck and contains the
|
||||
/// outlives of every item in the local crate. You should not use it
|
||||
/// directly, because to do so will make your pass dependent on the
|
||||
/// HIR of every item in the local crate. Instead, use
|
||||
/// `tcx.inferred_outlives_of()` to get the outlives for a *particular*
|
||||
/// item.
|
||||
pub struct CratePredicatesMap<'tcx> {
|
||||
/// For each struct with outlive bounds, maps to a vector of the
|
||||
/// predicate of its outlive bounds. If an item has no outlives
|
||||
/// bounds, it will have no entry.
|
||||
pub predicates: FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>>,
|
||||
|
||||
/// An empty vector, useful for cloning.
|
||||
pub empty_predicate: Lrc<Vec<ty::Predicate<'tcx>>>,
|
||||
}
|
||||
|
||||
impl<'tcx> AsRef<Predicate<'tcx>> for Predicate<'tcx> {
|
||||
fn as_ref(&self) -> &Predicate<'tcx> {
|
||||
self
|
||||
|
@ -64,6 +64,7 @@ pub fn provide(providers: &mut Providers) {
|
||||
type_of,
|
||||
generics_of,
|
||||
predicates_of,
|
||||
explicit_predicates_of,
|
||||
super_predicates_of,
|
||||
type_param_predicates,
|
||||
trait_def,
|
||||
@ -1296,13 +1297,17 @@ fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
def_id: DefId)
|
||||
-> ty::GenericPredicates<'tcx> {
|
||||
let explicit = explicit_predicates_of(tcx, def_id);
|
||||
let predicates = if tcx.sess.features_untracked().infer_outlives_requirements {
|
||||
[&explicit.predicates[..], &tcx.inferred_outlives_of(def_id)[..]].concat()
|
||||
} else { explicit.predicates };
|
||||
|
||||
ty::GenericPredicates {
|
||||
parent: explicit.parent,
|
||||
predicates: [&explicit.predicates[..], &tcx.inferred_outlives_of(def_id)[..]].concat()
|
||||
predicates: predicates,
|
||||
}
|
||||
}
|
||||
|
||||
fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
def_id: DefId)
|
||||
-> ty::GenericPredicates<'tcx> {
|
||||
use rustc::hir::map::*;
|
||||
|
@ -4840,11 +4840,11 @@ register_diagnostics! {
|
||||
E0588, // packed type cannot transitively contain a `[repr(align)]` type
|
||||
E0592, // duplicate definitions with name `{}`
|
||||
// E0613, // Removed (merged with E0609)
|
||||
E0640, // infer outlives
|
||||
E0627, // yield statement outside of generator literal
|
||||
E0632, // cannot provide explicit type parameters when `impl Trait` is used in
|
||||
// argument position.
|
||||
E0634, // type has conflicting packed representaton hints
|
||||
E0640, // infer outlives requirements
|
||||
E0641, // cannot cast to/from a pointer with an unknown kind
|
||||
E0645, // trait aliases not finished
|
||||
E0907, // type inside generator must be known in this context
|
||||
|
@ -82,6 +82,7 @@ This API is completely unstable and subject to change.
|
||||
#![feature(slice_patterns)]
|
||||
#![feature(slice_sort_by_cached_key)]
|
||||
#![feature(dyn_trait)]
|
||||
#![feature(underscore_lifetimes)]
|
||||
|
||||
#[macro_use] extern crate log;
|
||||
#[macro_use] extern crate syntax;
|
||||
|
82
src/librustc_typeck/outlives/explicit.rs
Normal file
82
src/librustc_typeck/outlives/explicit.rs
Normal file
@ -0,0 +1,82 @@
|
||||
// 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::{CrateNum, DefId, LocalDefId, 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;
|
||||
|
||||
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();
|
||||
|
||||
// iterate over the entire crate
|
||||
tcx.hir.krate().visit_all_item_likes(&mut ExplicitVisitor {
|
||||
tcx: tcx,
|
||||
explicit_predicates: &mut predicates,
|
||||
crate_num: crate_num,
|
||||
});
|
||||
|
||||
predicates
|
||||
}
|
||||
|
||||
pub struct ExplicitVisitor<'cx, 'tcx: 'cx> {
|
||||
tcx: TyCtxt<'cx, 'tcx, 'tcx>,
|
||||
explicit_predicates: &'cx mut FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>>,
|
||||
crate_num: CrateNum,
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for ExplicitVisitor<'cx, 'tcx> {
|
||||
fn visit_item(&mut self, item: &'tcx hir::Item) {
|
||||
let def_id = DefId {
|
||||
krate: self.crate_num,
|
||||
index: item.hir_id.owner,
|
||||
};
|
||||
|
||||
let local_explicit_predicate = self.tcx.explicit_predicates_of(def_id);
|
||||
|
||||
let filtered_predicates = local_explicit_predicate
|
||||
.predicates
|
||||
.into_iter()
|
||||
.filter(|pred| match pred {
|
||||
ty::Predicate::TypeOutlives(..) | ty::Predicate::RegionOutlives(..) => true,
|
||||
|
||||
ty::Predicate::Trait(..)
|
||||
| ty::Predicate::Projection(..)
|
||||
| ty::Predicate::WellFormed(..)
|
||||
| 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);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
self.explicit_predicates
|
||||
.insert(def_id, Lrc::new(filtered_predicates));
|
||||
}
|
||||
|
||||
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {}
|
||||
|
||||
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {}
|
||||
}
|
52
src/librustc_typeck/outlives/implicit_empty.rs
Normal file
52
src/librustc_typeck/outlives/implicit_empty.rs
Normal file
@ -0,0 +1,52 @@
|
||||
// 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) {}
|
||||
}
|
442
src/librustc_typeck/outlives/implicit_infer.rs
Normal file
442
src/librustc_typeck/outlives/implicit_infer.rs
Normal file
@ -0,0 +1,442 @@
|
||||
// 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.
|
||||
|
||||
#![allow(unused)]
|
||||
|
||||
use rustc::hir;
|
||||
use rustc::hir::def::{CtorKind, Def};
|
||||
use rustc::hir::def_id::{self, CrateNum, DefId, LOCAL_CRATE};
|
||||
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 syntax::{abi, ast};
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
|
||||
/// Infer predicates for the items in the crate.
|
||||
///
|
||||
/// global_inferred_outlives: this is initially the empty map that
|
||||
/// was generated by walking the items in the crate. This will
|
||||
/// now be filled with inferred predicates.
|
||||
pub fn infer_predicates<'tcx>(
|
||||
tcx: TyCtxt<'_, 'tcx, 'tcx>,
|
||||
explicit_map: &FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>>,
|
||||
) -> FxHashMap<DefId, RequiredPredicates<'tcx>> {
|
||||
debug!("infer_predicates");
|
||||
|
||||
let mut predicates_added = true;
|
||||
|
||||
let mut global_inferred_outlives = FxHashMap::default();
|
||||
|
||||
// If new predicates were added then we need to re-calculate
|
||||
// all crates since there could be new implied predicates.
|
||||
while predicates_added {
|
||||
predicates_added = false;
|
||||
|
||||
let mut visitor = InferVisitor {
|
||||
tcx: tcx,
|
||||
global_inferred_outlives: &mut global_inferred_outlives,
|
||||
predicates_added: &mut predicates_added,
|
||||
explicit_map: explicit_map,
|
||||
};
|
||||
|
||||
// Visit all the crates and infer predicates
|
||||
tcx.hir.krate().visit_all_item_likes(&mut visitor);
|
||||
}
|
||||
|
||||
global_inferred_outlives
|
||||
}
|
||||
|
||||
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>>>>,
|
||||
}
|
||||
|
||||
/// 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
|
||||
.hir
|
||||
.as_local_node_id(item_did)
|
||||
.expect("expected local def-id");
|
||||
let item = match self.tcx.hir.get(node_id) {
|
||||
hir::map::NodeItem(item) => item,
|
||||
_ => bug!(),
|
||||
};
|
||||
|
||||
let mut item_required_predicates = RequiredPredicates::default();
|
||||
match item.node {
|
||||
hir::ItemUnion(..) | hir::ItemEnum(..) | hir::ItemStruct(..) => {
|
||||
let adt_def = self.tcx.adt_def(item_did);
|
||||
|
||||
// Iterate over all fields in item_did
|
||||
for field_def in adt_def.all_fields() {
|
||||
// Calculating the predicate requirements necessary
|
||||
// for item_did.
|
||||
//
|
||||
// For field of type &'a T (reference) or TyAdt
|
||||
// (struct/enum/union) there will be outlive
|
||||
// requirements for adt_def.
|
||||
let field_ty = self.tcx.type_of(field_def.did);
|
||||
insert_required_predicates_to_be_wf(
|
||||
self.tcx,
|
||||
field_ty,
|
||||
self.global_inferred_outlives,
|
||||
&mut item_required_predicates,
|
||||
self.explicit_map,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
_ => {}
|
||||
};
|
||||
|
||||
// If new predicates were added (`local_predicate_map` has more
|
||||
// predicates than the `global_inferred_outlives`), the new predicates
|
||||
// might result in implied predicates for their parent types.
|
||||
// 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
|
||||
.get(&item_did)
|
||||
.map(|p| p.len())
|
||||
.unwrap_or(0);
|
||||
if item_required_predicates.len() > item_predicates_len {
|
||||
*self.predicates_added = true;
|
||||
self.global_inferred_outlives
|
||||
.insert(item_did, item_required_predicates);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {}
|
||||
|
||||
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {}
|
||||
}
|
||||
|
||||
fn insert_required_predicates_to_be_wf<'tcx>(
|
||||
tcx: TyCtxt<'_, 'tcx, '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>>>>,
|
||||
) {
|
||||
for ty in field_ty.walk() {
|
||||
match ty.sty {
|
||||
// The field is of type &'a T which means that we will have
|
||||
// a predicate requirement of T: 'a (T outlives 'a).
|
||||
//
|
||||
// We also want to calculate potential predicates for the T
|
||||
ty::TyRef(region, mt) => {
|
||||
insert_outlives_predicate(tcx, mt.ty.into(), region, required_predicates);
|
||||
}
|
||||
|
||||
// For each TyAdt (struct/enum/union) type `Foo<'a, T>`, we
|
||||
// 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
|
||||
//
|
||||
// Example 1:
|
||||
//
|
||||
// struct Foo<'a, T> {
|
||||
// field1: Bar<'a, T>
|
||||
// }
|
||||
//
|
||||
// struct Bar<'b, U> {
|
||||
// field2: &'b U
|
||||
// }
|
||||
//
|
||||
// Here, when processing the type of `field1`, we would
|
||||
// request the set of implicit predicates computed for `Bar`
|
||||
// thus far. This will initially come back empty, but in next
|
||||
// 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`.
|
||||
if let Some(unsubstituted_predicates) = global_inferred_outlives.get(&def.did) {
|
||||
for unsubstituted_predicate in unsubstituted_predicates {
|
||||
// `unsubstituted_predicate` is `U: 'b` in the
|
||||
// example above. So apply the substitution to
|
||||
// get `T: 'a` (or `predicate`):
|
||||
let predicate = unsubstituted_predicate.subst(tcx, substs);
|
||||
insert_outlives_predicate(
|
||||
tcx,
|
||||
predicate.0,
|
||||
predicate.1,
|
||||
required_predicates,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
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() {
|
||||
check_explicit_predicates(
|
||||
tcx,
|
||||
&p.skip_binder().def_id,
|
||||
&[region.into()],
|
||||
required_predicates,
|
||||
explicit_map,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ty::TyProjection(obj) => {
|
||||
// FIXME This corresponds to `<T as Foo<'a>>::Bar`. In this case, we should use the
|
||||
// explicit predicates as well.
|
||||
check_explicit_predicates(
|
||||
tcx,
|
||||
&obj.item_def_id,
|
||||
obj.substs,
|
||||
required_predicates,
|
||||
explicit_map,
|
||||
);
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// We also have to check the explicit predicates
|
||||
/// declared on the type.
|
||||
///
|
||||
/// struct Foo<'a, T> {
|
||||
/// field1: Bar<T>
|
||||
/// }
|
||||
///
|
||||
/// struct Bar<U> where U: 'static, U: Foo {
|
||||
/// ...
|
||||
/// }
|
||||
///
|
||||
/// Here, we should fetch the explicit predicates, which
|
||||
/// 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>(
|
||||
tcx: TyCtxt<'_, 'tcx, 'tcx>,
|
||||
def_id: &DefId,
|
||||
substs: &[Kind<'tcx>],
|
||||
required_predicates: &mut RequiredPredicates<'tcx>,
|
||||
explicit_map: &FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>>,
|
||||
) {
|
||||
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.0.subst(tcx, substs);
|
||||
insert_outlives_predicate(
|
||||
tcx,
|
||||
predicate.0.into(),
|
||||
predicate.1,
|
||||
required_predicates,
|
||||
);
|
||||
}
|
||||
|
||||
// `poly` is `PolyRegionOutlivesPredicate<OutlivesPredicate<Ty>>`
|
||||
// where OutlivesPredicate<region1, region2> is the predicate
|
||||
// we want to add.
|
||||
ty::Predicate::RegionOutlives(poly) => {
|
||||
let predicate = poly.0.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.
|
||||
//
|
||||
// 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_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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
@ -7,23 +7,105 @@
|
||||
// <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::hir::def_id::DefId;
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
#![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;
|
||||
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
*providers = Providers {
|
||||
inferred_outlives_of,
|
||||
inferred_outlives_crate,
|
||||
..*providers
|
||||
};
|
||||
}
|
||||
|
||||
//todo
|
||||
fn inferred_outlives_of<'a, 'tcx>(_tcx: TyCtxt<'a, 'tcx, 'tcx>, _def_id: DefId)
|
||||
-> Vec<ty::Predicate<'tcx>> {
|
||||
Vec::new()
|
||||
fn inferred_outlives_of<'a, 'tcx>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
item_def_id: DefId,
|
||||
) -> Lrc<Vec<ty::Predicate<'tcx>>> {
|
||||
let id = tcx.hir
|
||||
.as_local_node_id(item_def_id)
|
||||
.expect("expected local def-id");
|
||||
|
||||
match tcx.hir.get(id) {
|
||||
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
|
||||
.predicates
|
||||
.get(&item_def_id)
|
||||
.unwrap_or(&crate_map.empty_predicate)
|
||||
.clone()
|
||||
}
|
||||
|
||||
_ => Lrc::new(Vec::new()),
|
||||
},
|
||||
|
||||
_ => Lrc::new(Vec::new()),
|
||||
}
|
||||
}
|
||||
|
||||
fn inferred_outlives_crate<'tcx>(
|
||||
tcx: TyCtxt<'_, 'tcx, 'tcx>,
|
||||
crate_num: CrateNum,
|
||||
) -> Lrc<CratePredicatesMap<'tcx>> {
|
||||
// Compute a map from each struct/enum/union S to the **explicit**
|
||||
// outlives predicates (`T: 'a`, `'a: 'b`) that the user wrote.
|
||||
// Typically there won't be many of these, except in older code where
|
||||
// they were mandatory. Nonetheless, we have to ensure that every such
|
||||
// predicate is satisfied, so they form a kind of base set of requirements
|
||||
// for the type.
|
||||
|
||||
// Compute the inferred predicates
|
||||
let exp = explicit::explicit_predicates(tcx, crate_num);
|
||||
let mut 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
|
||||
.iter()
|
||||
.map(|(&def_id, set)| {
|
||||
let vec: Vec<ty::Predicate<'tcx>> = set.iter()
|
||||
.map(
|
||||
|ty::OutlivesPredicate(kind1, region2)| match kind1.unpack() {
|
||||
UnpackedKind::Type(ty1) => ty::Predicate::TypeOutlives(ty::Binder(
|
||||
ty::OutlivesPredicate(ty1, region2),
|
||||
)),
|
||||
UnpackedKind::Lifetime(region1) => ty::Predicate::RegionOutlives(
|
||||
ty::Binder(ty::OutlivesPredicate(region1, region2)),
|
||||
),
|
||||
},
|
||||
)
|
||||
.collect();
|
||||
(def_id, Lrc::new(vec))
|
||||
})
|
||||
.collect();
|
||||
|
||||
let empty_predicate = Lrc::new(Vec::new());
|
||||
|
||||
Lrc::new(ty::CratePredicatesMap {
|
||||
predicates,
|
||||
empty_predicate,
|
||||
})
|
||||
}
|
||||
|
@ -13,11 +13,13 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor;
|
||||
use rustc::ty::TyCtxt;
|
||||
|
||||
pub fn test_inferred_outlives<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
||||
tcx.hir.krate().visit_all_item_likes(&mut OutlivesTest { tcx });
|
||||
tcx.hir
|
||||
.krate()
|
||||
.visit_all_item_likes(&mut OutlivesTest { tcx });
|
||||
}
|
||||
|
||||
struct OutlivesTest<'a, 'tcx: 'a> {
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> ItemLikeVisitor<'tcx> for OutlivesTest<'a, 'tcx> {
|
||||
@ -28,14 +30,16 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for OutlivesTest<'a, 'tcx> {
|
||||
// attribute and report an error with various results if found.
|
||||
if self.tcx.has_attr(item_def_id, "rustc_outlives") {
|
||||
let inferred_outlives_of = self.tcx.inferred_outlives_of(item_def_id);
|
||||
span_err!(self.tcx.sess,
|
||||
item.span,
|
||||
E0640,
|
||||
"{:?}",
|
||||
inferred_outlives_of);
|
||||
span_err!(
|
||||
self.tcx.sess,
|
||||
item.span,
|
||||
E0640,
|
||||
"{:?}",
|
||||
inferred_outlives_of
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem) { }
|
||||
fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) { }
|
||||
fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem) {}
|
||||
fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) {}
|
||||
}
|
||||
|
@ -426,6 +426,9 @@ declare_features! (
|
||||
// Use `?` as the Kleene "at most one" operator
|
||||
(active, macro_at_most_once_rep, "1.25.0", Some(48075), None),
|
||||
|
||||
// Infer outlives requirements; RFC 2093
|
||||
(active, infer_outlives_requirements, "1.26.0", Some(44493), None),
|
||||
|
||||
// Multiple patterns with `|` in `if let` and `while let`
|
||||
(active, if_while_or_patterns, "1.26.0", Some(48215), None),
|
||||
|
||||
@ -1023,6 +1026,12 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
|
||||
"never will be stable",
|
||||
cfg_fn!(rustc_attrs))),
|
||||
|
||||
// RFC #2093
|
||||
("infer_outlives_requirements", Normal, Gated(Stability::Unstable,
|
||||
"infer_outlives_requirements",
|
||||
"infer outlives requirements is an experimental feature",
|
||||
cfg_fn!(infer_outlives_requirements))),
|
||||
|
||||
("wasm_custom_section", Whitelisted, Gated(Stability::Unstable,
|
||||
"wasm_custom_section",
|
||||
"attribute is currently unstable",
|
||||
|
@ -8,6 +8,8 @@
|
||||
// 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)]
|
||||
@ -16,7 +18,7 @@
|
||||
// https://github.com/rust-lang/rfcs/blob/master/text/2093-infer-outlives.md#example-1-a-reference
|
||||
|
||||
#[rustc_outlives]
|
||||
struct Direct<'a, T> { //~ ERROR 19:1: 21:2: [] [E0640]
|
||||
struct Direct<'a, T> { //~ ERROR 21:1: 23:2: [Binder(OutlivesPredicate(T, ReEarlyBound(0, 'a)))] [E0640]
|
||||
field: &'a T
|
||||
}
|
||||
|
||||
|
18
src/test/ui/feature-gate-infer_outlives_requirements.rs
Normal file
18
src/test/ui/feature-gate-infer_outlives_requirements.rs
Normal file
@ -0,0 +1,18 @@
|
||||
// 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 T needs to outlive lifetime 'a.
|
||||
struct Foo<'a, T> {
|
||||
bar: &'a [T] //~ ERROR the parameter type `T` may not live long enough [E0309]
|
||||
}
|
||||
|
||||
fn main() { }
|
17
src/test/ui/feature-gate-infer_outlives_requirements.stderr
Normal file
17
src/test/ui/feature-gate-infer_outlives_requirements.stderr
Normal file
@ -0,0 +1,17 @@
|
||||
error[E0309]: the parameter type `T` may not live long enough
|
||||
--> $DIR/feature-gate-infer_outlives_requirements.rs:15:5
|
||||
|
|
||||
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]
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
note: ...so that the reference type `&'a [T]` does not outlive the data it points at
|
||||
--> $DIR/feature-gate-infer_outlives_requirements.rs:15:5
|
||||
|
|
||||
LL | bar: &'a [T] //~ 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`.
|
38
src/test/ui/rfc-2093-infer-outlives/enum-pass.rs
Normal file
38
src/test/ui/rfc-2093-infer-outlives/enum-pass.rs
Normal file
@ -0,0 +1,38 @@
|
||||
// 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.
|
||||
|
||||
// must-compile-successfully
|
||||
|
||||
#![feature(infer_outlives_requirements)]
|
||||
|
||||
// Type T needs to outlive lifetime 'a.
|
||||
enum Foo<'a, T> {
|
||||
|
||||
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() {}
|
||||
|
37
src/test/ui/rfc-2093-infer-outlives/enum.rs
Normal file
37
src/test/ui/rfc-2093-infer-outlives/enum.rs
Normal file
@ -0,0 +1,37 @@
|
||||
// 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)
|
||||
|
||||
// Type T needs to outlive lifetime 'a.
|
||||
enum Foo<'a, T> {
|
||||
|
||||
One(Bar<'a, T>)
|
||||
}
|
||||
|
||||
// Type U needs to outlive lifetime 'b
|
||||
struct Bar<'b, U> {
|
||||
field2: &'b U //~ ERROR 23:5: 23:18: the parameter type `U` may not live long enough [E0309]
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Type K needs to outlive lifetime 'c.
|
||||
enum Ying<'c, K> {
|
||||
One(&'c Yang<K>) //~ ERROR 30:9: 30:21: the parameter type `K` may not live long enough [E0309]
|
||||
}
|
||||
|
||||
struct Yang<V> {
|
||||
field2: V
|
||||
}
|
||||
|
||||
fn main() {}
|
31
src/test/ui/rfc-2093-infer-outlives/enum.stderr
Normal file
31
src/test/ui/rfc-2093-infer-outlives/enum.stderr
Normal file
@ -0,0 +1,31 @@
|
||||
error[E0309]: the parameter type `U` may not live long enough
|
||||
--> $DIR/enum.rs:23:5
|
||||
|
|
||||
LL | struct Bar<'b, U> {
|
||||
| - help: consider adding an explicit lifetime bound `U: 'b`...
|
||||
LL | field2: &'b U //~ ERROR 23:5: 23: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/enum.rs:23:5
|
||||
|
|
||||
LL | field2: &'b U //~ ERROR 23:5: 23:18: the parameter type `U` may not live long enough [E0309]
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error[E0309]: the parameter type `K` may not live long enough
|
||||
--> $DIR/enum.rs:30:9
|
||||
|
|
||||
LL | enum Ying<'c, K> {
|
||||
| - help: consider adding an explicit lifetime bound `K: 'c`...
|
||||
LL | One(&'c Yang<K>) //~ ERROR 30:9: 30:21: 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/enum.rs:30:9
|
||||
|
|
||||
LL | One(&'c Yang<K>) //~ ERROR 30:9: 30:21: 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`.
|
@ -0,0 +1,30 @@
|
||||
// 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
|
||||
// must-compile-successfully
|
||||
|
||||
#![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() {}
|
30
src/test/ui/rfc-2093-infer-outlives/explicit-impl-pass.rs
Normal file
30
src/test/ui/rfc-2093-infer-outlives/explicit-impl-pass.rs
Normal file
@ -0,0 +1,30 @@
|
||||
// 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
|
||||
// must-compile-successfully
|
||||
|
||||
#![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() {}
|
30
src/test/ui/rfc-2093-infer-outlives/explicit-impl.rs
Normal file
30
src/test/ui/rfc-2093-infer-outlives/explicit-impl.rs
Normal file
@ -0,0 +1,30 @@
|
||||
// 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() { }
|
17
src/test/ui/rfc-2093-infer-outlives/explicit-impl.stderr
Normal file
17
src/test/ui/rfc-2093-infer-outlives/explicit-impl.stderr
Normal file
@ -0,0 +1,17 @@
|
||||
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`.
|
27
src/test/ui/rfc-2093-infer-outlives/explicit-where-pass.rs
Normal file
27
src/test/ui/rfc-2093-infer-outlives/explicit-where-pass.rs
Normal file
@ -0,0 +1,27 @@
|
||||
// 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.
|
||||
|
||||
// must-compile-successfully
|
||||
|
||||
#![feature(infer_outlives_requirements)]
|
||||
// Outlives requirementes are inferred (RFC 2093)
|
||||
|
||||
// explicit-where: infer U: 'b
|
||||
struct ExFoo<'b, U> {
|
||||
bar: ExBar<'b, U>
|
||||
}
|
||||
struct ExBar<'a, T> where T: 'a {
|
||||
x: &'a (),
|
||||
y: T,
|
||||
}
|
||||
|
||||
|
||||
fn main() {}
|
||||
|
23
src/test/ui/rfc-2093-infer-outlives/explicit-where.rs
Normal file
23
src/test/ui/rfc-2093-infer-outlives/explicit-where.rs
Normal file
@ -0,0 +1,23 @@
|
||||
// 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() { }
|
17
src/test/ui/rfc-2093-infer-outlives/explicit-where.stderr
Normal file
17
src/test/ui/rfc-2093-infer-outlives/explicit-where.stderr
Normal file
@ -0,0 +1,17 @@
|
||||
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`.
|
22
src/test/ui/rfc-2093-infer-outlives/multiple-regions-pass.rs
Normal file
22
src/test/ui/rfc-2093-infer-outlives/multiple-regions-pass.rs
Normal file
@ -0,0 +1,22 @@
|
||||
// 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.
|
||||
|
||||
// must-compile-successfully
|
||||
|
||||
#![feature(infer_outlives_requirements)]
|
||||
// Outlives requirementes are inferred (RFC 2093)
|
||||
|
||||
// multiple-regions: infer 'b: 'a
|
||||
struct MultiFoo<'a, 'b, T> {
|
||||
x: &'a &'b T
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
19
src/test/ui/rfc-2093-infer-outlives/multiple-regions.rs
Normal file
19
src/test/ui/rfc-2093-infer-outlives/multiple-regions.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// 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.
|
||||
|
||||
// Needs an explicit where clause stating outlives condition. (RFC 2093)
|
||||
|
||||
// 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]
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
20
src/test/ui/rfc-2093-infer-outlives/multiple-regions.stderr
Normal file
20
src/test/ui/rfc-2093-infer-outlives/multiple-regions.stderr
Normal file
@ -0,0 +1,20 @@
|
||||
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`.
|
25
src/test/ui/rfc-2093-infer-outlives/nested-structs-pass.rs
Normal file
25
src/test/ui/rfc-2093-infer-outlives/nested-structs-pass.rs
Normal file
@ -0,0 +1,25 @@
|
||||
// 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.
|
||||
|
||||
// must-compile-successfully
|
||||
|
||||
#![feature(infer_outlives_requirements)]
|
||||
// Outlives requirementes are inferred (RFC 2093)
|
||||
|
||||
// nested-structs: infer U: 'b and therefore T: 'a
|
||||
struct NestFoo<'a, T> {
|
||||
field1: NestBar<'a, T>
|
||||
}
|
||||
struct NestBar<'b, U> {
|
||||
field2: &'b U
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
26
src/test/ui/rfc-2093-infer-outlives/nested-structs.rs
Normal file
26
src/test/ui/rfc-2093-infer-outlives/nested-structs.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// 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.
|
||||
|
||||
// Needs an explicit where clause stating outlives condition. (RFC 2093)
|
||||
|
||||
|
||||
// Type T needs to outlive lifetime 'a. This is not reported due to
|
||||
// a compilation error in Bar.
|
||||
struct Foo<'a, T> {
|
||||
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]
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
17
src/test/ui/rfc-2093-infer-outlives/nested-structs.stderr
Normal file
17
src/test/ui/rfc-2093-infer-outlives/nested-structs.stderr
Normal file
@ -0,0 +1,17 @@
|
||||
error[E0309]: the parameter type `U` may not live long enough
|
||||
--> $DIR/nested-structs.rs:22:5
|
||||
|
|
||||
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]
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
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]
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0309`.
|
23
src/test/ui/rfc-2093-infer-outlives/projections-pass.rs
Normal file
23
src/test/ui/rfc-2093-infer-outlives/projections-pass.rs
Normal file
@ -0,0 +1,23 @@
|
||||
// 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.
|
||||
|
||||
// must-compile-successfully
|
||||
|
||||
#![feature(infer_outlives_requirements)]
|
||||
// Outlives requirementes are inferred (RFC 2093)
|
||||
|
||||
// projections: infer <Iterator>::Item: 'a
|
||||
struct ProjFoo<'a, T: Iterator> {
|
||||
bar: &'a T::Item
|
||||
}
|
||||
|
||||
|
||||
fn main() {}
|
||||
|
20
src/test/ui/rfc-2093-infer-outlives/projections.rs
Normal file
20
src/test/ui/rfc-2093-infer-outlives/projections.rs
Normal file
@ -0,0 +1,20 @@
|
||||
// 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() { }
|
16
src/test/ui/rfc-2093-infer-outlives/projections.stderr
Normal file
16
src/test/ui/rfc-2093-infer-outlives/projections.stderr
Normal file
@ -0,0 +1,16 @@
|
||||
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`.
|
23
src/test/ui/rfc-2093-infer-outlives/reference-pass.rs
Normal file
23
src/test/ui/rfc-2093-infer-outlives/reference-pass.rs
Normal file
@ -0,0 +1,23 @@
|
||||
// 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.
|
||||
|
||||
// must-compile-successfully
|
||||
|
||||
#![feature(infer_outlives_requirements)]
|
||||
// Outlives requirementes are inferred (RFC 2093)
|
||||
|
||||
// reference: infer T: 'a
|
||||
struct RefFoo<'a, T> {
|
||||
bar: &'a [T]
|
||||
}
|
||||
|
||||
|
||||
fn main() {}
|
||||
|
18
src/test/ui/rfc-2093-infer-outlives/reference.rs
Normal file
18
src/test/ui/rfc-2093-infer-outlives/reference.rs
Normal file
@ -0,0 +1,18 @@
|
||||
// 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 T needs to outlive lifetime 'a.
|
||||
struct Foo<'a, T> {
|
||||
bar: &'a [T] //~ ERROR the parameter type `T` may not live long enough [E0309]
|
||||
}
|
||||
|
||||
fn main() { }
|
17
src/test/ui/rfc-2093-infer-outlives/reference.stderr
Normal file
17
src/test/ui/rfc-2093-infer-outlives/reference.stderr
Normal file
@ -0,0 +1,17 @@
|
||||
error[E0309]: the parameter type `T` may not live long enough
|
||||
--> $DIR/reference.rs:15:5
|
||||
|
|
||||
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]
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
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]
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0309`.
|
39
src/test/ui/rfc-2093-infer-outlives/union-pass.rs
Normal file
39
src/test/ui/rfc-2093-infer-outlives/union-pass.rs
Normal file
@ -0,0 +1,39 @@
|
||||
// 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.
|
||||
|
||||
// must-compile-successfully
|
||||
|
||||
#![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> {
|
||||
field1: Bar<'a, T>
|
||||
}
|
||||
|
||||
// Type U needs to outlive lifetime 'b
|
||||
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() {}
|
||||
|
40
src/test/ui/rfc-2093-infer-outlives/union.rs
Normal file
40
src/test/ui/rfc-2093-infer-outlives/union.rs
Normal file
@ -0,0 +1,40 @@
|
||||
// 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() {}
|
||||
|
31
src/test/ui/rfc-2093-infer-outlives/union.stderr
Normal file
31
src/test/ui/rfc-2093-infer-outlives/union.stderr
Normal file
@ -0,0 +1,31 @@
|
||||
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…
Reference in New Issue
Block a user