Auto merge of #72362 - matthewjasper:remove-rescope, r=nikomatsakis

Remove ReScope

`ReScope` is unnecessary now that AST borrowck is gone and we're erasing the results of region inference in function bodies. This removes about as much of the old regionck code as possible without having to enable NLL fully.

cc #68261

r? @nikomatsakis
This commit is contained in:
bors 2020-05-24 04:15:08 +00:00
commit 52b605c8cb
81 changed files with 620 additions and 2765 deletions

View file

@ -332,7 +332,6 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
ty::ReStatic
| ty::ReEarlyBound(..)
| ty::ReFree(_)
| ty::ReScope(_)
| ty::ReEmpty(_)
| ty::RePlaceholder(..)
| ty::ReErased => self.canonicalize_region_mode.canonicalize_free_region(self, r),

View file

@ -619,7 +619,6 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
| ty::ReVar(..)
| ty::ReEmpty(_)
| ty::ReStatic
| ty::ReScope(..)
| ty::ReEarlyBound(..)
| ty::ReFree(..) => {
// see common code below

View file

@ -61,7 +61,6 @@ use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::Node;
use rustc_middle::middle::region;
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::{
self,
@ -81,58 +80,12 @@ pub mod nice_region_error;
pub(super) fn note_and_explain_region(
tcx: TyCtxt<'tcx>,
region_scope_tree: &region::ScopeTree,
err: &mut DiagnosticBuilder<'_>,
prefix: &str,
region: ty::Region<'tcx>,
suffix: &str,
) {
let (description, span) = match *region {
ty::ReScope(scope) => {
let new_string;
let unknown_scope =
|| format!("{}unknown scope: {:?}{}. Please report a bug.", prefix, scope, suffix);
let span = scope.span(tcx, region_scope_tree);
let hir_id = scope.hir_id(region_scope_tree);
let tag = match hir_id.and_then(|hir_id| tcx.hir().find(hir_id)) {
Some(Node::Block(_)) => "block",
Some(Node::Expr(expr)) => match expr.kind {
hir::ExprKind::Call(..) => "call",
hir::ExprKind::MethodCall(..) => "method call",
hir::ExprKind::Match(.., hir::MatchSource::IfLetDesugar { .. }) => "if let",
hir::ExprKind::Match(.., hir::MatchSource::WhileLetDesugar) => "while let",
hir::ExprKind::Match(.., hir::MatchSource::ForLoopDesugar) => "for",
hir::ExprKind::Match(..) => "match",
_ => "expression",
},
Some(Node::Stmt(_)) => "statement",
Some(Node::Item(it)) => item_scope_tag(&it),
Some(Node::TraitItem(it)) => trait_item_scope_tag(&it),
Some(Node::ImplItem(it)) => impl_item_scope_tag(&it),
Some(_) | None => {
err.span_note(span, &unknown_scope());
return;
}
};
let scope_decorated_tag = match scope.data {
region::ScopeData::Node => tag,
region::ScopeData::CallSite => "scope of call-site for function",
region::ScopeData::Arguments => "scope of function body",
region::ScopeData::Destruction => {
new_string = format!("destruction scope surrounding {}", tag);
&new_string[..]
}
region::ScopeData::Remainder(first_statement_index) => {
new_string = format!(
"block suffix following statement {}",
first_statement_index.index()
);
&new_string[..]
}
};
explain_span(tcx, scope_decorated_tag, span)
}
ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic => {
msg_span_from_free_region(tcx, region)
}
@ -284,7 +237,6 @@ fn explain_span(tcx: TyCtxt<'tcx>, heading: &str, span: Span) -> (String, Option
pub fn unexpected_hidden_region_diagnostic(
tcx: TyCtxt<'tcx>,
region_scope_tree: Option<&region::ScopeTree>,
span: Span,
hidden_ty: Ty<'tcx>,
hidden_region: ty::Region<'tcx>,
@ -297,64 +249,56 @@ pub fn unexpected_hidden_region_diagnostic(
);
// Explain the region we are capturing.
if let ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic | ty::ReEmpty(_) = hidden_region {
// Assuming regionck succeeded (*), we ought to always be
// capturing *some* region from the fn header, and hence it
// ought to be free. So under normal circumstances, we will go
// down this path which gives a decent human readable
// explanation.
//
// (*) if not, the `tainted_by_errors` field would be set to
// `Some(ErrorReported)` in any case, so we wouldn't be here at all.
note_and_explain_free_region(
tcx,
&mut err,
&format!("hidden type `{}` captures ", hidden_ty),
hidden_region,
"",
);
} else {
// Ugh. This is a painful case: the hidden region is not one
// that we can easily summarize or explain. This can happen
// in a case like
// `src/test/ui/multiple-lifetimes/ordinary-bounds-unsuited.rs`:
//
// ```
// fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> {
// if condition() { a } else { b }
// }
// ```
//
// Here the captured lifetime is the intersection of `'a` and
// `'b`, which we can't quite express.
if let Some(region_scope_tree) = region_scope_tree {
// If the `region_scope_tree` is available, this is being
// invoked from the "region inferencer error". We can at
// least report a really cryptic error for now.
note_and_explain_region(
match hidden_region {
ty::ReEmpty(ty::UniverseIndex::ROOT) => {
// All lifetimes shorter than the function body are `empty` in
// lexical region resolution. The default explanation of "an empty
// lifetime" isn't really accurate here.
let message = format!(
"hidden type `{}` captures lifetime smaller than the function body",
hidden_ty
);
err.span_note(span, &message);
}
ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic | ty::ReEmpty(_) => {
// Assuming regionck succeeded (*), we ought to always be
// capturing *some* region from the fn header, and hence it
// ought to be free. So under normal circumstances, we will go
// down this path which gives a decent human readable
// explanation.
//
// (*) if not, the `tainted_by_errors` field would be set to
// `Some(ErrorReported)` in any case, so we wouldn't be here at all.
note_and_explain_free_region(
tcx,
region_scope_tree,
&mut err,
&format!("hidden type `{}` captures ", hidden_ty),
hidden_region,
"",
);
} else {
// If the `region_scope_tree` is *unavailable*, this is
// being invoked by the code that comes *after* region
// inferencing. This is a bug, as the region inferencer
// ought to have noticed the failed constraint and invoked
// error reporting, which in turn should have prevented us
// from getting trying to infer the hidden type
// completely.
tcx.sess.delay_span_bug(
span,
&format!(
"hidden type captures unexpected lifetime `{:?}` \
but no region inference failure",
hidden_region,
),
}
_ => {
// Ugh. This is a painful case: the hidden region is not one
// that we can easily summarize or explain. This can happen
// in a case like
// `src/test/ui/multiple-lifetimes/ordinary-bounds-unsuited.rs`:
//
// ```
// fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> {
// if condition() { a } else { b }
// }
// ```
//
// Here the captured lifetime is the intersection of `'a` and
// `'b`, which we can't quite express.
// We can at least report a really cryptic error for now.
note_and_explain_region(
tcx,
&mut err,
&format!("hidden type `{}` captures ", hidden_ty),
hidden_region,
"",
);
}
}
@ -363,11 +307,7 @@ pub fn unexpected_hidden_region_diagnostic(
}
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn report_region_errors(
&self,
region_scope_tree: &region::ScopeTree,
errors: &Vec<RegionResolutionError<'tcx>>,
) {
pub fn report_region_errors(&self, errors: &Vec<RegionResolutionError<'tcx>>) {
debug!("report_region_errors(): {} errors to start", errors.len());
// try to pre-process the errors, which will group some of them
@ -390,17 +330,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// general bit of code that displays the error information
RegionResolutionError::ConcreteFailure(origin, sub, sup) => {
if sub.is_placeholder() || sup.is_placeholder() {
self.report_placeholder_failure(region_scope_tree, origin, sub, sup)
.emit();
self.report_placeholder_failure(origin, sub, sup).emit();
} else {
self.report_concrete_failure(region_scope_tree, origin, sub, sup)
.emit();
self.report_concrete_failure(origin, sub, sup).emit();
}
}
RegionResolutionError::GenericBoundFailure(origin, param_ty, sub) => {
self.report_generic_bound_failure(
region_scope_tree,
origin.span(),
Some(origin),
param_ty,
@ -417,29 +354,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
sup_r,
) => {
if sub_r.is_placeholder() {
self.report_placeholder_failure(
region_scope_tree,
sub_origin,
sub_r,
sup_r,
)
.emit();
self.report_placeholder_failure(sub_origin, sub_r, sup_r).emit();
} else if sup_r.is_placeholder() {
self.report_placeholder_failure(
region_scope_tree,
sup_origin,
sub_r,
sup_r,
)
.emit();
self.report_placeholder_failure(sup_origin, sub_r, sup_r).emit();
} else {
self.report_sub_sup_conflict(
region_scope_tree,
var_origin,
sub_origin,
sub_r,
sup_origin,
sup_r,
var_origin, sub_origin, sub_r, sup_origin, sup_r,
);
}
}
@ -460,13 +380,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// value.
let sub_r = self.tcx.mk_region(ty::ReEmpty(var_universe));
self.report_placeholder_failure(
region_scope_tree,
sup_origin,
sub_r,
sup_r,
)
.emit();
self.report_placeholder_failure(sup_origin, sub_r, sup_r).emit();
}
RegionResolutionError::MemberConstraintFailure {
@ -477,7 +391,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
let hidden_ty = self.resolve_vars_if_possible(&hidden_ty);
unexpected_hidden_region_diagnostic(
self.tcx,
Some(region_scope_tree),
span,
hidden_ty,
member_region,
@ -1754,19 +1667,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn report_generic_bound_failure(
&self,
region_scope_tree: &region::ScopeTree,
span: Span,
origin: Option<SubregionOrigin<'tcx>>,
bound_kind: GenericKind<'tcx>,
sub: Region<'tcx>,
) {
self.construct_generic_bound_failure(region_scope_tree, span, origin, bound_kind, sub)
.emit();
self.construct_generic_bound_failure(span, origin, bound_kind, sub).emit();
}
pub fn construct_generic_bound_failure(
&self,
region_scope_tree: &region::ScopeTree,
span: Span,
origin: Option<SubregionOrigin<'tcx>>,
bound_kind: GenericKind<'tcx>,
@ -1918,7 +1828,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
));
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
&format!("{} must be valid for ", labeled_user_string),
sub,
@ -1936,7 +1845,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
fn report_sub_sup_conflict(
&self,
region_scope_tree: &region::ScopeTree,
var_origin: RegionVariableOrigin,
sub_origin: SubregionOrigin<'tcx>,
sub_region: Region<'tcx>,
@ -1947,7 +1855,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"first, the lifetime cannot outlive ",
sup_region,
@ -1973,7 +1880,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
if sub_expected == sup_expected && sub_found == sup_found {
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"...but the lifetime must also be valid for ",
sub_region,
@ -1995,7 +1901,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"but, the lifetime must be valid for ",
sub_region,

View file

@ -8,7 +8,6 @@ use rustc_span::source_map::Span;
mod different_lifetimes;
mod find_anon_type;
mod named_anon_conflict;
mod outlives_closure;
mod placeholder_error;
mod static_impl_trait;
mod trait_impl_difference;
@ -57,7 +56,6 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> {
ErrorReported
})
.or_else(|| self.try_report_anon_anon_conflict())
.or_else(|| self.try_report_outlives_closure())
.or_else(|| self.try_report_static_impl_trait())
.or_else(|| self.try_report_impl_not_conforming_to_trait())
}

View file

@ -1,117 +0,0 @@
//! Error Reporting for Anonymous Region Lifetime Errors
//! where both the regions are anonymous.
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
use crate::infer::lexical_region_resolve::RegionResolutionError::SubSupConflict;
use crate::infer::SubregionOrigin;
use rustc_errors::ErrorReported;
use rustc_hir::{Expr, ExprKind::Closure, Node};
use rustc_middle::ty::RegionKind;
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
/// Print the error message for lifetime errors when binding escapes a closure.
///
/// Consider a case where we have
///
/// ```no_run
/// fn with_int<F>(f: F) where F: FnOnce(&isize) {
/// let x = 3;
/// f(&x);
/// }
/// fn main() {
/// let mut x = None;
/// with_int(|y| x = Some(y));
/// }
/// ```
///
/// the output will be
///
/// ```text
/// let mut x = None;
/// ----- borrowed data cannot be stored into here...
/// with_int(|y| x = Some(y));
/// --- ^ cannot be stored outside of its closure
/// |
/// ...because it cannot outlive this closure
/// ```
pub(super) fn try_report_outlives_closure(&self) -> Option<ErrorReported> {
if let Some(SubSupConflict(_, origin, ref sub_origin, _, ref sup_origin, sup_region)) =
self.error
{
// #45983: when trying to assign the contents of an argument to a binding outside of a
// closure, provide a specific message pointing this out.
if let (
&SubregionOrigin::BindingTypeIsNotValidAtDecl(ref external_span),
&RegionKind::ReFree(ref free_region),
) = (&sub_origin, sup_region)
{
let hir = &self.tcx().hir();
if let Some(def_id) = free_region.scope.as_local() {
let hir_id = hir.as_local_hir_id(def_id);
if let Node::Expr(Expr { kind: Closure(_, _, _, closure_span, None), .. }) =
hir.get(hir_id)
{
let sup_sp = sup_origin.span();
let origin_sp = origin.span();
let mut err = self.tcx().sess.struct_span_err(
sup_sp,
"borrowed data cannot be stored outside of its closure",
);
err.span_label(sup_sp, "cannot be stored outside of its closure");
if origin_sp == sup_sp || origin_sp.contains(sup_sp) {
// // sup_sp == origin.span():
//
// let mut x = None;
// ----- borrowed data cannot be stored into here...
// with_int(|y| x = Some(y));
// --- ^ cannot be stored outside of its closure
// |
// ...because it cannot outlive this closure
//
// // origin.contains(&sup_sp):
//
// let mut f: Option<&u32> = None;
// ----- borrowed data cannot be stored into here...
// closure_expecting_bound(|x: &'x u32| {
// ------------ ... because it cannot outlive this closure
// f = Some(x);
// ^ cannot be stored outside of its closure
err.span_label(
*external_span,
"borrowed data cannot be stored into here...",
);
err.span_label(
*closure_span,
"...because it cannot outlive this closure",
);
} else {
// FIXME: the wording for this case could be much improved
//
// let mut lines_to_use: Vec<&CrateId> = Vec::new();
// - cannot infer an appropriate lifetime...
// let push_id = |installed_id: &CrateId| {
// ------- ------------------------ borrowed data cannot outlive this closure
// |
// ...so that variable is valid at time of its declaration
// lines_to_use.push(installed_id);
// ^^^^^^^^^^^^ cannot be stored outside of its closure
err.span_label(origin_sp, "cannot infer an appropriate lifetime...");
err.span_label(
*external_span,
"...so that variable is valid at time of its \
declaration",
);
err.span_label(
*closure_span,
"borrowed data cannot outlive this closure",
);
}
err.emit();
return Some(ErrorReported);
}
}
}
}
None
}
}

View file

@ -1,7 +1,6 @@
use crate::infer::error_reporting::{note_and_explain_region, ObligationCauseExt};
use crate::infer::{self, InferCtxt, SubregionOrigin};
use rustc_errors::{struct_span_err, DiagnosticBuilder};
use rustc_middle::middle::region;
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::{self, Region};
@ -38,65 +37,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
err.span_note(span, &format!("...so that closure can access `{}`", var_name));
}
infer::InfStackClosure(span) => {
err.span_note(span, "...so that closure does not outlive its stack frame");
}
infer::InvokeClosure(span) => {
err.span_note(span, "...so that closure is not invoked outside its lifetime");
}
infer::DerefPointer(span) => {
err.span_note(span, "...so that pointer is not dereferenced outside its lifetime");
}
infer::ClosureCapture(span, id) => {
err.span_note(
span,
&format!(
"...so that captured variable `{}` does not outlive the \
enclosing closure",
self.tcx.hir().name(id)
),
);
}
infer::IndexSlice(span) => {
err.span_note(span, "...so that slice is not indexed outside the lifetime");
}
infer::RelateObjectBound(span) => {
err.span_note(span, "...so that it can be closed over into an object");
}
infer::CallRcvr(span) => {
err.span_note(span, "...so that method receiver is valid for the method call");
}
infer::CallArg(span) => {
err.span_note(span, "...so that argument is valid for the call");
}
infer::CallReturn(span) => {
err.span_note(span, "...so that return value is valid for the call");
}
infer::Operand(span) => {
err.span_note(span, "...so that operand is valid for operation");
}
infer::AddrOf(span) => {
err.span_note(span, "...so that reference is valid at the time of borrow");
}
infer::AutoBorrow(span) => {
err.span_note(span, "...so that auto-reference is valid at the time of borrow");
}
infer::ExprTypeIsNotInScope(t, span) => {
err.span_note(
span,
&format!(
"...so type `{}` of expression is valid during the \
expression",
self.ty_to_string(t)
),
);
}
infer::BindingTypeIsNotValidAtDecl(span) => {
err.span_note(span, "...so that variable is valid at time of its declaration");
}
infer::ParameterInScope(_, span) => {
err.span_note(span, "...so that a type/lifetime parameter is in scope here");
}
infer::DataBorrowed(ty, span) => {
err.span_note(
span,
@ -126,25 +72,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
),
);
}
infer::RelateDefaultParamBound(span, t) => {
err.span_note(
span,
&format!(
"...so that type parameter instantiated with `{}`, will \
meet its declared lifetime bounds",
self.ty_to_string(t)
),
);
}
infer::RelateRegionParamBound(span) => {
err.span_note(
span,
"...so that the declared lifetime parameter bounds are satisfied",
);
}
infer::SafeDestructor(span) => {
err.span_note(span, "...so that references are valid when the destructor runs");
}
infer::CompareImplMethodObligation { span, .. } => {
err.span_note(
span,
@ -157,7 +90,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub(super) fn report_concrete_failure(
&self,
region_scope_tree: &region::ScopeTree,
origin: SubregionOrigin<'tcx>,
sub: Region<'tcx>,
sup: Region<'tcx>,
@ -166,10 +98,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
infer::Subtype(box trace) => {
let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
let mut err = self.report_and_explain_type_error(trace, &terr);
note_and_explain_region(self.tcx, region_scope_tree, &mut err, "", sup, "...");
note_and_explain_region(self.tcx, &mut err, "", sup, "...");
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"...does not necessarily outlive ",
sub,
@ -187,7 +118,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
);
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"...the reference is valid for ",
sub,
@ -195,7 +125,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
);
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"...but the borrowed content is only valid for ",
sup,
@ -215,7 +144,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
);
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"...the borrowed pointer is valid for ",
sub,
@ -223,7 +151,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
);
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
&format!("...but `{}` is only valid for ", var_name),
sup,
@ -231,106 +158,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
);
err
}
infer::InfStackClosure(span) => {
let mut err =
struct_span_err!(self.tcx.sess, span, E0314, "closure outlives stack frame");
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"...the closure must be valid for ",
sub,
"...",
);
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"...but the closure's stack frame is only valid \
for ",
sup,
"",
);
err
}
infer::InvokeClosure(span) => {
let mut err = struct_span_err!(
self.tcx.sess,
span,
E0315,
"cannot invoke closure outside of its lifetime"
);
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"the closure is only valid for ",
sup,
"",
);
err
}
infer::DerefPointer(span) => {
let mut err = struct_span_err!(
self.tcx.sess,
span,
E0473,
"dereference of reference outside its lifetime"
);
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"the reference is only valid for ",
sup,
"",
);
err
}
infer::ClosureCapture(span, id) => {
let mut err = struct_span_err!(
self.tcx.sess,
span,
E0474,
"captured variable `{}` does not outlive the \
enclosing closure",
self.tcx.hir().name(id)
);
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"captured variable is valid for ",
sup,
"",
);
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"closure is valid for ",
sub,
"",
);
err
}
infer::IndexSlice(span) => {
let mut err = struct_span_err!(
self.tcx.sess,
span,
E0475,
"index of slice outside its lifetime"
);
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"the slice is only valid for ",
sup,
"",
);
err
}
infer::RelateObjectBound(span) => {
let mut err = struct_span_err!(
self.tcx.sess,
@ -339,17 +166,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
"lifetime of the source pointer does not outlive \
lifetime bound of the object type"
);
note_and_explain_region(self.tcx, &mut err, "object type is valid for ", sub, "");
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"object type is valid for ",
sub,
"",
);
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"source pointer is only valid for ",
sup,
@ -367,22 +186,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
self.ty_to_string(ty)
);
match *sub {
ty::ReStatic => note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"type must satisfy ",
sub,
"",
),
_ => note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"type must outlive ",
sub,
"",
),
ty::ReStatic => {
note_and_explain_region(self.tcx, &mut err, "type must satisfy ", sub, "")
}
_ => note_and_explain_region(self.tcx, &mut err, "type must outlive ", sub, ""),
}
err
}
@ -391,7 +198,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"lifetime parameter instantiated with ",
sup,
@ -399,7 +205,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
);
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"but lifetime parameter must outlive ",
sub,
@ -407,61 +212,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
);
err
}
infer::RelateDefaultParamBound(span, ty) => {
let mut err = struct_span_err!(
self.tcx.sess,
span,
E0479,
"the type `{}` (provided as the value of a type \
parameter) is not valid at this point",
self.ty_to_string(ty)
);
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"type must outlive ",
sub,
"",
);
err
}
infer::CallRcvr(span) => {
let mut err = struct_span_err!(
self.tcx.sess,
span,
E0480,
"lifetime of method receiver does not outlive the \
method call"
);
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"the receiver is only valid for ",
sup,
"",
);
err
}
infer::CallArg(span) => {
let mut err = struct_span_err!(
self.tcx.sess,
span,
E0481,
"lifetime of function argument does not outlive \
the function call"
);
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"the function argument is only valid for ",
sup,
"",
);
err
}
infer::CallReturn(span) => {
let mut err = struct_span_err!(
self.tcx.sess,
@ -472,7 +222,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
);
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"the return value is only valid for ",
sup,
@ -480,140 +229,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
);
err
}
infer::Operand(span) => {
let mut err = struct_span_err!(
self.tcx.sess,
span,
E0483,
"lifetime of operand does not outlive the \
operation"
);
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"the operand is only valid for ",
sup,
"",
);
err
}
infer::AddrOf(span) => {
let mut err = struct_span_err!(
self.tcx.sess,
span,
E0484,
"reference is not valid at the time of borrow"
);
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"the borrow is only valid for ",
sup,
"",
);
err
}
infer::AutoBorrow(span) => {
let mut err = struct_span_err!(
self.tcx.sess,
span,
E0485,
"automatically reference is not valid at the time \
of borrow"
);
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"the automatic borrow is only valid for ",
sup,
"",
);
err
}
infer::ExprTypeIsNotInScope(t, span) => {
let mut err = struct_span_err!(
self.tcx.sess,
span,
E0486,
"type of expression contains references that are \
not valid during the expression: `{}`",
self.ty_to_string(t)
);
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"type is only valid for ",
sup,
"",
);
err
}
infer::SafeDestructor(span) => {
let mut err = struct_span_err!(
self.tcx.sess,
span,
E0487,
"unsafe use of destructor: destructor might be \
called while references are dead"
);
// FIXME (22171): terms "super/subregion" are suboptimal
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"superregion: ",
sup,
"",
);
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"subregion: ",
sub,
"",
);
err
}
infer::BindingTypeIsNotValidAtDecl(span) => {
let mut err = struct_span_err!(
self.tcx.sess,
span,
E0488,
"lifetime of variable does not enclose its \
declaration"
);
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"the variable is only valid for ",
sup,
"",
);
err
}
infer::ParameterInScope(_, span) => {
let mut err = struct_span_err!(
self.tcx.sess,
span,
E0489,
"type/lifetime parameter not in scope here"
);
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"the parameter is only valid for ",
sub,
"",
);
err
}
infer::DataBorrowed(ty, span) => {
let mut err = struct_span_err!(
self.tcx.sess,
@ -622,22 +237,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
"a value of type `{}` is borrowed for too long",
self.ty_to_string(ty)
);
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"the type is valid for ",
sub,
"",
);
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"but the borrow lasts for ",
sup,
"",
);
note_and_explain_region(self.tcx, &mut err, "the type is valid for ", sub, "");
note_and_explain_region(self.tcx, &mut err, "but the borrow lasts for ", sup, "");
err
}
infer::ReferenceOutlivesReferent(ty, span) => {
@ -648,17 +249,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
"in type `{}`, reference has a longer lifetime than the data it references",
self.ty_to_string(ty)
);
note_and_explain_region(self.tcx, &mut err, "the pointer is valid for ", sub, "");
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"the pointer is valid for ",
sub,
"",
);
note_and_explain_region(
self.tcx,
region_scope_tree,
&mut err,
"but the referenced data is only valid for ",
sup,
@ -683,7 +276,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub(super) fn report_placeholder_failure(
&self,
region_scope_tree: &region::ScopeTree,
placeholder_origin: SubregionOrigin<'tcx>,
sub: Region<'tcx>,
sup: Region<'tcx>,
@ -695,7 +287,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
self.report_and_explain_type_error(trace, &terr)
}
_ => self.report_concrete_failure(region_scope_tree, placeholder_origin, sub, sup),
_ => self.report_concrete_failure(placeholder_origin, sub, sup),
}
}
}

View file

@ -5,7 +5,6 @@
use rustc_data_structures::transitive_relation::TransitiveRelation;
use rustc_hir::def_id::DefId;
use rustc_middle::middle::region;
use rustc_middle::ty::{self, Lift, Region, TyCtxt};
/// Combines a `region::ScopeTree` (which governs relationships between
@ -21,21 +20,13 @@ pub struct RegionRelations<'a, 'tcx> {
/// The context used to fetch the region maps.
pub context: DefId,
/// The region maps for the given context.
pub region_scope_tree: &'a region::ScopeTree,
/// Free-region relationships.
pub free_regions: &'a FreeRegionMap<'tcx>,
}
impl<'a, 'tcx> RegionRelations<'a, 'tcx> {
pub fn new(
tcx: TyCtxt<'tcx>,
context: DefId,
region_scope_tree: &'a region::ScopeTree,
free_regions: &'a FreeRegionMap<'tcx>,
) -> Self {
Self { tcx, context, region_scope_tree, free_regions }
pub fn new(tcx: TyCtxt<'tcx>, context: DefId, free_regions: &'a FreeRegionMap<'tcx>) -> Self {
Self { tcx, context, free_regions }
}
pub fn lub_free_regions(&self, r_a: Region<'tcx>, r_b: Region<'tcx>) -> Region<'tcx> {

View file

@ -127,7 +127,6 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
ty::ReStatic
| ty::ReEarlyBound(..)
| ty::ReFree(_)
| ty::ReScope(_)
| ty::ReVar(_)
| ty::RePlaceholder(..)
| ty::ReEmpty(_)

View file

@ -1,253 +0,0 @@
//! This module provides linkage between libgraphviz traits and
//! `rustc_trait_selection::infer::region_constraints`, generating a
//! rendering of the graph represented by the list of `Constraint`
//! instances (which make up the edges of the graph), as well as the
//! origin for each constraint (which are attached to the labels on
//! each edge).
/// For clarity, rename the graphviz crate locally to dot.
use graphviz as dot;
use super::Constraint;
use crate::infer::region_constraints::RegionConstraintData;
use crate::infer::RegionRelations;
use crate::infer::SubregionOrigin;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir::def_id::DefIndex;
use rustc_middle::middle::region;
use rustc_middle::ty;
use std::borrow::Cow;
use std::collections::btree_map::BTreeMap;
use std::collections::hash_map::Entry::Vacant;
use std::env;
use std::fs;
use std::io;
use std::sync::atomic::{AtomicBool, Ordering};
fn print_help_message() {
println!(
"\
-Z print-region-graph by default prints a region constraint graph for every \n\
function body, to the path `constraints.nodeXXX.dot`, where the XXX is \n\
replaced with the node id of the function under analysis. \n\
\n\
To select one particular function body, set `RUST_REGION_GRAPH_NODE=XXX`, \n\
where XXX is the node id desired. \n\
\n\
To generate output to some path other than the default \n\
`constraints.nodeXXX.dot`, set `RUST_REGION_GRAPH=/path/desired.dot`; \n\
occurrences of the character `%` in the requested path will be replaced with\n\
the node id of the function under analysis. \n\
\n\
(Since you requested help via RUST_REGION_GRAPH=help, no region constraint \n\
graphs will be printed. \n\
"
);
}
pub fn maybe_print_constraints_for<'a, 'tcx>(
region_data: &RegionConstraintData<'tcx>,
region_rels: &RegionRelations<'a, 'tcx>,
) {
let tcx = region_rels.tcx;
let context = region_rels.context;
if !tcx.sess.opts.debugging_opts.print_region_graph {
return;
}
let requested_node = env::var("RUST_REGION_GRAPH_NODE")
.ok()
.and_then(|s| s.parse().map(DefIndex::from_u32).ok());
if requested_node.is_some() && requested_node != Some(context.index) {
return;
}
let requested_output = env::var("RUST_REGION_GRAPH");
debug!("requested_output: {:?} requested_node: {:?}", requested_output, requested_node);
let output_path = {
let output_template = match requested_output {
Ok(ref s) if s == "help" => {
static PRINTED_YET: AtomicBool = AtomicBool::new(false);
if !PRINTED_YET.load(Ordering::SeqCst) {
print_help_message();
PRINTED_YET.store(true, Ordering::SeqCst);
}
return;
}
Ok(other_path) => other_path,
Err(_) => "constraints.node%.dot".to_string(),
};
if output_template.is_empty() {
panic!("empty string provided as RUST_REGION_GRAPH");
}
if output_template.contains('%') {
let mut new_str = String::new();
for c in output_template.chars() {
if c == '%' {
new_str.push_str(&context.index.as_u32().to_string());
} else {
new_str.push(c);
}
}
new_str
} else {
output_template
}
};
if let Err(e) = dump_region_data_to(region_rels, &region_data.constraints, &output_path) {
let msg = format!("io error dumping region constraints: {}", e);
tcx.sess.err(&msg)
}
}
struct ConstraintGraph<'a, 'tcx> {
graph_name: String,
region_rels: &'a RegionRelations<'a, 'tcx>,
map: &'a BTreeMap<Constraint<'tcx>, SubregionOrigin<'tcx>>,
node_ids: FxHashMap<Node, usize>,
}
#[derive(Clone, Hash, PartialEq, Eq, Debug, Copy)]
enum Node {
RegionVid(ty::RegionVid),
Region(ty::RegionKind),
}
#[derive(Clone, PartialEq, Eq, Debug, Copy)]
enum Edge<'tcx> {
Constraint(Constraint<'tcx>),
EnclScope(region::Scope, region::Scope),
}
impl<'a, 'tcx> ConstraintGraph<'a, 'tcx> {
fn new(
name: String,
region_rels: &'a RegionRelations<'a, 'tcx>,
map: &'a ConstraintMap<'tcx>,
) -> ConstraintGraph<'a, 'tcx> {
let mut i = 0;
let mut node_ids = FxHashMap::default();
{
let mut add_node = |node| {
if let Vacant(e) = node_ids.entry(node) {
e.insert(i);
i += 1;
}
};
for (n1, n2) in map.keys().map(|c| constraint_to_nodes(c)) {
add_node(n1);
add_node(n2);
}
region_rels.region_scope_tree.each_encl_scope(|sub, sup| {
add_node(Node::Region(ty::ReScope(sub)));
add_node(Node::Region(ty::ReScope(sup)));
});
}
ConstraintGraph { map, node_ids, region_rels, graph_name: name }
}
}
impl<'a, 'tcx> dot::Labeller<'a> for ConstraintGraph<'a, 'tcx> {
type Node = Node;
type Edge = Edge<'tcx>;
fn graph_id(&self) -> dot::Id<'_> {
dot::Id::new(&*self.graph_name).unwrap()
}
fn node_id(&self, n: &Node) -> dot::Id<'_> {
let node_id = match self.node_ids.get(n) {
Some(node_id) => node_id,
None => bug!("no node_id found for node: {:?}", n),
};
let name = || format!("node_{}", node_id);
dot::Id::new(name())
.unwrap_or_else(|_| bug!("failed to create graphviz node identified by {}", name()))
}
fn node_label(&self, n: &Node) -> dot::LabelText<'_> {
match *n {
Node::RegionVid(n_vid) => dot::LabelText::label(format!("{:?}", n_vid)),
Node::Region(n_rgn) => dot::LabelText::label(format!("{:?}", n_rgn)),
}
}
fn edge_label(&self, e: &Edge<'_>) -> dot::LabelText<'_> {
match *e {
Edge::Constraint(ref c) => {
dot::LabelText::label(format!("{:?}", self.map.get(c).unwrap()))
}
Edge::EnclScope(..) => dot::LabelText::label("(enclosed)".to_owned()),
}
}
}
fn constraint_to_nodes(c: &Constraint<'_>) -> (Node, Node) {
match *c {
Constraint::VarSubVar(rv_1, rv_2) => (Node::RegionVid(rv_1), Node::RegionVid(rv_2)),
Constraint::RegSubVar(r_1, rv_2) => (Node::Region(*r_1), Node::RegionVid(rv_2)),
Constraint::VarSubReg(rv_1, r_2) => (Node::RegionVid(rv_1), Node::Region(*r_2)),
Constraint::RegSubReg(r_1, r_2) => (Node::Region(*r_1), Node::Region(*r_2)),
}
}
fn edge_to_nodes(e: &Edge<'_>) -> (Node, Node) {
match *e {
Edge::Constraint(ref c) => constraint_to_nodes(c),
Edge::EnclScope(sub, sup) => {
(Node::Region(ty::ReScope(sub)), Node::Region(ty::ReScope(sup)))
}
}
}
impl<'a, 'tcx> dot::GraphWalk<'a> for ConstraintGraph<'a, 'tcx> {
type Node = Node;
type Edge = Edge<'tcx>;
fn nodes(&self) -> dot::Nodes<'_, Node> {
let set = self.node_ids.keys().cloned().collect::<FxHashSet<_>>();
debug!("constraint graph has {} nodes", set.len());
set.into_iter().collect()
}
fn edges(&self) -> dot::Edges<'_, Edge<'tcx>> {
debug!("constraint graph has {} edges", self.map.len());
let mut v: Vec<_> = self.map.keys().map(|e| Edge::Constraint(*e)).collect();
self.region_rels
.region_scope_tree
.each_encl_scope(|sub, sup| v.push(Edge::EnclScope(sub, sup)));
debug!("region graph has {} edges", v.len());
Cow::Owned(v)
}
fn source(&self, edge: &Edge<'tcx>) -> Node {
let (n1, _) = edge_to_nodes(edge);
debug!("edge {:?} has source {:?}", edge, n1);
n1
}
fn target(&self, edge: &Edge<'tcx>) -> Node {
let (_, n2) = edge_to_nodes(edge);
debug!("edge {:?} has target {:?}", edge, n2);
n2
}
}
pub type ConstraintMap<'tcx> = BTreeMap<Constraint<'tcx>, SubregionOrigin<'tcx>>;
fn dump_region_data_to<'a, 'tcx>(
region_rels: &RegionRelations<'a, 'tcx>,
map: &ConstraintMap<'tcx>,
path: &str,
) -> io::Result<()> {
debug!("dump_region_data map (len: {}) path: {}", map.len(), path);
let g = ConstraintGraph::new("region_data".to_string(), region_rels, map);
debug!("dump_region_data calling render");
let mut v = Vec::new();
dot::render(&g, &mut v).unwrap();
fs::write(path, &v)
}

View file

@ -18,13 +18,11 @@ use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{ReEarlyBound, ReEmpty, ReErased, ReFree, ReStatic};
use rustc_middle::ty::{ReLateBound, RePlaceholder, ReScope, ReVar};
use rustc_middle::ty::{ReLateBound, RePlaceholder, ReVar};
use rustc_middle::ty::{Region, RegionVid};
use rustc_span::Span;
use std::fmt;
mod graphviz;
/// This function performs lexical region resolution given a complete
/// set of constraints and variable origins. It performs a fixed-point
/// iteration to find region values which satisfy all constraints,
@ -49,7 +47,10 @@ pub fn resolve<'tcx>(
let mut values = resolver.infer_variable_values(&mut errors);
let re_erased = region_rels.tcx.lifetimes.re_erased;
values.values.iter_mut().for_each(|v| *v = VarValue::Value(re_erased));
values.values.iter_mut().for_each(|v| match *v {
VarValue::Value(ref mut r) => *r = re_erased,
VarValue::ErrorValue => {}
});
(values, errors)
}
RegionckMode::Erase { suppress_errors: true } => {
@ -146,7 +147,6 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
self.region_rels.context,
self.dump_constraints(self.region_rels)
);
graphviz::maybe_print_constraints_for(&self.data, self.region_rels);
let graph = self.construct_graph();
self.expand_givens(&graph);
@ -290,8 +290,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
// Find all the "upper bounds" -- that is, each region `b` such that
// `r0 <= b` must hold.
let (member_upper_bounds, _) =
self.collect_concrete_regions(graph, member_vid, OUTGOING, None);
let (member_upper_bounds, ..) =
self.collect_bounding_regions(graph, member_vid, OUTGOING, None);
// Get an iterator over the *available choice* -- that is,
// each choice region `c` where `lb <= c` and `c <= ub` for all the
@ -423,15 +423,6 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
match *b_data {
VarValue::Value(cur_region) => {
// Identical scopes can show up quite often, if the fixed point
// iteration converges slowly. Skip them. This is purely an
// optimization.
if let (ReScope(a_scope), ReScope(cur_scope)) = (a_region, cur_region) {
if a_scope == cur_scope {
return false;
}
}
// This is a specialized version of the `lub_concrete_regions`
// check below for a common case, here purely as an
// optimization.
@ -525,8 +516,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
self.tcx().lifetimes.re_static
}
(&ReEmpty(_), r @ (ReEarlyBound(_) | ReFree(_) | ReScope(_)))
| (r @ (ReEarlyBound(_) | ReFree(_) | ReScope(_)), &ReEmpty(_)) => {
(&ReEmpty(_), r @ (ReEarlyBound(_) | ReFree(_)))
| (r @ (ReEarlyBound(_) | ReFree(_)), &ReEmpty(_)) => {
// All empty regions are less than early-bound, free,
// and scope regions.
r
@ -551,46 +542,6 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
}
}
(&ReEarlyBound(_) | &ReFree(_), &ReScope(s_id))
| (&ReScope(s_id), &ReEarlyBound(_) | &ReFree(_)) => {
// A "free" region can be interpreted as "some region
// at least as big as fr.scope". So, we can
// reasonably compare free regions and scopes:
let fr_scope = match (a, b) {
(&ReEarlyBound(ref br), _) | (_, &ReEarlyBound(ref br)) => {
self.region_rels.region_scope_tree.early_free_scope(self.tcx(), br)
}
(&ReFree(ref fr), _) | (_, &ReFree(ref fr)) => {
self.region_rels.region_scope_tree.free_scope(self.tcx(), fr)
}
_ => bug!(),
};
let r_id =
self.region_rels.region_scope_tree.nearest_common_ancestor(fr_scope, s_id);
if r_id == fr_scope {
// if the free region's scope `fr.scope` is bigger than
// the scope region `s_id`, then the LUB is the free
// region itself:
match (a, b) {
(_, &ReScope(_)) => return a,
(&ReScope(_), _) => return b,
_ => bug!(),
}
}
// otherwise, we don't know what the free region is,
// so we must conservatively say the LUB is static:
self.tcx().lifetimes.re_static
}
(&ReScope(a_id), &ReScope(b_id)) => {
// The region corresponding to an outer block is a
// subtype of the region corresponding to an inner
// block.
let lub = self.region_rels.region_scope_tree.nearest_common_ancestor(a_id, b_id);
self.tcx().mk_region(ReScope(lub))
}
(&ReEarlyBound(_) | &ReFree(_), &ReEarlyBound(_) | &ReFree(_)) => {
self.region_rels.lub_free_regions(a, b)
}
@ -659,7 +610,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
if !self.sub_concrete_regions(a_region, b_region) {
debug!(
"collect_errors: region error at {:?}: \
cannot verify that {:?}={:?} <= {:?}",
cannot verify that {:?}={:?} <= {:?}",
origin, a_vid, a_region, b_region
);
*a_data = VarValue::ErrorValue;
@ -716,7 +667,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
graph: &RegionGraph<'tcx>,
errors: &mut Vec<RegionResolutionError<'tcx>>,
) {
debug!("collect_var_errors");
debug!("collect_var_errors, var_data = {:#?}", var_data.values);
// This is the best way that I have found to suppress
// duplicate and related errors. Basically we keep a set of
@ -815,10 +766,10 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
) {
// Errors in expanding nodes result from a lower-bound that is
// not contained by an upper-bound.
let (mut lower_bounds, lower_dup) =
self.collect_concrete_regions(graph, node_idx, INCOMING, Some(dup_vec));
let (mut upper_bounds, upper_dup) =
self.collect_concrete_regions(graph, node_idx, OUTGOING, Some(dup_vec));
let (mut lower_bounds, lower_vid_bounds, lower_dup) =
self.collect_bounding_regions(graph, node_idx, INCOMING, Some(dup_vec));
let (mut upper_bounds, _, upper_dup) =
self.collect_bounding_regions(graph, node_idx, OUTGOING, Some(dup_vec));
if lower_dup || upper_dup {
return;
@ -874,15 +825,22 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
// If we have a scenario like `exists<'a> { forall<'b> { 'b:
// 'a } }`, we wind up without any lower-bound -- all we have
// are placeholders as upper bounds, but the universe of the
// variable `'a` doesn't permit those placeholders.
// variable `'a`, or some variable that `'a` has to outlive, doesn't
// permit those placeholders.
let min_universe = lower_vid_bounds
.into_iter()
.map(|vid| self.var_infos[vid].universe)
.min()
.expect("lower_vid_bounds should at least include `node_idx`");
for upper_bound in &upper_bounds {
if let ty::RePlaceholder(p) = upper_bound.region {
if node_universe.cannot_name(p.universe) {
if min_universe.cannot_name(p.universe) {
let origin = self.var_infos[node_idx].origin;
errors.push(RegionResolutionError::UpperBoundUniverseConflict(
node_idx,
origin,
node_universe,
min_universe,
upper_bound.origin.clone(),
upper_bound.region,
));
@ -904,13 +862,24 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
);
}
fn collect_concrete_regions(
/// Collects all regions that "bound" the variable `orig_node_idx` in the
/// given direction.
///
/// If `dup_vec` is `Some` it's used to track duplicates between successive
/// calls of this function.
///
/// The return tuple fields are:
/// - a list of all concrete regions bounding the given region.
/// - the set of all region variables bounding the given region.
/// - a `bool` that's true if the returned region variables overlap with
/// those returned by a previous call for another region.
fn collect_bounding_regions(
&self,
graph: &RegionGraph<'tcx>,
orig_node_idx: RegionVid,
dir: Direction,
mut dup_vec: Option<&mut IndexVec<RegionVid, Option<RegionVid>>>,
) -> (Vec<RegionAndOrigin<'tcx>>, bool) {
) -> (Vec<RegionAndOrigin<'tcx>>, FxHashSet<RegionVid>, bool) {
struct WalkState<'tcx> {
set: FxHashSet<RegionVid>,
stack: Vec<RegionVid>,
@ -929,9 +898,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
// direction specified
process_edges(&self.data, &mut state, graph, orig_node_idx, dir);
while !state.stack.is_empty() {
let node_idx = state.stack.pop().unwrap();
while let Some(node_idx) = state.stack.pop() {
// check whether we've visited this node on some previous walk
if let Some(dup_vec) = &mut dup_vec {
if dup_vec[node_idx].is_none() {
@ -949,8 +916,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
process_edges(&self.data, &mut state, graph, node_idx, dir);
}
let WalkState { result, dup_found, .. } = state;
return (result, dup_found);
let WalkState { result, dup_found, set, .. } = state;
return (result, set, dup_found);
fn process_edges<'tcx>(
this: &RegionConstraintData<'tcx>,

View file

@ -20,7 +20,6 @@ use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues};
use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
use rustc_middle::middle::region;
use rustc_middle::mir;
use rustc_middle::mir::interpret::ConstEvalResult;
use rustc_middle::traits::select;
@ -378,22 +377,6 @@ pub enum SubregionOrigin<'tcx> {
/// Arose from a subtyping relation
Subtype(Box<TypeTrace<'tcx>>),
/// Stack-allocated closures cannot outlive innermost loop
/// or function so as to ensure we only require finite stack
InfStackClosure(Span),
/// Invocation of closure must be within its lifetime
InvokeClosure(Span),
/// Dereference of reference must be within its lifetime
DerefPointer(Span),
/// Closure bound must not outlive captured variables
ClosureCapture(Span, hir::HirId),
/// Index into slice must be within its lifetime
IndexSlice(Span),
/// When casting `&'a T` to an `&'b Trait` object,
/// relating `'a` to `'b`
RelateObjectBound(Span),
@ -406,10 +389,6 @@ pub enum SubregionOrigin<'tcx> {
/// that must outlive some other region.
RelateRegionParamBound(Span),
/// A bound placed on type parameters that states that must outlive
/// the moment of their instantiation.
RelateDefaultParamBound(Span, Ty<'tcx>),
/// Creating a pointer `b` to contents of another reference
Reborrow(Span),
@ -422,36 +401,9 @@ pub enum SubregionOrigin<'tcx> {
/// (&'a &'b T) where a >= b
ReferenceOutlivesReferent(Ty<'tcx>, Span),
/// Type or region parameters must be in scope.
ParameterInScope(ParameterOrigin, Span),
/// The type T of an expression E must outlive the lifetime for E.
ExprTypeIsNotInScope(Ty<'tcx>, Span),
/// A `ref b` whose region does not enclose the decl site
BindingTypeIsNotValidAtDecl(Span),
/// Regions appearing in a method receiver must outlive method call
CallRcvr(Span),
/// Regions appearing in a function argument must outlive func call
CallArg(Span),
/// Region in return type of invoked fn must enclose call
CallReturn(Span),
/// Operands must be in scope
Operand(Span),
/// Region resulting from a `&` expr must enclose the `&` expr
AddrOf(Span),
/// An auto-borrow that does not enclose the expr where it occurs
AutoBorrow(Span),
/// Region constraint arriving from destructor safety
SafeDestructor(Span),
/// Comparing the signature and requirements of an impl method against
/// the containing trait.
CompareImplMethodObligation {
@ -1260,7 +1212,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn resolve_regions_and_report_errors(
&self,
region_context: DefId,
region_map: &region::ScopeTree,
outlives_env: &OutlivesEnvironment<'tcx>,
mode: RegionckMode,
) {
@ -1280,12 +1231,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
.into_infos_and_data()
};
let region_rels = &RegionRelations::new(
self.tcx,
region_context,
region_map,
outlives_env.free_region_map(),
);
let region_rels =
&RegionRelations::new(self.tcx, region_context, outlives_env.free_region_map());
let (lexical_region_resolutions, errors) =
lexical_region_resolve::resolve(region_rels, var_infos, data, mode);
@ -1299,7 +1246,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// this infcx was in use. This is totally hokey but
// otherwise we have a hard time separating legit region
// errors from silly ones.
self.report_region_errors(region_map, &errors);
self.report_region_errors(&errors);
}
}
@ -1809,29 +1756,14 @@ impl<'tcx> SubregionOrigin<'tcx> {
pub fn span(&self) -> Span {
match *self {
Subtype(ref a) => a.span(),
InfStackClosure(a) => a,
InvokeClosure(a) => a,
DerefPointer(a) => a,
ClosureCapture(a, _) => a,
IndexSlice(a) => a,
RelateObjectBound(a) => a,
RelateParamBound(a, _) => a,
RelateRegionParamBound(a) => a,
RelateDefaultParamBound(a, _) => a,
Reborrow(a) => a,
ReborrowUpvar(a, _) => a,
DataBorrowed(_, a) => a,
ReferenceOutlivesReferent(_, a) => a,
ParameterInScope(_, a) => a,
ExprTypeIsNotInScope(_, a) => a,
BindingTypeIsNotValidAtDecl(a) => a,
CallRcvr(a) => a,
CallArg(a) => a,
CallReturn(a) => a,
Operand(a) => a,
AddrOf(a) => a,
AutoBorrow(a) => a,
SafeDestructor(a) => a,
CompareImplMethodObligation { span, .. } => span,
}
}

View file

@ -758,11 +758,9 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
pub fn universe(&self, region: Region<'tcx>) -> ty::UniverseIndex {
match *region {
ty::ReScope(..)
| ty::ReStatic
| ty::ReErased
| ty::ReFree(..)
| ty::ReEarlyBound(..) => ty::UniverseIndex::ROOT,
ty::ReStatic | ty::ReErased | ty::ReFree(..) | ty::ReEarlyBound(..) => {
ty::UniverseIndex::ROOT
}
ty::ReEmpty(ui) => ui,
ty::RePlaceholder(placeholder) => placeholder.universe,
ty::ReVar(vid) => self.var_universe(vid),

View file

@ -87,9 +87,6 @@ impl<'a> HashStable<StableHashingContext<'a>> for ty::RegionKind {
index.hash_stable(hcx, hasher);
name.hash_stable(hcx, hasher);
}
ty::ReScope(scope) => {
scope.hash_stable(hcx, hasher);
}
ty::ReFree(ref free_region) => {
free_region.hash_stable(hcx, hasher);
}

View file

@ -7,7 +7,7 @@
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/borrow_check.html
use crate::ich::{NodeIdHashingMode, StableHashingContext};
use crate::ty::{self, DefIdTree, TyCtxt};
use crate::ty::TyCtxt;
use rustc_hir as hir;
use rustc_hir::Node;
@ -333,7 +333,7 @@ pub struct YieldData {
pub source: hir::YieldSource,
}
impl<'tcx> ScopeTree {
impl ScopeTree {
pub fn record_scope_parent(&mut self, child: Scope, parent: Option<(Scope, ScopeDepth)>) {
debug!("{:?}.parent = {:?}", child, parent);
@ -348,24 +348,6 @@ impl<'tcx> ScopeTree {
}
}
pub fn each_encl_scope<E>(&self, mut e: E)
where
E: FnMut(Scope, Scope),
{
for (&child, &parent) in &self.parent_map {
e(child, parent.0)
}
}
pub fn each_var_scope<E>(&self, mut e: E)
where
E: FnMut(&hir::ItemLocalId, Scope),
{
for (child, &parent) in self.var_map.iter() {
e(child, parent)
}
}
pub fn opt_destruction_scope(&self, n: hir::ItemLocalId) -> Option<Scope> {
self.destruction_scopes.get(&n).cloned()
}
@ -406,12 +388,6 @@ impl<'tcx> ScopeTree {
self.parent_map.get(&id).cloned().map(|(p, _)| p)
}
/// Returns the narrowest scope that encloses `id`, if any.
#[allow(dead_code)] // used in cfg
pub fn encl_scope(&self, id: Scope) -> Scope {
self.opt_encl_scope(id).unwrap()
}
/// Returns the lifetime of the local variable `var_id`
pub fn var_scope(&self, var_id: hir::ItemLocalId) -> Scope {
self.var_map
@ -448,17 +424,6 @@ impl<'tcx> ScopeTree {
None
}
/// Returns the lifetime of the variable `id`.
pub fn var_region(&self, id: hir::ItemLocalId) -> ty::RegionKind {
let scope = ty::ReScope(self.var_scope(id));
debug!("var_region({:?}) = {:?}", id, scope);
scope
}
pub fn scopes_intersect(&self, scope1: Scope, scope2: Scope) -> bool {
self.is_subscope_of(scope1, scope2) || self.is_subscope_of(scope2, scope1)
}
/// Returns `true` if `subscope` is equal to or is lexically nested inside `superscope`, and
/// `false` otherwise.
pub fn is_subscope_of(&self, subscope: Scope, superscope: Scope) -> bool {
@ -479,127 +444,6 @@ impl<'tcx> ScopeTree {
true
}
/// Returns the ID of the innermost containing body.
pub fn containing_body(&self, mut scope: Scope) -> Option<hir::ItemLocalId> {
loop {
if let ScopeData::CallSite = scope.data {
return Some(scope.item_local_id());
}
scope = self.opt_encl_scope(scope)?;
}
}
/// Finds the nearest common ancestor of two scopes. That is, finds the
/// smallest scope which is greater than or equal to both `scope_a` and
/// `scope_b`.
pub fn nearest_common_ancestor(&self, scope_a: Scope, scope_b: Scope) -> Scope {
if scope_a == scope_b {
return scope_a;
}
let mut a = scope_a;
let mut b = scope_b;
// Get the depth of each scope's parent. If either scope has no parent,
// it must be the root, which means we can stop immediately because the
// root must be the nearest common ancestor. (In practice, this is
// moderately common.)
let (parent_a, parent_a_depth) = match self.parent_map.get(&a) {
Some(pd) => *pd,
None => return a,
};
let (parent_b, parent_b_depth) = match self.parent_map.get(&b) {
Some(pd) => *pd,
None => return b,
};
if parent_a_depth > parent_b_depth {
// `a` is lower than `b`. Move `a` up until it's at the same depth
// as `b`. The first move up is trivial because we already found
// `parent_a` above; the loop does the remaining N-1 moves.
a = parent_a;
for _ in 0..(parent_a_depth - parent_b_depth - 1) {
a = self.parent_map.get(&a).unwrap().0;
}
} else if parent_b_depth > parent_a_depth {
// `b` is lower than `a`.
b = parent_b;
for _ in 0..(parent_b_depth - parent_a_depth - 1) {
b = self.parent_map.get(&b).unwrap().0;
}
} else {
// Both scopes are at the same depth, and we know they're not equal
// because that case was tested for at the top of this function. So
// we can trivially move them both up one level now.
assert!(parent_a_depth != 0);
a = parent_a;
b = parent_b;
}
// Now both scopes are at the same level. We move upwards in lockstep
// until they match. In practice, this loop is almost always executed
// zero times because `a` is almost always a direct ancestor of `b` or
// vice versa.
while a != b {
a = self.parent_map.get(&a).unwrap().0;
b = self.parent_map.get(&b).unwrap().0;
}
a
}
/// Assuming that the provided region was defined within this `ScopeTree`,
/// returns the outermost `Scope` that the region outlives.
pub fn early_free_scope(&self, tcx: TyCtxt<'tcx>, br: &ty::EarlyBoundRegion) -> Scope {
let param_owner = tcx.parent(br.def_id).unwrap();
let param_owner_id = tcx.hir().as_local_hir_id(param_owner.expect_local());
let scope = tcx
.hir()
.maybe_body_owned_by(param_owner_id)
.map(|body_id| tcx.hir().body(body_id).value.hir_id.local_id)
.unwrap_or_else(|| {
// The lifetime was defined on node that doesn't own a body,
// which in practice can only mean a trait or an impl, that
// is the parent of a method, and that is enforced below.
if Some(param_owner_id) != self.root_parent {
tcx.sess.delay_span_bug(
DUMMY_SP,
&format!(
"free_scope: {:?} not recognized by the \
region scope tree for {:?} / {:?}",
param_owner,
self.root_parent.map(|id| tcx.hir().local_def_id(id)),
self.root_body.map(|hir_id| hir_id.owner)
),
);
}
// The trait/impl lifetime is in scope for the method's body.
self.root_body.unwrap().local_id
});
Scope { id: scope, data: ScopeData::CallSite }
}
/// Assuming that the provided region was defined within this `ScopeTree`,
/// returns the outermost `Scope` that the region outlives.
pub fn free_scope(&self, tcx: TyCtxt<'tcx>, fr: &ty::FreeRegion) -> Scope {
let param_owner = match fr.bound_region {
ty::BoundRegion::BrNamed(def_id, _) => tcx.parent(def_id).unwrap(),
_ => fr.scope,
};
// Ensure that the named late-bound lifetimes were defined
// on the same function that they ended up being freed in.
assert_eq!(param_owner, fr.scope);
let param_owner_id = tcx.hir().as_local_hir_id(param_owner.expect_local());
let body_id = tcx.hir().body_owned_by(param_owner_id);
Scope { id: tcx.hir().body(body_id).value.hir_id.local_id, data: ScopeData::CallSite }
}
/// Checks whether the given scope contains a `yield`. If so,
/// returns `Some((span, expr_count))` with the span of a yield we found and
/// the number of expressions and patterns appearing before the `yield` in the body + 1.

View file

@ -1,5 +1,4 @@
use crate::middle::cstore::{ExternCrate, ExternCrateSource};
use crate::middle::region;
use crate::mir::interpret::{sign_extend, truncate, AllocId, ConstValue, Pointer, Scalar};
use crate::ty::layout::IntegerExt;
use crate::ty::subst::{GenericArg, GenericArgKind, Subst};
@ -1588,9 +1587,9 @@ impl<F: fmt::Write> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> {
false
}
ty::ReScope(_) | ty::ReVar(_) if identify_regions => true,
ty::ReVar(_) if identify_regions => true,
ty::ReVar(_) | ty::ReScope(_) | ty::ReErased => false,
ty::ReVar(_) | ty::ReErased => false,
ty::ReStatic | ty::ReEmpty(_) => true,
}
@ -1666,32 +1665,12 @@ impl<F: fmt::Write> FmtPrinter<'_, '_, F> {
}
}
}
ty::ReScope(scope) if identify_regions => {
match scope.data {
region::ScopeData::Node => p!(write("'{}s", scope.item_local_id().as_usize())),
region::ScopeData::CallSite => {
p!(write("'{}cs", scope.item_local_id().as_usize()))
}
region::ScopeData::Arguments => {
p!(write("'{}as", scope.item_local_id().as_usize()))
}
region::ScopeData::Destruction => {
p!(write("'{}ds", scope.item_local_id().as_usize()))
}
region::ScopeData::Remainder(first_statement_index) => p!(write(
"'{}_{}rs",
scope.item_local_id().as_usize(),
first_statement_index.index()
)),
}
return Ok(self);
}
ty::ReVar(region_vid) if identify_regions => {
p!(write("{:?}", region_vid));
return Ok(self);
}
ty::ReVar(_) => {}
ty::ReScope(_) | ty::ReErased => {}
ty::ReErased => {}
ty::ReStatic => {
p!(write("'static"));
return Ok(self);

View file

@ -87,8 +87,6 @@ impl fmt::Debug for ty::RegionKind {
ty::ReFree(ref fr) => fr.fmt(f),
ty::ReScope(id) => write!(f, "ReScope({:?})", id),
ty::ReStatic => write!(f, "ReStatic"),
ty::ReVar(ref vid) => vid.fmt(f),

View file

@ -6,7 +6,6 @@ use self::InferTy::*;
use self::TyKind::*;
use crate::infer::canonical::Canonical;
use crate::middle::region;
use crate::mir::interpret::ConstValue;
use crate::mir::interpret::{LitToConstInput, Scalar};
use crate::mir::Promoted;
@ -1179,17 +1178,15 @@ rustc_index::newtype_index! {
pub type Region<'tcx> = &'tcx RegionKind;
/// Representation of (lexical) regions. Note that the NLL checker
/// uses a distinct representation of regions. For this reason, it
/// internally replaces all the regions with inference variables --
/// the index of the variable is then used to index into internal NLL
/// data structures. See `rustc_mir::borrow_check` module for more
/// information.
/// Representation of regions. Note that the NLL checker uses a distinct
/// representation of regions. For this reason, it internally replaces all the
/// regions with inference variables -- the index of the variable is then used
/// to index into internal NLL data structures. See `rustc_mir::borrow_check`
/// module for more information.
///
/// ## The Region lattice within a given function
///
/// In general, the (lexical, and hence deprecated) region lattice
/// looks like
/// In general, the region lattice looks like
///
/// ```
/// static ----------+-----...------+ (greatest)
@ -1197,7 +1194,6 @@ pub type Region<'tcx> = &'tcx RegionKind;
/// early-bound and | |
/// free regions | |
/// | | |
/// scope regions | |
/// | | |
/// empty(root) placeholder(U1) |
/// | / |
@ -1212,13 +1208,7 @@ pub type Region<'tcx> = &'tcx RegionKind;
/// Early-bound/free regions are the named lifetimes in scope from the
/// function declaration. They have relationships to one another
/// determined based on the declared relationships from the
/// function. They all collectively outlive the scope regions. (See
/// `RegionRelations` type, and particularly
/// `crate::infer::outlives::free_region_map::FreeRegionMap`.)
///
/// The scope regions are related to one another based on the AST
/// structure. (See `RegionRelations` type, and particularly the
/// `rustc_middle::middle::region::ScopeTree`.)
/// function.
///
/// Note that inference variables and bound regions are not included
/// in this diagram. In the case of inference variables, they should
@ -1307,11 +1297,6 @@ pub enum RegionKind {
/// region parameters.
ReFree(FreeRegion),
/// A concrete region naming some statically determined scope
/// (e.g., an expression or sequence of statements) within the
/// current function.
ReScope(region::Scope),
/// Static data that has an "infinite" lifetime. Top in the region lattice.
ReStatic,
@ -1535,7 +1520,6 @@ impl RegionKind {
RegionKind::ReEarlyBound(ebr) => ebr.has_name(),
RegionKind::ReLateBound(_, br) => br.is_named(),
RegionKind::ReFree(fr) => fr.bound_region.is_named(),
RegionKind::ReScope(..) => false,
RegionKind::ReStatic => true,
RegionKind::ReVar(..) => false,
RegionKind::RePlaceholder(placeholder) => placeholder.name.is_named(),
@ -1616,7 +1600,7 @@ impl RegionKind {
flags = flags | TypeFlags::HAS_RE_PARAM;
flags = flags | TypeFlags::STILL_FURTHER_SPECIALIZABLE;
}
ty::ReFree { .. } | ty::ReScope { .. } => {
ty::ReFree { .. } => {
flags = flags | TypeFlags::HAS_FREE_REGIONS;
flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
}

View file

@ -162,10 +162,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let type_test_span = type_test.locations.span(&self.body);
if let Some(lower_bound_region) = lower_bound_region {
let region_scope_tree = &self.infcx.tcx.region_scope_tree(self.mir_def_id);
self.infcx
.construct_generic_bound_failure(
region_scope_tree,
type_test_span,
None,
type_test.generic_kind,
@ -194,12 +192,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}
RegionErrorKind::UnexpectedHiddenRegion { span, hidden_ty, member_region } => {
let region_scope_tree = &self.infcx.tcx.region_scope_tree(self.mir_def_id);
let named_ty = self.regioncx.name_regions(self.infcx.tcx, hidden_ty);
let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region);
unexpected_hidden_region_diagnostic(
self.infcx.tcx,
Some(region_scope_tree),
span,
named_ty,
named_region,

View file

@ -284,7 +284,6 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
},
ty::ReLateBound(..)
| ty::ReScope(..)
| ty::ReVar(..)
| ty::RePlaceholder(..)
| ty::ReEmpty(_)

View file

@ -670,7 +670,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
// `least_region`. We cannot use `push_outlives_components` because regions in
// closure signatures are not included in their outlives components. We need to
// ensure all regions outlive the given bound so that we don't end up with,
// say, `ReScope` appearing in a return type and causing ICEs when other
// say, `ReVar` appearing in a return type and causing ICEs when other
// functions end up with region constraints involving regions from other
// functions.
//
@ -816,7 +816,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
// The regions that we expect from borrow checking.
ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReEmpty(ty::UniverseIndex::ROOT) => {}
ty::ReEmpty(_) | ty::RePlaceholder(_) | ty::ReVar(_) | ty::ReScope(_) => {
ty::ReEmpty(_) | ty::RePlaceholder(_) | ty::ReVar(_) => {
// All of the regions in the type should either have been
// erased by writeback, or mapped back to named regions by
// borrow checking.
@ -835,7 +835,6 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> {
if let Some(hidden_ty) = self.hidden_ty.take() {
unexpected_hidden_region_diagnostic(
self.tcx,
None,
self.tcx.def_span(self.opaque_type_def_id),
hidden_ty,
r,

View file

@ -28,7 +28,6 @@ use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
use rustc_errors::ErrorReported;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_middle::middle::region;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
use rustc_middle::ty::{
@ -237,15 +236,12 @@ fn do_normalize_predicates<'tcx>(
debug!("do_normalize_predictes: normalized predicates = {:?}", predicates);
let region_scope_tree = region::ScopeTree::default();
// We can use the `elaborated_env` here; the region code only
// cares about declarations like `'a: 'b`.
let outlives_env = OutlivesEnvironment::new(elaborated_env);
infcx.resolve_regions_and_report_errors(
region_context,
&region_scope_tree,
&outlives_env,
RegionckMode::default(),
);

View file

@ -394,7 +394,6 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Lifetime<RustInterner<'tcx>>> for Region<'t
ty::BrEnv => unimplemented!(),
},
ReFree(_) => unimplemented!(),
ReScope(_) => unimplemented!(),
ReStatic => unimplemented!(),
ReVar(_) => unimplemented!(),
RePlaceholder(placeholder_region) => {

View file

@ -3,7 +3,6 @@
use super::{check_fn, Expectation, FnCtxt, GeneratorTypes};
use crate::astconv::AstConv;
use crate::middle::region;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::{FutureTraitLangItem, GeneratorTraitLangItem};
@ -12,12 +11,11 @@ use rustc_infer::infer::LateBoundRegionConversionTime;
use rustc_infer::infer::{InferOk, InferResult};
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::{self, GenericParamDefKind, ToPredicate, Ty};
use rustc_middle::ty::{self, GenericParamDefKind, Ty};
use rustc_span::source_map::Span;
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits::error_reporting::ArgKind;
use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
use rustc_trait_selection::traits::Obligation;
use std::cmp;
use std::iter;
@ -518,22 +516,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let InferOk { value: (), obligations } =
self.at(&cause, self.param_env).eq(*expected_ty, supplied_ty)?;
all_obligations.extend(obligations);
// Also, require that the supplied type must outlive
// the closure body.
let closure_body_region = self.tcx.mk_region(ty::ReScope(region::Scope {
id: body.value.hir_id.local_id,
data: region::ScopeData::Node,
}));
all_obligations.push(Obligation::new(
cause,
self.param_env,
ty::PredicateKind::TypeOutlives(ty::Binder::dummy(ty::OutlivesPredicate(
supplied_ty,
closure_body_region,
)))
.to_predicate(self.tcx),
));
}
let (supplied_output_ty, _) = self.infcx.replace_bound_vars_with_fresh_vars(

View file

@ -5,7 +5,6 @@ use rustc_errors::{struct_span_err, ErrorReported};
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{InferOk, RegionckMode, TyCtxtInferExt};
use rustc_infer::traits::TraitEngineExt as _;
use rustc_middle::middle::region;
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
use rustc_middle::ty::subst::{Subst, SubstsRef};
@ -120,8 +119,6 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
return Err(ErrorReported);
}
let region_scope_tree = region::ScopeTree::default();
// NB. It seems a bit... suspicious to use an empty param-env
// here. The correct thing, I imagine, would be
// `OutlivesEnvironment::new(impl_param_env)`, which would
@ -134,7 +131,6 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
infcx.resolve_regions_and_report_errors(
drop_impl_did.to_def_id(),
&region_scope_tree,
&outlives_env,
RegionckMode::default(),
);

View file

@ -106,13 +106,13 @@ use rustc_hir::lang_items::{
use rustc_hir::{ExprKind, GenericArg, HirIdMap, Item, ItemKind, Node, PatKind, QPath};
use rustc_index::bit_set::BitSet;
use rustc_index::vec::Idx;
use rustc_infer::infer;
use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
use rustc_infer::infer::{self, InferCtxt, InferOk, InferResult, TyCtxtInferExt};
use rustc_infer::infer::{InferCtxt, InferOk, InferResult, RegionVariableOrigin, TyCtxtInferExt};
use rustc_middle::hir::map::blocks::FnLikeNode;
use rustc_middle::middle::region;
use rustc_middle::mir::interpret::ConstValue;
use rustc_middle::ty::adjustment::{
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast,
@ -667,13 +667,6 @@ impl Inherited<'a, 'tcx> {
let tcx = infcx.tcx;
let item_id = tcx.hir().local_def_id_to_hir_id(def_id);
let body_id = tcx.hir().maybe_body_owned_by(item_id);
let implicit_region_bound = body_id.map(|body_id| {
let body = tcx.hir().body(body_id);
tcx.mk_region(ty::ReScope(region::Scope {
id: body.value.hir_id.local_id,
data: region::ScopeData::CallSite,
}))
});
Inherited {
tables: MaybeInProgressTables { maybe_tables: infcx.in_progress_tables },
@ -686,7 +679,7 @@ impl Inherited<'a, 'tcx> {
deferred_generator_interiors: RefCell::new(Vec::new()),
opaque_types: RefCell::new(Default::default()),
opaque_types_vars: RefCell::new(Default::default()),
implicit_region_bound,
implicit_region_bound: None,
body_id,
}
}
@ -1337,12 +1330,9 @@ fn check_fn<'a, 'tcx>(
// C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
// (as it's created inside the body itself, not passed in from outside).
let maybe_va_list = if fn_sig.c_variadic {
let va_list_did =
tcx.require_lang_item(VaListTypeLangItem, Some(body.params.last().unwrap().span));
let region = tcx.mk_region(ty::ReScope(region::Scope {
id: body.value.hir_id.local_id,
data: region::ScopeData::CallSite,
}));
let span = body.params.last().unwrap().span;
let va_list_did = tcx.require_lang_item(VaListTypeLangItem, Some(span));
let region = fcx.next_region_var(RegionVariableOrigin::MiscVariable(span));
Some(tcx.type_of(va_list_did).subst(tcx, &[region.into()]))
} else {

View file

@ -83,12 +83,10 @@ use rustc_hir::PatKind;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{self, RegionObligation, RegionckMode};
use rustc_middle::ty::adjustment;
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
use rustc_middle::ty::{self, Ty};
use rustc_span::Span;
use rustc_trait_selection::infer::OutlivesEnvironmentExt;
use rustc_trait_selection::opaque_types::InferCtxtExt;
use std::mem;
use std::ops::Deref;
// a variation on try that just returns unit
@ -111,8 +109,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn regionck_expr(&self, body: &'tcx hir::Body<'tcx>) {
let subject = self.tcx.hir().body_owner_def_id(body.id());
let id = body.value.hir_id;
let mut rcx =
RegionCtxt::new(self, RepeatingScope(id), id, Subject(subject), self.param_env);
let mut rcx = RegionCtxt::new(self, id, Subject(subject), self.param_env);
// There are no add'l implied bounds when checking a
// standalone expr (e.g., the `E` in a type like `[u32; E]`).
@ -131,13 +128,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn regionck_item(&self, item_id: hir::HirId, span: Span, wf_tys: &[Ty<'tcx>]) {
debug!("regionck_item(item.id={:?}, wf_tys={:?})", item_id, wf_tys);
let subject = self.tcx.hir().local_def_id(item_id);
let mut rcx = RegionCtxt::new(
self,
RepeatingScope(item_id),
item_id,
Subject(subject),
self.param_env,
);
let mut rcx = RegionCtxt::new(self, item_id, Subject(subject), self.param_env);
rcx.outlives_environment.add_implied_bounds(self, wf_tys, item_id, span);
rcx.outlives_environment.save_implied_bounds(item_id);
rcx.visit_region_obligations(item_id);
@ -156,8 +147,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!("regionck_fn(id={})", fn_id);
let subject = self.tcx.hir().body_owner_def_id(body.id());
let hir_id = body.value.hir_id;
let mut rcx =
RegionCtxt::new(self, RepeatingScope(hir_id), hir_id, Subject(subject), self.param_env);
let mut rcx = RegionCtxt::new(self, hir_id, Subject(subject), self.param_env);
if !self.errors_reported_since_creation() {
// regionck assumes typeck succeeded
@ -182,12 +172,6 @@ pub struct RegionCtxt<'a, 'tcx> {
body_id: hir::HirId,
body_owner: LocalDefId,
// call_site scope of innermost fn
call_site_scope: Option<region::Scope>,
// id of innermost fn or loop
repeating_scope: hir::HirId,
// id of AST node being analyzed (the subject of the analysis).
subject_def_id: LocalDefId,
}
@ -199,13 +183,11 @@ impl<'a, 'tcx> Deref for RegionCtxt<'a, 'tcx> {
}
}
pub struct RepeatingScope(hir::HirId);
pub struct Subject(LocalDefId);
impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
pub fn new(
fcx: &'a FnCtxt<'a, 'tcx>,
RepeatingScope(initial_repeating_scope): RepeatingScope,
initial_body_id: hir::HirId,
Subject(subject): Subject,
param_env: ty::ParamEnv<'tcx>,
@ -215,19 +197,13 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
RegionCtxt {
fcx,
region_scope_tree,
repeating_scope: initial_repeating_scope,
body_id: initial_body_id,
body_owner: subject,
call_site_scope: None,
subject_def_id: subject,
outlives_environment,
}
}
fn set_repeating_scope(&mut self, scope: hir::HirId) -> hir::HirId {
mem::replace(&mut self.repeating_scope, scope)
}
/// Try to resolve the type for the given node, returning `t_err` if an error results. Note that
/// we never care about the details of the error, the same error will be detected and reported
/// in the writeback phase.
@ -261,16 +237,10 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
self.resolve_type(t)
}
/// Try to resolve the type for the given node.
pub fn resolve_expr_type_adjusted(&mut self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
let ty = self.tables.borrow().expr_ty_adjusted(expr);
self.resolve_type(ty)
}
/// This is the "main" function when region-checking a function item or a closure
/// within a function item. It begins by updating various fields (e.g., `call_site_scope`
/// and `outlives_environment`) to be appropriate to the function and then adds constraints
/// derived from the function body.
/// This is the "main" function when region-checking a function item or a
/// closure within a function item. It begins by updating various fields
/// (e.g., `outlives_environment`) to be appropriate to the function and
/// then adds constraints derived from the function body.
///
/// Note that it does **not** restore the state of the fields that
/// it updates! This is intentional, since -- for the main
@ -292,10 +262,6 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
self.body_id = body_id.hir_id;
self.body_owner = self.tcx.hir().body_owner_def_id(body_id);
let call_site =
region::Scope { id: body.value.hir_id.local_id, data: region::ScopeData::CallSite };
self.call_site_scope = Some(call_site);
let fn_sig = {
match self.tables.borrow().liberated_fn_sigs().get(id) {
Some(f) => *f,
@ -324,12 +290,6 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
self.visit_body(body);
self.visit_region_obligations(body_id.hir_id);
let call_site_scope = self.call_site_scope.unwrap();
debug!("visit_fn_body body.id {:?} call_site_scope: {:?}", body.id(), call_site_scope);
let call_site_region = self.tcx.mk_region(ty::ReScope(call_site_scope));
self.type_of_node_must_outlive(infer::CallReturn(span), body_id.hir_id, call_site_region);
self.constrain_opaque_types(
&self.fcx.opaque_types.borrow(),
self.outlives_environment.free_region_map(),
@ -354,7 +314,6 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
self.fcx.resolve_regions_and_report_errors(
self.subject_def_id.to_def_id(),
&self.region_scope_tree,
&self.outlives_environment,
mode,
);
@ -363,34 +322,6 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
fn constrain_bindings_in_pat(&mut self, pat: &hir::Pat<'_>) {
debug!("regionck::visit_pat(pat={:?})", pat);
pat.each_binding(|_, hir_id, span, _| {
// If we have a variable that contains region'd data, that
// data will be accessible from anywhere that the variable is
// accessed. We must be wary of loops like this:
//
// // from src/test/compile-fail/borrowck-lend-flow.rs
// let mut v = box 3, w = box 4;
// let mut x = &mut w;
// loop {
// **x += 1; // (2)
// borrow(v); //~ ERROR cannot borrow
// x = &mut v; // (1)
// }
//
// Typically, we try to determine the region of a borrow from
// those points where it is dereferenced. In this case, one
// might imagine that the lifetime of `x` need only be the
// body of the loop. But of course this is incorrect because
// the pointer that is created at point (1) is consumed at
// point (2), meaning that it must be live across the loop
// iteration. The easiest way to guarantee this is to require
// that the lifetime of any regions that appear in a
// variable's type enclose at least the variable's scope.
let var_scope = self.region_scope_tree.var_scope(hir_id.local_id);
let var_region = self.tcx.mk_region(ty::ReScope(var_scope));
let origin = infer::BindingTypeIsNotValidAtDecl(span);
self.type_of_node_must_outlive(origin, hir_id, var_region);
let typ = self.resolve_node_type(hir_id);
let body_id = self.body_id;
let _ = dropck::check_drop_obligations(self, typ, span, body_id);
@ -433,7 +364,6 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionCtxt<'a, 'tcx> {
// `visit_fn_body`. We will restore afterwards.
let old_body_id = self.body_id;
let old_body_owner = self.body_owner;
let old_call_site_scope = self.call_site_scope;
let env_snapshot = self.outlives_environment.push_snapshot_pre_closure();
let body = self.tcx.hir().body(body_id);
@ -441,7 +371,6 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionCtxt<'a, 'tcx> {
// Restore state from previous function.
self.outlives_environment.pop_snapshot_post_closure(env_snapshot);
self.call_site_scope = old_call_site_scope;
self.body_id = old_body_id;
self.body_owner = old_body_owner;
}
@ -462,42 +391,6 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionCtxt<'a, 'tcx> {
}
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
debug!("regionck::visit_expr(e={:?}, repeating_scope={:?})", expr, self.repeating_scope);
// No matter what, the type of each expression must outlive the
// scope of that expression. This also guarantees basic WF.
let expr_ty = self.resolve_node_type(expr.hir_id);
// the region corresponding to this expression
let expr_region = self.tcx.mk_region(ty::ReScope(region::Scope {
id: expr.hir_id.local_id,
data: region::ScopeData::Node,
}));
self.type_must_outlive(
infer::ExprTypeIsNotInScope(expr_ty, expr.span),
expr_ty,
expr_region,
);
let is_method_call = self.tables.borrow().is_method_call(expr);
// If we are calling a method (either explicitly or via an
// overloaded operator), check that all of the types provided as
// arguments for its type parameters are well-formed, and all the regions
// provided as arguments outlive the call.
if is_method_call {
let origin = match expr.kind {
hir::ExprKind::MethodCall(..) => infer::ParameterOrigin::MethodCall,
hir::ExprKind::Unary(op, _) if op == hir::UnOp::UnDeref => {
infer::ParameterOrigin::OverloadedDeref
}
_ => infer::ParameterOrigin::OverloadedOperator,
};
let substs = self.tables.borrow().node_substs(expr.hir_id);
self.substs_wf_in_scope(origin, substs, expr.span, expr_region);
// Arguments (sub-expressions) are checked via `constrain_call`, below.
}
// Check any autoderefs or autorefs that appear.
let cmt_result = self.constrain_adjustments(expr);
@ -512,117 +405,10 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionCtxt<'a, 'tcx> {
}
}
debug!(
"regionck::visit_expr(e={:?}, repeating_scope={:?}) - visiting subexprs",
expr, self.repeating_scope
);
match expr.kind {
hir::ExprKind::Path(_) => {
let substs = self.tables.borrow().node_substs(expr.hir_id);
let origin = infer::ParameterOrigin::Path;
self.substs_wf_in_scope(origin, substs, expr.span, expr_region);
}
hir::ExprKind::Call(ref callee, ref args) => {
if is_method_call {
self.constrain_call(expr, Some(&callee), args.iter().map(|e| &*e));
} else {
self.constrain_callee(&callee);
self.constrain_call(expr, None, args.iter().map(|e| &*e));
}
intravisit::walk_expr(self, expr);
}
hir::ExprKind::MethodCall(.., ref args) => {
self.constrain_call(expr, Some(&args[0]), args[1..].iter().map(|e| &*e));
intravisit::walk_expr(self, expr);
}
hir::ExprKind::AssignOp(_, ref lhs, ref rhs) => {
if is_method_call {
self.constrain_call(expr, Some(&lhs), Some(&**rhs).into_iter());
}
intravisit::walk_expr(self, expr);
}
hir::ExprKind::Index(ref lhs, ref rhs) if is_method_call => {
self.constrain_call(expr, Some(&lhs), Some(&**rhs).into_iter());
intravisit::walk_expr(self, expr);
}
hir::ExprKind::Binary(_, ref lhs, ref rhs) if is_method_call => {
// As `ExprKind::MethodCall`, but the call is via an overloaded op.
self.constrain_call(expr, Some(&lhs), Some(&**rhs).into_iter());
intravisit::walk_expr(self, expr);
}
hir::ExprKind::Binary(_, ref lhs, ref rhs) => {
// If you do `x OP y`, then the types of `x` and `y` must
// outlive the operation you are performing.
let lhs_ty = self.resolve_expr_type_adjusted(&lhs);
let rhs_ty = self.resolve_expr_type_adjusted(&rhs);
for &ty in &[lhs_ty, rhs_ty] {
self.type_must_outlive(infer::Operand(expr.span), ty, expr_region);
}
intravisit::walk_expr(self, expr);
}
hir::ExprKind::Unary(hir::UnOp::UnDeref, ref base) => {
// For *a, the lifetime of a must enclose the deref
if is_method_call {
self.constrain_call(expr, Some(base), None::<hir::Expr<'_>>.iter());
}
// For overloaded derefs, base_ty is the input to `Deref::deref`,
// but it's a reference type uing the same region as the output.
let base_ty = self.resolve_expr_type_adjusted(base);
if let ty::Ref(r_ptr, _, _) = base_ty.kind {
self.mk_subregion_due_to_dereference(expr.span, expr_region, r_ptr);
}
intravisit::walk_expr(self, expr);
}
hir::ExprKind::Unary(_, ref lhs) if is_method_call => {
// As above.
self.constrain_call(expr, Some(&lhs), None::<hir::Expr<'_>>.iter());
intravisit::walk_expr(self, expr);
}
hir::ExprKind::Index(ref vec_expr, _) => {
// For a[b], the lifetime of a must enclose the deref
let vec_type = self.resolve_expr_type_adjusted(&vec_expr);
self.constrain_index(expr, vec_type);
intravisit::walk_expr(self, expr);
}
hir::ExprKind::Cast(ref source, _) => {
// Determine if we are casting `source` to a trait
// instance. If so, we have to be sure that the type of
// the source obeys the trait's region bound.
self.constrain_cast(expr, &source);
intravisit::walk_expr(self, expr);
}
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, m, ref base) => {
self.link_addr_of(expr, m, &base);
// Require that when you write a `&expr` expression, the
// resulting pointer has a lifetime that encompasses the
// `&expr` expression itself. Note that we constraining
// the type of the node expr.id here *before applying
// adjustments*.
//
// FIXME(https://github.com/rust-lang/rfcs/issues/811)
// nested method calls requires that this rule change
let ty0 = self.resolve_node_type(expr.hir_id);
self.type_must_outlive(infer::AddrOf(expr.span), ty0, expr_region);
intravisit::walk_expr(self, expr);
}
@ -632,140 +418,12 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionCtxt<'a, 'tcx> {
intravisit::walk_expr(self, expr);
}
hir::ExprKind::Closure(.., body_id, _, _) => {
self.check_expr_fn_block(expr, body_id);
}
hir::ExprKind::Loop(ref body, _, _) => {
let repeating_scope = self.set_repeating_scope(body.hir_id);
intravisit::walk_expr(self, expr);
self.set_repeating_scope(repeating_scope);
}
hir::ExprKind::Ret(Some(ref ret_expr)) => {
let call_site_scope = self.call_site_scope;
debug!(
"visit_expr ExprKind::Ret ret_expr.hir_id {} call_site_scope: {:?}",
ret_expr.hir_id, call_site_scope
);
let call_site_region = self.tcx.mk_region(ty::ReScope(call_site_scope.unwrap()));
self.type_of_node_must_outlive(
infer::CallReturn(ret_expr.span),
ret_expr.hir_id,
call_site_region,
);
intravisit::walk_expr(self, expr);
}
_ => {
intravisit::walk_expr(self, expr);
}
_ => intravisit::walk_expr(self, expr),
}
}
}
impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
fn constrain_cast(&mut self, cast_expr: &hir::Expr<'_>, source_expr: &hir::Expr<'_>) {
debug!("constrain_cast(cast_expr={:?}, source_expr={:?})", cast_expr, source_expr);
let source_ty = self.resolve_node_type(source_expr.hir_id);
let target_ty = self.resolve_node_type(cast_expr.hir_id);
self.walk_cast(cast_expr, source_ty, target_ty);
}
fn walk_cast(&mut self, cast_expr: &hir::Expr<'_>, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) {
debug!("walk_cast(from_ty={:?}, to_ty={:?})", from_ty, to_ty);
match (&from_ty.kind, &to_ty.kind) {
/*From:*/
(&ty::Ref(from_r, from_ty, _), /*To: */ &ty::Ref(to_r, to_ty, _)) => {
// Target cannot outlive source, naturally.
self.sub_regions(infer::Reborrow(cast_expr.span), to_r, from_r);
self.walk_cast(cast_expr, from_ty, to_ty);
}
/*From:*/
(_, /*To: */ &ty::Dynamic(.., r)) => {
// When T is existentially quantified as a trait
// `Foo+'to`, it must outlive the region bound `'to`.
self.type_must_outlive(infer::RelateObjectBound(cast_expr.span), from_ty, r);
}
/*From:*/
(&ty::Adt(from_def, _), /*To: */ &ty::Adt(to_def, _))
if from_def.is_box() && to_def.is_box() =>
{
self.walk_cast(cast_expr, from_ty.boxed_ty(), to_ty.boxed_ty());
}
_ => {}
}
}
fn check_expr_fn_block(&mut self, expr: &'tcx hir::Expr<'tcx>, body_id: hir::BodyId) {
let repeating_scope = self.set_repeating_scope(body_id.hir_id);
intravisit::walk_expr(self, expr);
self.set_repeating_scope(repeating_scope);
}
fn constrain_callee(&mut self, callee_expr: &hir::Expr<'_>) {
let callee_ty = self.resolve_node_type(callee_expr.hir_id);
match callee_ty.kind {
ty::FnDef(..) | ty::FnPtr(_) => {}
_ => {
// this should not happen, but it does if the program is
// erroneous
//
// bug!(
// callee_expr.span,
// "Calling non-function: {}",
// callee_ty);
}
}
}
fn constrain_call<'b, I: Iterator<Item = &'b hir::Expr<'b>>>(
&mut self,
call_expr: &hir::Expr<'_>,
receiver: Option<&hir::Expr<'_>>,
arg_exprs: I,
) {
//! Invoked on every call site (i.e., normal calls, method calls,
//! and overloaded operators). Constrains the regions which appear
//! in the type of the function. Also constrains the regions that
//! appear in the arguments appropriately.
debug!("constrain_call(call_expr={:?}, receiver={:?})", call_expr, receiver);
// `callee_region` is the scope representing the time in which the
// call occurs.
//
// FIXME(#6268) to support nested method calls, should be callee_id
let callee_scope =
region::Scope { id: call_expr.hir_id.local_id, data: region::ScopeData::Node };
let callee_region = self.tcx.mk_region(ty::ReScope(callee_scope));
debug!("callee_region={:?}", callee_region);
for arg_expr in arg_exprs {
debug!("argument: {:?}", arg_expr);
// ensure that any regions appearing in the argument type are
// valid for at least the lifetime of the function:
self.type_of_node_must_outlive(
infer::CallArg(arg_expr.span),
arg_expr.hir_id,
callee_region,
);
}
// as loop above, but for receiver
if let Some(r) = receiver {
debug!("receiver: {:?}", r);
self.type_of_node_must_outlive(infer::CallRcvr(r.span), r.hir_id, callee_region);
}
}
/// Creates a temporary `MemCategorizationContext` and pass it to the closure.
fn with_mc<F, R>(&self, f: F) -> R
where
@ -784,79 +442,40 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
fn constrain_adjustments(&mut self, expr: &hir::Expr<'_>) -> mc::McResult<mc::Place<'tcx>> {
debug!("constrain_adjustments(expr={:?})", expr);
let mut cmt = self.with_mc(|mc| mc.cat_expr_unadjusted(expr))?;
let mut place = self.with_mc(|mc| mc.cat_expr_unadjusted(expr))?;
let tables = self.tables.borrow();
let adjustments = tables.expr_adjustments(&expr);
if adjustments.is_empty() {
return Ok(cmt);
return Ok(place);
}
debug!("constrain_adjustments: adjustments={:?}", adjustments);
// If necessary, constrain destructors in the unadjusted form of this
// expression.
self.check_safety_of_rvalue_destructor_if_necessary(&cmt, expr.span);
self.check_safety_of_rvalue_destructor_if_necessary(&place, expr.span);
let expr_region = self.tcx.mk_region(ty::ReScope(region::Scope {
id: expr.hir_id.local_id,
data: region::ScopeData::Node,
}));
for adjustment in adjustments {
debug!("constrain_adjustments: adjustment={:?}, cmt={:?}", adjustment, cmt);
debug!("constrain_adjustments: adjustment={:?}, place={:?}", adjustment, place);
if let adjustment::Adjust::Deref(Some(deref)) = adjustment.kind {
debug!("constrain_adjustments: overloaded deref: {:?}", deref);
// Treat overloaded autoderefs as if an AutoBorrow adjustment
// was applied on the base type, as that is always the case.
let input = self
.tcx
.mk_ref(deref.region, ty::TypeAndMut { ty: cmt.ty, mutbl: deref.mutbl });
let output = self.tcx.mk_ref(
deref.region,
ty::TypeAndMut { ty: adjustment.target, mutbl: deref.mutbl },
);
self.link_region(
expr.span,
deref.region,
ty::BorrowKind::from_mutbl(deref.mutbl),
&cmt,
&place,
);
// Specialized version of constrain_call.
self.type_must_outlive(infer::CallRcvr(expr.span), input, expr_region);
self.type_must_outlive(infer::CallReturn(expr.span), output, expr_region);
}
if let adjustment::Adjust::Borrow(ref autoref) = adjustment.kind {
self.link_autoref(expr, &cmt, autoref);
// Require that the resulting region encompasses
// the current node.
//
// FIXME(#6268) remove to support nested method calls
self.type_of_node_must_outlive(
infer::AutoBorrow(expr.span),
expr.hir_id,
expr_region,
);
self.link_autoref(expr, &place, autoref);
}
cmt = self.with_mc(|mc| mc.cat_expr_adjusted(expr, cmt, &adjustment))?;
place = self.with_mc(|mc| mc.cat_expr_adjusted(expr, place, &adjustment))?;
}
Ok(cmt)
}
pub fn mk_subregion_due_to_dereference(
&mut self,
deref_span: Span,
minimum_lifetime: ty::Region<'tcx>,
maximum_lifetime: ty::Region<'tcx>,
) {
self.sub_regions(infer::DerefPointer(deref_span), minimum_lifetime, maximum_lifetime)
Ok(place)
}
fn check_safety_of_rvalue_destructor_if_necessary(
@ -872,59 +491,6 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
}
}
}
/// Invoked on any index expression that occurs. Checks that if this is a slice
/// being indexed, the lifetime of the pointer includes the deref expr.
fn constrain_index(&mut self, index_expr: &hir::Expr<'_>, indexed_ty: Ty<'tcx>) {
debug!("constrain_index(index_expr=?, indexed_ty={}", self.ty_to_string(indexed_ty));
let r_index_expr = ty::ReScope(region::Scope {
id: index_expr.hir_id.local_id,
data: region::ScopeData::Node,
});
if let ty::Ref(r_ptr, r_ty, _) = indexed_ty.kind {
match r_ty.kind {
ty::Slice(_) | ty::Str => {
self.sub_regions(
infer::IndexSlice(index_expr.span),
self.tcx.mk_region(r_index_expr),
r_ptr,
);
}
_ => {}
}
}
}
/// Guarantees that any lifetimes that appear in the type of the node `id` (after applying
/// adjustments) are valid for at least `minimum_lifetime`.
fn type_of_node_must_outlive(
&mut self,
origin: infer::SubregionOrigin<'tcx>,
hir_id: hir::HirId,
minimum_lifetime: ty::Region<'tcx>,
) {
// Try to resolve the type. If we encounter an error, then typeck
// is going to fail anyway, so just stop here and let typeck
// report errors later on in the writeback phase.
let ty0 = self.resolve_node_type(hir_id);
let ty = self
.tables
.borrow()
.adjustments()
.get(hir_id)
.and_then(|adj| adj.last())
.map_or(ty0, |adj| adj.target);
let ty = self.resolve_type(ty);
debug!(
"constrain_regions_in_type_of_node(\
ty={}, ty0={}, id={:?}, minimum_lifetime={:?})",
ty, ty0, hir_id, minimum_lifetime
);
self.type_must_outlive(origin, ty, minimum_lifetime);
}
/// Adds constraints to inference such that `T: 'a` holds (or
/// reports an error if it cannot).
///
@ -1035,13 +601,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
self.link_region(expr.span, r, ty::BorrowKind::from_mutbl(m.into()), expr_cmt);
}
adjustment::AutoBorrow::RawPtr(m) => {
let r = self.tcx.mk_region(ty::ReScope(region::Scope {
id: expr.hir_id.local_id,
data: region::ScopeData::Node,
}));
self.link_region(expr.span, r, ty::BorrowKind::from_mutbl(m), expr_cmt);
}
adjustment::AutoBorrow::RawPtr(_) => {}
}
}
@ -1251,39 +811,4 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
}
}
}
/// Checks that the values provided for type/region arguments in a given
/// expression are well-formed and in-scope.
fn substs_wf_in_scope(
&mut self,
origin: infer::ParameterOrigin,
substs: SubstsRef<'tcx>,
expr_span: Span,
expr_region: ty::Region<'tcx>,
) {
debug!(
"substs_wf_in_scope(substs={:?}, \
expr_region={:?}, \
origin={:?}, \
expr_span={:?})",
substs, expr_region, origin, expr_span
);
let origin = infer::ParameterInScope(origin, expr_span);
for kind in substs {
match kind.unpack() {
GenericArgKind::Lifetime(lt) => {
self.sub_regions(origin.clone(), expr_region, lt);
}
GenericArgKind::Type(ty) => {
let ty = self.resolve_type(ty);
self.type_must_outlive(origin.clone(), ty, expr_region);
}
GenericArgKind::Const(_) => {
// Const parameters don't impose constraints.
}
}
}
}
}

View file

@ -11,7 +11,6 @@ use rustc_hir::ItemKind;
use rustc_infer::infer;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{RegionckMode, TyCtxtInferExt};
use rustc_middle::middle::region;
use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
use rustc_middle::ty::TypeFoldable;
use rustc_middle::ty::{self, Ty, TyCtxt};
@ -293,11 +292,9 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
}
// Finally, resolve all regions.
let region_scope_tree = region::ScopeTree::default();
let outlives_env = OutlivesEnvironment::new(param_env);
infcx.resolve_regions_and_report_errors(
impl_did.to_def_id(),
&region_scope_tree,
&outlives_env,
RegionckMode::default(),
);
@ -552,14 +549,8 @@ pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedI
}
// Finally, resolve all regions.
let region_scope_tree = region::ScopeTree::default();
let outlives_env = OutlivesEnvironment::new(param_env);
infcx.resolve_regions_and_report_errors(
impl_did,
&region_scope_tree,
&outlives_env,
RegionckMode::default(),
);
infcx.resolve_regions_and_report_errors(impl_did, &outlives_env, RegionckMode::default());
CoerceUnsizedInfo { custom_kind: kind }
})

View file

@ -73,7 +73,6 @@ use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{InferCtxt, RegionckMode, TyCtxtInferExt};
use rustc_infer::traits::specialization_graph::Node;
use rustc_middle::middle::region::ScopeTree;
use rustc_middle::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
use rustc_middle::ty::trait_def::TraitSpecializationKind;
use rustc_middle::ty::{self, InstantiatedPredicates, TyCtxt, TypeFoldable};
@ -165,12 +164,7 @@ fn get_impl_substs<'tcx>(
// Conservatively use an empty `ParamEnv`.
let outlives_env = OutlivesEnvironment::new(ty::ParamEnv::empty());
infcx.resolve_regions_and_report_errors(
impl1_def_id,
&ScopeTree::default(),
&outlives_env,
RegionckMode::default(),
);
infcx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env, RegionckMode::default());
let impl2_substs = match infcx.fully_resolve(&impl2_substs) {
Ok(s) => s,
Err(_) => {

View file

@ -170,7 +170,6 @@ fn is_free_region(tcx: TyCtxt<'_>, region: Region<'_>) -> bool {
// These regions don't appear in types from type declarations:
RegionKind::ReErased
| RegionKind::ReScope(..)
| RegionKind::ReVar(..)
| RegionKind::RePlaceholder(..)
| RegionKind::ReFree(..) => {

View file

@ -444,7 +444,6 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
}
ty::ReFree(..)
| ty::ReScope(..)
| ty::ReVar(..)
| ty::RePlaceholder(..)
| ty::ReEmpty(_)

View file

@ -447,7 +447,6 @@ impl Clean<Option<Lifetime>> for ty::RegionKind {
ty::ReLateBound(..)
| ty::ReFree(..)
| ty::ReScope(..)
| ty::ReVar(..)
| ty::RePlaceholder(..)
| ty::ReEmpty(_)

View file

@ -1,12 +0,0 @@
error: borrowed data cannot be stored outside of its closure
--> $DIR/issue-45983.rs:20:27
|
LL | let x = None;
| - borrowed data cannot be stored into here...
LL | give_any(|y| x = Some(y));
| --- ^ cannot be stored outside of its closure
| |
| ...because it cannot outlive this closure
error: aborting due to previous error

View file

@ -1,21 +0,0 @@
error[E0521]: borrowed data escapes outside of closure
--> $DIR/issue-45983.rs:20:18
|
LL | let x = None;
| - `x` declared here, outside of the closure body
LL | give_any(|y| x = Some(y));
| - ^^^^^^^^^^^ `y` escapes the closure body here
| |
| `y` is a reference that is only valid in the closure body
error[E0594]: cannot assign to `x`, as it is not declared as mutable
--> $DIR/issue-45983.rs:20:18
|
LL | let x = None;
| - help: consider changing this to be mutable: `mut x`
LL | give_any(|y| x = Some(y));
| ^^^^^^^^^^^ cannot assign
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0594`.

View file

@ -1,24 +1,12 @@
// As documented in Issue #45983, this test is evaluating the quality
// of our diagnostics on erroneous code using higher-ranked closures.
// revisions: migrate nll
// Since we are testing nll (and migration) explicitly as a separate
// revisions, don't worry about the --compare-mode=nll on this test.
// ignore-compare-mode-nll
// ignore-compare-mode-polonius
//[nll]compile-flags: -Z borrowck=mir
fn give_any<F: for<'r> FnOnce(&'r ())>(f: F) {
f(&());
}
fn main() {
let x = None;
let mut x = None;
give_any(|y| x = Some(y));
//[migrate]~^ ERROR borrowed data cannot be stored outside of its closure
//[nll]~^^ ERROR borrowed data escapes outside of closure
//[nll]~| ERROR cannot assign to `x`, as it is not declared as mutable
//~^ ERROR borrowed data escapes outside of closure
}

View file

@ -1,9 +1,9 @@
error[E0521]: borrowed data escapes outside of closure
--> $DIR/regions-escape-bound-fn-2.rs:8:18
--> $DIR/issue-45983.rs:10:18
|
LL | let mut x = None;
| ----- `x` declared here, outside of the closure body
LL | with_int(|y| x = Some(y));
LL | give_any(|y| x = Some(y));
| - ^^^^^^^^^^^ `y` escapes the closure body here
| |
| `y` is a reference that is only valid in the closure body

View file

@ -1,14 +0,0 @@
error[E0521]: borrowed data escapes outside of closure
--> $DIR/issue-7573.rs:21:9
|
LL | let mut lines_to_use: Vec<&CrateId> = Vec::new();
| ---------------- `lines_to_use` declared here, outside of the closure body
LL |
LL | let push_id = |installed_id: &CrateId| {
| ------------ `installed_id` is a reference that is only valid in the closure body
...
LL | lines_to_use.push(installed_id);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `installed_id` escapes the closure body here
error: aborting due to previous error

View file

@ -1,36 +1,34 @@
pub struct CrateId {
local_path: String,
junk: String
junk: String,
}
impl CrateId {
fn new(s: &str) -> CrateId {
CrateId {
local_path: s.to_string(),
junk: "wutevs".to_string()
}
CrateId { local_path: s.to_string(), junk: "wutevs".to_string() }
}
}
pub fn remove_package_from_database() {
let mut lines_to_use: Vec<&CrateId> = Vec::new();
//~^ NOTE cannot infer an appropriate lifetime
//~^ NOTE `lines_to_use` declared here, outside of the closure body
let push_id = |installed_id: &CrateId| {
//~^ NOTE borrowed data cannot outlive this closure
//~| NOTE ...so that variable is valid at time of its declaration
//~^ NOTE `installed_id` is a reference that is only valid in the closure body
lines_to_use.push(installed_id);
//~^ ERROR borrowed data cannot be stored outside of its closure
//~| NOTE cannot be stored outside of its closure
//~^ ERROR borrowed data escapes outside of closure
//~| NOTE `installed_id` escapes the closure body here
};
list_database(push_id);
for l in &lines_to_use {
println!("{}", l.local_path);
}
}
pub fn list_database<F>(mut f: F) where F: FnMut(&CrateId) {
pub fn list_database<F>(mut f: F)
where
F: FnMut(&CrateId),
{
let stuff = ["foo", "bar"];
for l in &stuff {

View file

@ -1,16 +1,14 @@
error: borrowed data cannot be stored outside of its closure
--> $DIR/issue-7573.rs:21:27
error[E0521]: borrowed data escapes outside of closure
--> $DIR/issue-7573.rs:17:9
|
LL | let mut lines_to_use: Vec<&CrateId> = Vec::new();
| - cannot infer an appropriate lifetime...
| ---------------- `lines_to_use` declared here, outside of the closure body
LL |
LL | let push_id = |installed_id: &CrateId| {
| ------- ------------------------ borrowed data cannot outlive this closure
| |
| ...so that variable is valid at time of its declaration
...
| ------------ `installed_id` is a reference that is only valid in the closure body
LL |
LL | lines_to_use.push(installed_id);
| ^^^^^^^^^^^^ cannot be stored outside of its closure
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `installed_id` escapes the closure body here
error: aborting due to previous error

View file

@ -1,4 +1,7 @@
fn with_int<F>(f: F) where F: FnOnce(&isize) {
fn with_int<F>(f: F)
where
F: FnOnce(&isize),
{
let x = 3;
f(&x);
}
@ -6,5 +9,5 @@ fn with_int<F>(f: F) where F: FnOnce(&isize) {
fn main() {
let mut x = None;
with_int(|y| x = Some(y));
//~^ ERROR borrowed data cannot be stored outside of its closure
//~^ ERROR borrowed data escapes outside of closure
}

View file

@ -1,12 +1,12 @@
error: borrowed data cannot be stored outside of its closure
--> $DIR/regions-escape-bound-fn-2.rs:8:27
error[E0521]: borrowed data escapes outside of closure
--> $DIR/regions-escape-bound-fn-2.rs:11:18
|
LL | let mut x = None;
| ----- borrowed data cannot be stored into here...
| ----- `x` declared here, outside of the closure body
LL | with_int(|y| x = Some(y));
| --- ^ cannot be stored outside of its closure
| |
| ...because it cannot outlive this closure
| - ^^^^^^^^^^^ `y` escapes the closure body here
| |
| `y` is a reference that is only valid in the closure body
error: aborting due to previous error

View file

@ -1,12 +0,0 @@
error[E0521]: borrowed data escapes outside of closure
--> $DIR/regions-escape-bound-fn.rs:8:18
|
LL | let mut x: Option<&isize> = None;
| ----- `x` declared here, outside of the closure body
LL | with_int(|y| x = Some(y));
| - ^^^^^^^^^^^ `y` escapes the closure body here
| |
| `y` is a reference that is only valid in the closure body
error: aborting due to previous error

View file

@ -1,4 +1,7 @@
fn with_int<F>(f: F) where F: FnOnce(&isize) {
fn with_int<F>(f: F)
where
F: FnOnce(&isize),
{
let x = 3;
f(&x);
}
@ -6,5 +9,5 @@ fn with_int<F>(f: F) where F: FnOnce(&isize) {
fn main() {
let mut x: Option<&isize> = None;
with_int(|y| x = Some(y));
//~^ ERROR borrowed data cannot be stored outside of its closure
//~^ ERROR borrowed data escapes outside of closure
}

View file

@ -1,12 +1,12 @@
error: borrowed data cannot be stored outside of its closure
--> $DIR/regions-escape-bound-fn.rs:8:27
error[E0521]: borrowed data escapes outside of closure
--> $DIR/regions-escape-bound-fn.rs:11:18
|
LL | let mut x: Option<&isize> = None;
| ----- borrowed data cannot be stored into here...
| ----- `x` declared here, outside of the closure body
LL | with_int(|y| x = Some(y));
| --- ^ cannot be stored outside of its closure
| |
| ...because it cannot outlive this closure
| - ^^^^^^^^^^^ `y` escapes the closure body here
| |
| `y` is a reference that is only valid in the closure body
error: aborting due to previous error

View file

@ -1,12 +0,0 @@
error[E0521]: borrowed data escapes outside of closure
--> $DIR/regions-escape-unboxed-closure.rs:6:23
|
LL | let mut x: Option<&isize> = None;
| ----- `x` declared here, outside of the closure body
LL | with_int(&mut |y| x = Some(y));
| - ^^^^^^^^^^^ `y` escapes the closure body here
| |
| `y` is a reference that is only valid in the closure body
error: aborting due to previous error

View file

@ -1,8 +1,7 @@
fn with_int(f: &mut dyn FnMut(&isize)) {
}
fn with_int(f: &mut dyn FnMut(&isize)) {}
fn main() {
let mut x: Option<&isize> = None;
with_int(&mut |y| x = Some(y));
//~^ ERROR borrowed data cannot be stored outside of its closure
//~^ ERROR borrowed data escapes outside of closure
}

View file

@ -1,12 +1,12 @@
error: borrowed data cannot be stored outside of its closure
--> $DIR/regions-escape-unboxed-closure.rs:6:32
error[E0521]: borrowed data escapes outside of closure
--> $DIR/regions-escape-unboxed-closure.rs:5:23
|
LL | let mut x: Option<&isize> = None;
| ----- borrowed data cannot be stored into here...
| ----- `x` declared here, outside of the closure body
LL | with_int(&mut |y| x = Some(y));
| --- ^ cannot be stored outside of its closure
| |
| ...because it cannot outlive this closure
| - ^^^^^^^^^^^ `y` escapes the closure body here
| |
| `y` is a reference that is only valid in the closure body
error: aborting due to previous error

View file

@ -1,123 +0,0 @@
error: lifetime may not live long enough
--> $DIR/variadic-ffi-4.rs:8:5
|
LL | pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f> {
| -- -- has type `core::ffi::VaListImpl<'1>`
| |
| lifetime `'f` defined here
LL | ap
| ^^ function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'f`
error: lifetime may not live long enough
--> $DIR/variadic-ffi-4.rs:8:5
|
LL | pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f> {
| -- -- has type `core::ffi::VaListImpl<'1>`
| |
| lifetime `'f` defined here
LL | ap
| ^^ returning this value requires that `'1` must outlive `'f`
error: lifetime may not live long enough
--> $DIR/variadic-ffi-4.rs:12:5
|
LL | pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaListImpl<'static> {
| -- has type `core::ffi::VaListImpl<'1>`
LL | ap
| ^^ returning this value requires that `'1` must outlive `'static`
error: lifetime may not live long enough
--> $DIR/variadic-ffi-4.rs:16:33
|
LL | let _ = ap.with_copy(|ap| { ap });
| --- ^^ returning this value requires that `'1` must outlive `'2`
| | |
| | return type of closure is core::ffi::VaList<'2, '_>
| has type `core::ffi::VaList<'1, '_>`
error: lifetime may not live long enough
--> $DIR/variadic-ffi-4.rs:20:5
|
LL | pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
| ------- ------- has type `core::ffi::VaListImpl<'2>`
| |
| has type `&mut core::ffi::VaListImpl<'1>`
LL | *ap0 = ap1;
| ^^^^ assignment requires that `'1` must outlive `'2`
error: lifetime may not live long enough
--> $DIR/variadic-ffi-4.rs:20:5
|
LL | pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
| ------- ------- has type `core::ffi::VaListImpl<'2>`
| |
| has type `&mut core::ffi::VaListImpl<'1>`
LL | *ap0 = ap1;
| ^^^^ assignment requires that `'2` must outlive `'1`
error: lifetime may not live long enough
--> $DIR/variadic-ffi-4.rs:24:5
|
LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
| --- ------- has type `core::ffi::VaListImpl<'2>`
| |
| has type `&mut core::ffi::VaListImpl<'1>`
LL | ap0 = &mut ap1;
| ^^^^^^^^^^^^^^ assignment requires that `'1` must outlive `'2`
error: lifetime may not live long enough
--> $DIR/variadic-ffi-4.rs:24:5
|
LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
| --- ------- has type `core::ffi::VaListImpl<'2>`
| |
| has type `&mut core::ffi::VaListImpl<'1>`
LL | ap0 = &mut ap1;
| ^^^^^^^^^^^^^^ assignment requires that `'2` must outlive `'1`
error[E0384]: cannot assign to immutable argument `ap0`
--> $DIR/variadic-ffi-4.rs:24:5
|
LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
| --- help: make this binding mutable: `mut ap0`
LL | ap0 = &mut ap1;
| ^^^^^^^^^^^^^^ cannot assign to immutable argument
error[E0597]: `ap1` does not live long enough
--> $DIR/variadic-ffi-4.rs:24:11
|
LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
| - let's call the lifetime of this reference `'3`
LL | ap0 = &mut ap1;
| ------^^^^^^^^
| | |
| | borrowed value does not live long enough
| assignment requires that `ap1` is borrowed for `'3`
...
LL | }
| - `ap1` dropped here while still borrowed
error: lifetime may not live long enough
--> $DIR/variadic-ffi-4.rs:31:12
|
LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
| ------- ------- has type `core::ffi::VaListImpl<'2>`
| |
| has type `&mut core::ffi::VaListImpl<'1>`
LL | *ap0 = ap1.clone();
| ^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
error: lifetime may not live long enough
--> $DIR/variadic-ffi-4.rs:31:12
|
LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
| ------- ------- has type `core::ffi::VaListImpl<'2>`
| |
| has type `&mut core::ffi::VaListImpl<'1>`
LL | *ap0 = ap1.clone();
| ^^^^^^^^^^^ argument requires that `'2` must outlive `'1`
error: aborting due to 12 previous errors
Some errors have detailed explanations: E0384, E0597.
For more information about an error, try `rustc --explain E0384`.

View file

@ -1,32 +1,38 @@
#![crate_type="lib"]
#![crate_type = "lib"]
#![no_std]
#![feature(c_variadic)]
use core::ffi::{VaList, VaListImpl};
pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f> {
ap //~ ERROR: mismatched types
ap
//~^ ERROR: lifetime may not live long enough
//~| ERROR: lifetime may not live long enough
}
pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaListImpl<'static> {
ap //~ ERROR: mismatched types
ap //~ ERROR: lifetime may not live long enough
}
pub unsafe extern "C" fn no_escape2(_: usize, ap: ...) {
let _ = ap.with_copy(|ap| { ap }); //~ ERROR: cannot infer an appropriate lifetime
let _ = ap.with_copy(|ap| ap); //~ ERROR: lifetime may not live long enough
}
pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
*ap0 = ap1; //~ ERROR: mismatched types
*ap0 = ap1;
//~^ ERROR: lifetime may not live long enough
//~| ERROR: lifetime may not live long enough
}
pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
ap0 = &mut ap1;
//~^ ERROR: a value of type `core::ffi::VaListImpl<'_>` is borrowed for too long
//~| ERROR: mismatched types
//~| ERROR: cannot infer an appropriate lifetime
//~^ ERROR: `ap1` does not live long enough
//~| ERROR: lifetime may not live long enough
//~| ERROR: lifetime may not live long enough
}
pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
*ap0 = ap1.clone(); //~ ERROR: mismatched types
*ap0 = ap1.clone();
//~^ ERROR: lifetime may not live long enough
//~| ERROR: lifetime may not live long enough
}

View file

@ -1,217 +1,114 @@
error[E0308]: mismatched types
error: lifetime may not live long enough
--> $DIR/variadic-ffi-4.rs:8:5
|
LL | pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f> {
| -- -- has type `core::ffi::VaListImpl<'1>`
| |
| lifetime `'f` defined here
LL | ap
| ^^ lifetime mismatch
|
= note: expected struct `core::ffi::VaListImpl<'f>`
found struct `core::ffi::VaListImpl<'_>`
note: the scope of call-site for function at 7:78...
--> $DIR/variadic-ffi-4.rs:7:78
|
LL | pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f> {
| ______________________________________________________________________________^
LL | | ap
LL | | }
| |_^
note: ...does not necessarily outlive the lifetime `'f` as defined on the function body at 7:37
--> $DIR/variadic-ffi-4.rs:7:37
| ^^ function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'f`
error: lifetime may not live long enough
--> $DIR/variadic-ffi-4.rs:8:5
|
LL | pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f> {
| ^^
error[E0308]: mismatched types
--> $DIR/variadic-ffi-4.rs:12:5
|
| -- -- has type `core::ffi::VaListImpl<'1>`
| |
| lifetime `'f` defined here
LL | ap
| ^^ lifetime mismatch
|
= note: expected struct `core::ffi::VaListImpl<'static>`
found struct `core::ffi::VaListImpl<'_>`
note: the scope of call-site for function at 11:79...
--> $DIR/variadic-ffi-4.rs:11:79
|
LL | pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaListImpl<'static> {
| _______________________________________________________________________________^
LL | | ap
LL | | }
| |_^
= note: ...does not necessarily outlive the static lifetime
| ^^ returning this value requires that `'1` must outlive `'f`
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> $DIR/variadic-ffi-4.rs:16:33
error: lifetime may not live long enough
--> $DIR/variadic-ffi-4.rs:14:5
|
LL | let _ = ap.with_copy(|ap| { ap });
| ^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 16:26...
--> $DIR/variadic-ffi-4.rs:16:26
|
LL | let _ = ap.with_copy(|ap| { ap });
| ^^^^^^^^^^^
note: ...so that the expression is assignable
--> $DIR/variadic-ffi-4.rs:16:33
|
LL | let _ = ap.with_copy(|ap| { ap });
| ^^
= note: expected `core::ffi::VaList<'_, '_>`
found `core::ffi::VaList<'_, '_>`
note: but, the lifetime must be valid for the method call at 16:13...
--> $DIR/variadic-ffi-4.rs:16:13
|
LL | let _ = ap.with_copy(|ap| { ap });
| ^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so type `core::ffi::VaList<'_, '_>` of expression is valid during the expression
--> $DIR/variadic-ffi-4.rs:16:13
|
LL | let _ = ap.with_copy(|ap| { ap });
| ^^^^^^^^^^^^^^^^^^^^^^^^^
LL | pub unsafe extern "C" fn no_escape1(_: usize, ap: ...) -> VaListImpl<'static> {
| -- has type `core::ffi::VaListImpl<'1>`
LL | ap
| ^^ returning this value requires that `'1` must outlive `'static`
error[E0308]: mismatched types
--> $DIR/variadic-ffi-4.rs:20:12
error: lifetime may not live long enough
--> $DIR/variadic-ffi-4.rs:18:31
|
LL | let _ = ap.with_copy(|ap| ap);
| --- ^^ returning this value requires that `'1` must outlive `'2`
| | |
| | return type of closure is core::ffi::VaList<'2, '_>
| has type `core::ffi::VaList<'1, '_>`
error: lifetime may not live long enough
--> $DIR/variadic-ffi-4.rs:22:5
|
LL | pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
| ------- ------- has type `core::ffi::VaListImpl<'2>`
| |
| has type `&mut core::ffi::VaListImpl<'1>`
LL | *ap0 = ap1;
| ^^^ lifetime mismatch
|
= note: expected struct `core::ffi::VaListImpl<'_>`
found struct `core::ffi::VaListImpl<'_>`
note: the scope of call-site for function at 19:87...
--> $DIR/variadic-ffi-4.rs:19:87
|
LL | pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
| _______________________________________________________________________________________^
LL | | *ap0 = ap1;
LL | | }
| |_^
note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 19:1
--> $DIR/variadic-ffi-4.rs:19:1
|
LL | / pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
LL | | *ap0 = ap1;
LL | | }
| |_^
| ^^^^ assignment requires that `'1` must outlive `'2`
error[E0490]: a value of type `core::ffi::VaListImpl<'_>` is borrowed for too long
--> $DIR/variadic-ffi-4.rs:24:11
error: lifetime may not live long enough
--> $DIR/variadic-ffi-4.rs:22:5
|
LL | ap0 = &mut ap1;
| ^^^^^^^^
|
note: the type is valid for the anonymous lifetime #1 defined on the function body at 23:1
--> $DIR/variadic-ffi-4.rs:23:1
|
LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
LL | | ap0 = &mut ap1;
LL | |
LL | |
LL | |
LL | | }
| |_^
note: but the borrow lasts for the scope of call-site for function at 23:83
--> $DIR/variadic-ffi-4.rs:23:83
|
LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
| ___________________________________________________________________________________^
LL | | ap0 = &mut ap1;
LL | |
LL | |
LL | |
LL | | }
| |_^
LL | pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
| ------- ------- has type `core::ffi::VaListImpl<'2>`
| |
| has type `&mut core::ffi::VaListImpl<'1>`
LL | *ap0 = ap1;
| ^^^^ assignment requires that `'2` must outlive `'1`
error[E0308]: mismatched types
--> $DIR/variadic-ffi-4.rs:24:11
error: lifetime may not live long enough
--> $DIR/variadic-ffi-4.rs:28:5
|
LL | pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
| ------- ------- has type `core::ffi::VaListImpl<'2>`
| |
| has type `&mut core::ffi::VaListImpl<'1>`
LL | ap0 = &mut ap1;
| ^^^^^^^^ lifetime mismatch
|
= note: expected mutable reference `&mut core::ffi::VaListImpl<'_>`
found mutable reference `&mut core::ffi::VaListImpl<'_>`
note: the scope of call-site for function at 23:83...
--> $DIR/variadic-ffi-4.rs:23:83
|
LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
| ___________________________________________________________________________________^
LL | | ap0 = &mut ap1;
LL | |
LL | |
LL | |
LL | | }
| |_^
note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 23:1
--> $DIR/variadic-ffi-4.rs:23:1
|
LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
LL | | ap0 = &mut ap1;
LL | |
LL | |
LL | |
LL | | }
| |_^
| ^^^^^^^^^^^^^^ assignment requires that `'1` must outlive `'2`
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> $DIR/variadic-ffi-4.rs:24:11
error: lifetime may not live long enough
--> $DIR/variadic-ffi-4.rs:28:5
|
LL | pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
| ------- ------- has type `core::ffi::VaListImpl<'2>`
| |
| has type `&mut core::ffi::VaListImpl<'1>`
LL | ap0 = &mut ap1;
| ^^^^^^^^
|
note: first, the lifetime cannot outlive the scope of call-site for function at 23:83...
--> $DIR/variadic-ffi-4.rs:23:83
|
LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
| ___________________________________________________________________________________^
LL | | ap0 = &mut ap1;
LL | |
LL | |
LL | |
LL | | }
| |_^
note: ...so that the type `core::ffi::VaListImpl<'_>` is not borrowed for too long
--> $DIR/variadic-ffi-4.rs:24:11
|
LL | ap0 = &mut ap1;
| ^^^^^^^^
note: but, the lifetime must be valid for the anonymous lifetime #1 defined on the function body at 23:1...
--> $DIR/variadic-ffi-4.rs:23:1
|
LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
LL | | ap0 = &mut ap1;
LL | |
LL | |
LL | |
LL | | }
| |_^
note: ...so that reference does not outlive borrowed content
--> $DIR/variadic-ffi-4.rs:24:11
|
LL | ap0 = &mut ap1;
| ^^^^^^^^
| ^^^^^^^^^^^^^^ assignment requires that `'2` must outlive `'1`
error[E0308]: mismatched types
--> $DIR/variadic-ffi-4.rs:31:12
error[E0597]: `ap1` does not live long enough
--> $DIR/variadic-ffi-4.rs:28:11
|
LL | pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
| - let's call the lifetime of this reference `'3`
LL | ap0 = &mut ap1;
| ------^^^^^^^^
| | |
| | borrowed value does not live long enough
| assignment requires that `ap1` is borrowed for `'3`
...
LL | }
| - `ap1` dropped here while still borrowed
error: lifetime may not live long enough
--> $DIR/variadic-ffi-4.rs:35:12
|
LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
| ------- ------- has type `core::ffi::VaListImpl<'2>`
| |
| has type `&mut core::ffi::VaListImpl<'1>`
LL | *ap0 = ap1.clone();
| ^^^^^^^^^^^ lifetime mismatch
|
= note: expected struct `core::ffi::VaListImpl<'_>`
found struct `core::ffi::VaListImpl<'_>`
note: the scope of call-site for function at 30:87...
--> $DIR/variadic-ffi-4.rs:30:87
|
LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
| _______________________________________________________________________________________^
LL | | *ap0 = ap1.clone();
LL | | }
| |_^
note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 30:1
--> $DIR/variadic-ffi-4.rs:30:1
|
LL | / pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
LL | | *ap0 = ap1.clone();
LL | | }
| |_^
| ^^^^^^^^^^^ argument requires that `'1` must outlive `'2`
error: aborting due to 8 previous errors
error: lifetime may not live long enough
--> $DIR/variadic-ffi-4.rs:35:12
|
LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
| ------- ------- has type `core::ffi::VaListImpl<'2>`
| |
| has type `&mut core::ffi::VaListImpl<'1>`
LL | *ap0 = ap1.clone();
| ^^^^^^^^^^^ argument requires that `'2` must outlive `'1`
Some errors have detailed explanations: E0308, E0495.
For more information about an error, try `rustc --explain E0308`.
error: aborting due to 11 previous errors
For more information about this error, try `rustc --explain E0597`.

View file

@ -0,0 +1,24 @@
error: lifetime may not live long enough
--> $DIR/expect-region-supply-region-2.rs:14:30
|
LL | fn expect_bound_supply_named<'x>() {
| -- lifetime `'x` defined here
...
LL | closure_expecting_bound(|x: &'x u32| {
| ^ - let's call the lifetime of this reference `'1`
| |
| requires that `'1` must outlive `'x`
error: lifetime may not live long enough
--> $DIR/expect-region-supply-region-2.rs:14:30
|
LL | fn expect_bound_supply_named<'x>() {
| -- lifetime `'x` defined here
...
LL | closure_expecting_bound(|x: &'x u32| {
| ^ requires that `'x` must outlive `'static`
|
= help: consider replacing `'x` with `'static`
error: aborting due to 2 previous errors

View file

@ -0,0 +1,24 @@
#![allow(warnings)]
fn closure_expecting_bound<F>(_: F)
where
F: FnOnce(&u32),
{
}
fn expect_bound_supply_named<'x>() {
let mut f: Option<&u32> = None;
// Here we give a type annotation that `x` should be free. We get
// an error because of that.
closure_expecting_bound(|x: &'x u32| {
//~^ ERROR mismatched types
//~| ERROR mismatched types
// Borrowck doesn't get a chance to run, but if it did it should error
// here.
f = Some(x);
});
}
fn main() {}

View file

@ -0,0 +1,55 @@
error[E0308]: mismatched types
--> $DIR/expect-region-supply-region-2.rs:14:33
|
LL | closure_expecting_bound(|x: &'x u32| {
| ^^^^^^^ lifetime mismatch
|
= note: expected reference `&u32`
found reference `&'x u32`
note: the anonymous lifetime #2 defined on the body at 14:29...
--> $DIR/expect-region-supply-region-2.rs:14:29
|
LL | closure_expecting_bound(|x: &'x u32| {
| _____________________________^
LL | |
LL | |
LL | |
... |
LL | | f = Some(x);
LL | | });
| |_____^
note: ...does not necessarily outlive the lifetime `'x` as defined on the function body at 9:30
--> $DIR/expect-region-supply-region-2.rs:9:30
|
LL | fn expect_bound_supply_named<'x>() {
| ^^
error[E0308]: mismatched types
--> $DIR/expect-region-supply-region-2.rs:14:33
|
LL | closure_expecting_bound(|x: &'x u32| {
| ^^^^^^^ lifetime mismatch
|
= note: expected reference `&u32`
found reference `&'x u32`
note: the lifetime `'x` as defined on the function body at 9:30...
--> $DIR/expect-region-supply-region-2.rs:9:30
|
LL | fn expect_bound_supply_named<'x>() {
| ^^
note: ...does not necessarily outlive the anonymous lifetime #2 defined on the body at 14:29
--> $DIR/expect-region-supply-region-2.rs:14:29
|
LL | closure_expecting_bound(|x: &'x u32| {
| _____________________________^
LL | |
LL | |
LL | |
... |
LL | | f = Some(x);
LL | | });
| |_____^
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0308`.

View file

@ -1,44 +0,0 @@
error[E0521]: borrowed data escapes outside of closure
--> $DIR/expect-region-supply-region.rs:18:9
|
LL | let mut f: Option<&u32> = None;
| ----- `f` declared here, outside of the closure body
LL | closure_expecting_bound(|x| {
| - `x` is a reference that is only valid in the closure body
LL | f = Some(x);
| ^^^^^^^^^^^ `x` escapes the closure body here
error[E0521]: borrowed data escapes outside of closure
--> $DIR/expect-region-supply-region.rs:28:9
|
LL | let mut f: Option<&u32> = None;
| ----- `f` declared here, outside of the closure body
LL | closure_expecting_bound(|x: &u32| {
| - `x` is a reference that is only valid in the closure body
LL | f = Some(x);
| ^^^^^^^^^^^ `x` escapes the closure body here
error: lifetime may not live long enough
--> $DIR/expect-region-supply-region.rs:37:30
|
LL | fn expect_bound_supply_named<'x>() {
| -- lifetime `'x` defined here
...
LL | closure_expecting_bound(|x: &'x u32| {
| ^ - let's call the lifetime of this reference `'1`
| |
| requires that `'1` must outlive `'x`
error: lifetime may not live long enough
--> $DIR/expect-region-supply-region.rs:37:30
|
LL | fn expect_bound_supply_named<'x>() {
| -- lifetime `'x` defined here
...
LL | closure_expecting_bound(|x: &'x u32| {
| ^ requires that `'x` must outlive `'static`
|
= help: consider replacing `'x` with `'static`
error: aborting due to 4 previous errors

View file

@ -1,12 +1,14 @@
#![allow(warnings)]
fn closure_expecting_bound<F>(_: F)
where F: FnOnce(&u32)
where
F: FnOnce(&u32),
{
}
fn closure_expecting_free<'a, F>(_: F)
where F: FnOnce(&'a u32)
where
F: FnOnce(&'a u32),
{
}
@ -15,7 +17,7 @@ fn expect_bound_supply_nothing() {
// it to escape into `f`:
let mut f: Option<&u32> = None;
closure_expecting_bound(|x| {
f = Some(x); //~ ERROR borrowed data cannot be stored outside of its closure
f = Some(x); //~ ERROR borrowed data escapes outside of closure
});
}
@ -25,22 +27,7 @@ fn expect_bound_supply_bound() {
// closure:
let mut f: Option<&u32> = None;
closure_expecting_bound(|x: &u32| {
f = Some(x); //~ ERROR borrowed data cannot be stored outside of its closure
});
}
fn expect_bound_supply_named<'x>() {
let mut f: Option<&u32> = None;
// Here we give a type annotation that `x` should be free. We get
// an error because of that.
closure_expecting_bound(|x: &'x u32| {
//~^ ERROR mismatched types
//~| ERROR mismatched types
// And we still cannot let `x` escape into `f`.
f = Some(x);
//~^ ERROR borrowed data cannot be stored outside of its closure
f = Some(x); //~ ERROR borrowed data escapes outside of closure
});
}
@ -67,4 +54,4 @@ fn expect_free_supply_named<'x>() {
closure_expecting_free(|x: &'x u32| f = Some(x)); // OK
}
fn main() { }
fn main() {}

View file

@ -1,87 +1,22 @@
error: borrowed data cannot be stored outside of its closure
--> $DIR/expect-region-supply-region.rs:18:18
error[E0521]: borrowed data escapes outside of closure
--> $DIR/expect-region-supply-region.rs:20:9
|
LL | let mut f: Option<&u32> = None;
| ----- borrowed data cannot be stored into here...
| ----- `f` declared here, outside of the closure body
LL | closure_expecting_bound(|x| {
| --- ...because it cannot outlive this closure
| - `x` is a reference that is only valid in the closure body
LL | f = Some(x);
| ^ cannot be stored outside of its closure
| ^^^^^^^^^^^ `x` escapes the closure body here
error: borrowed data cannot be stored outside of its closure
--> $DIR/expect-region-supply-region.rs:28:18
error[E0521]: borrowed data escapes outside of closure
--> $DIR/expect-region-supply-region.rs:30:9
|
LL | let mut f: Option<&u32> = None;
| ----- borrowed data cannot be stored into here...
| ----- `f` declared here, outside of the closure body
LL | closure_expecting_bound(|x: &u32| {
| --------- ...because it cannot outlive this closure
| - `x` is a reference that is only valid in the closure body
LL | f = Some(x);
| ^ cannot be stored outside of its closure
| ^^^^^^^^^^^ `x` escapes the closure body here
error[E0308]: mismatched types
--> $DIR/expect-region-supply-region.rs:37:33
|
LL | closure_expecting_bound(|x: &'x u32| {
| ^^^^^^^ lifetime mismatch
|
= note: expected reference `&u32`
found reference `&'x u32`
note: the anonymous lifetime #2 defined on the body at 37:29...
--> $DIR/expect-region-supply-region.rs:37:29
|
LL | closure_expecting_bound(|x: &'x u32| {
| _____________________________^
LL | |
LL | |
LL | |
... |
LL | |
LL | | });
| |_____^
note: ...does not necessarily outlive the lifetime `'x` as defined on the function body at 32:30
--> $DIR/expect-region-supply-region.rs:32:30
|
LL | fn expect_bound_supply_named<'x>() {
| ^^
error: aborting due to 2 previous errors
error[E0308]: mismatched types
--> $DIR/expect-region-supply-region.rs:37:33
|
LL | closure_expecting_bound(|x: &'x u32| {
| ^^^^^^^ lifetime mismatch
|
= note: expected reference `&u32`
found reference `&'x u32`
note: the lifetime `'x` as defined on the function body at 32:30...
--> $DIR/expect-region-supply-region.rs:32:30
|
LL | fn expect_bound_supply_named<'x>() {
| ^^
note: ...does not necessarily outlive the anonymous lifetime #2 defined on the body at 37:29
--> $DIR/expect-region-supply-region.rs:37:29
|
LL | closure_expecting_bound(|x: &'x u32| {
| _____________________________^
LL | |
LL | |
LL | |
... |
LL | |
LL | | });
| |_____^
error: borrowed data cannot be stored outside of its closure
--> $DIR/expect-region-supply-region.rs:42:18
|
LL | let mut f: Option<&u32> = None;
| ----- borrowed data cannot be stored into here...
...
LL | closure_expecting_bound(|x: &'x u32| {
| ------------ ...because it cannot outlive this closure
...
LL | f = Some(x);
| ^ cannot be stored outside of its closure
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0308`.

View file

@ -0,0 +1,28 @@
error: lifetime may not live long enough
--> $DIR/E0490.rs:2:12
|
LL | fn f<'a, 'b>(y: &'b ()) {
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
LL | let x: &'a _ = &y;
| ^^^^^ type annotation requires that `'b` must outlive `'a`
|
= help: consider adding the following bound: `'b: 'a`
error[E0597]: `y` does not live long enough
--> $DIR/E0490.rs:2:20
|
LL | fn f<'a, 'b>(y: &'b ()) {
| -- lifetime `'a` defined here
LL | let x: &'a _ = &y;
| ----- ^^ borrowed value does not live long enough
| |
| type annotation requires that `y` is borrowed for `'a`
...
LL | }
| - `y` dropped here while still borrowed
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0597`.

View file

@ -0,0 +1,8 @@
fn f<'a, 'b>(y: &'b ()) {
let x: &'a _ = &y;
//~^ E0490
//~| E0495
//~| E0495
}
fn main() {}

View file

@ -0,0 +1,76 @@
error[E0490]: a value of type `&'b ()` is borrowed for too long
--> $DIR/E0490.rs:2:20
|
LL | let x: &'a _ = &y;
| ^^
|
note: the type is valid for the lifetime `'a` as defined on the function body at 1:6
--> $DIR/E0490.rs:1:6
|
LL | fn f<'a, 'b>(y: &'b ()) {
| ^^
note: but the borrow lasts for the lifetime `'b` as defined on the function body at 1:10
--> $DIR/E0490.rs:1:10
|
LL | fn f<'a, 'b>(y: &'b ()) {
| ^^
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> $DIR/E0490.rs:2:20
|
LL | let x: &'a _ = &y;
| ^^
|
note: first, the lifetime cannot outlive the lifetime `'b` as defined on the function body at 1:10...
--> $DIR/E0490.rs:1:10
|
LL | fn f<'a, 'b>(y: &'b ()) {
| ^^
note: ...so that the type `&'b ()` is not borrowed for too long
--> $DIR/E0490.rs:2:20
|
LL | let x: &'a _ = &y;
| ^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 1:6...
--> $DIR/E0490.rs:1:6
|
LL | fn f<'a, 'b>(y: &'b ()) {
| ^^
note: ...so that reference does not outlive borrowed content
--> $DIR/E0490.rs:2:20
|
LL | let x: &'a _ = &y;
| ^^
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> $DIR/E0490.rs:2:20
|
LL | let x: &'a _ = &y;
| ^^
|
note: first, the lifetime cannot outlive the lifetime `'b` as defined on the function body at 1:10...
--> $DIR/E0490.rs:1:10
|
LL | fn f<'a, 'b>(y: &'b ()) {
| ^^
note: ...so that the expression is assignable
--> $DIR/E0490.rs:2:20
|
LL | let x: &'a _ = &y;
| ^^
= note: expected `&'a &()`
found `&'a &'b ()`
note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 1:6...
--> $DIR/E0490.rs:1:6
|
LL | fn f<'a, 'b>(y: &'b ()) {
| ^^
note: ...so that the reference type `&'a &()` does not outlive the data it points at
--> $DIR/E0490.rs:2:12
|
LL | let x: &'a _ = &y;
| ^^^^^
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0495`.

View file

@ -1,11 +0,0 @@
error: lifetime may not live long enough
--> $DIR/E0621-does-not-trigger-for-closures.rs:15:45
|
LL | invoke(&x, |a, b| if a > b { a } else { b });
| -- ^ returning this value requires that `'1` must outlive `'2`
| ||
| |return type of closure is &'2 i32
| has type `&'1 i32`
error: aborting due to previous error

View file

@ -1,9 +1,7 @@
// Test that we give the generic E0495 when one of the free regions is
// Test that we give the generic error when one of the free regions is
// bound in a closure (rather than suggesting a change to the signature
// of the closure, which is not specified in `foo` but rather in `invoke`).
// FIXME - This might be better as a UI test, but the finer details
// of the error seem to vary on different machines.
fn invoke<'a, F>(x: &'a i32, f: F) -> &'a i32
where F: FnOnce(&'a i32, &i32) -> &'a i32
{
@ -12,7 +10,7 @@ where F: FnOnce(&'a i32, &i32) -> &'a i32
}
fn foo<'a>(x: &'a i32) {
invoke(&x, |a, b| if a > b { a } else { b }); //~ ERROR E0495
invoke(&x, |a, b| if a > b { a } else { b }); //~ ERROR lifetime may not live long enough
}
fn main() {}

View file

@ -1,30 +1,11 @@
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
--> $DIR/E0621-does-not-trigger-for-closures.rs:15:5
error: lifetime may not live long enough
--> $DIR/E0621-does-not-trigger-for-closures.rs:13:45
|
LL | invoke(&x, |a, b| if a > b { a } else { b });
| ^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 15:16...
--> $DIR/E0621-does-not-trigger-for-closures.rs:15:16
|
LL | invoke(&x, |a, b| if a > b { a } else { b });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> $DIR/E0621-does-not-trigger-for-closures.rs:15:45
|
LL | invoke(&x, |a, b| if a > b { a } else { b });
| ^
note: but, the lifetime must be valid for the call at 15:5...
--> $DIR/E0621-does-not-trigger-for-closures.rs:15:5
|
LL | invoke(&x, |a, b| if a > b { a } else { b });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so type `&i32` of expression is valid during the expression
--> $DIR/E0621-does-not-trigger-for-closures.rs:15:5
|
LL | invoke(&x, |a, b| if a > b { a } else { b });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| -- ^ returning this value requires that `'1` must outlive `'2`
| ||
| |return type of closure is &'2 i32
| has type `&'1 i32`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0495`.

View file

@ -4,17 +4,11 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea
LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
| ^^^^^^^^^^^^^^^^^^
|
note: hidden type `Ordinary<'_>` captures the scope of call-site for function at 23:1
--> $DIR/ordinary-bounds-unrelated.rs:23:1
note: hidden type `Ordinary<'_>` captures lifetime smaller than the function body
--> $DIR/ordinary-bounds-unrelated.rs:18:74
|
LL | / {
LL | | // Hidden type `Ordinary<'0>` with constraints:
LL | | //
LL | | // ```
... |
LL | | if condition() { a } else { b }
LL | | }
| |_^
LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
| ^^^^^^^^^^^^^^^^^^
error: aborting due to previous error

View file

@ -4,17 +4,11 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea
LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
| ^^^^^^^^^^^^^^^^^^
|
note: hidden type `Ordinary<'_>` captures the scope of call-site for function at 22:1
--> $DIR/ordinary-bounds-unsuited.rs:22:1
note: hidden type `Ordinary<'_>` captures lifetime smaller than the function body
--> $DIR/ordinary-bounds-unsuited.rs:20:62
|
LL | / {
LL | | // We return a value:
LL | | //
LL | | // ```
... |
LL | | if condition() { a } else { b }
LL | | }
| |_^
LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
| ^^^^^^^^^^^^^^^^^^
error: aborting due to previous error

View file

@ -6,22 +6,21 @@ trait A<T>
fn get(&self) -> T { panic!() }
}
struct B<'a, T:'a>(&'a (A<T>+'a));
struct B<'a, T: 'a>(&'a (A<T> + 'a));
trait X { fn foo(&self) {} }
impl<'a, T> X for B<'a, T> {}
fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
// oh dear!
box B(&*v) as Box<X>
//~^ ERROR the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough
//~^ ERROR the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough
}
fn main() {}

View file

@ -1,7 +1,7 @@
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:17:5
|
LL | fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | // oh dear!
LL | box B(&*v) as Box<X>
@ -13,25 +13,10 @@ note: ...so that the type `B<'_, T>` will meet its required lifetime bounds
LL | box B(&*v) as Box<X>
| ^^^^^^^^^^
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:17:5
|
LL | fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | // oh dear!
LL | box B(&*v) as Box<X>
| ^^^^^^^^^^^^^^^^^^^^
|
note: ...so that it can be closed over into an object
--> $DIR/regions-close-object-into-object-5.rs:17:5
|
LL | box B(&*v) as Box<X>
| ^^^^^^^^^^^^^^^^^^^^
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:17:9
|
LL | fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | // oh dear!
LL | box B(&*v) as Box<X>
@ -46,7 +31,7 @@ LL | box B(&*v) as Box<X>
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:17:9
|
LL | fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | // oh dear!
LL | box B(&*v) as Box<X>
@ -61,7 +46,7 @@ LL | box B(&*v) as Box<X>
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:17:11
|
LL | fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | // oh dear!
LL | box B(&*v) as Box<X>
@ -76,7 +61,7 @@ LL | box B(&*v) as Box<X>
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:17:11
|
LL | fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | // oh dear!
LL | box B(&*v) as Box<X>
@ -91,7 +76,7 @@ LL | box B(&*v) as Box<X>
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:17:11
|
LL | fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | // oh dear!
LL | box B(&*v) as Box<X>
@ -103,6 +88,6 @@ note: ...so that the type `(dyn A<T> + 'static)` is not borrowed for too long
LL | box B(&*v) as Box<X>
| ^^^
error: aborting due to 7 previous errors
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0310`.

View file

@ -1,5 +1,5 @@
error[E0310]: the parameter type `A` may not live long enough
--> $DIR/regions-close-over-type-parameter-1.rs:10:5
--> $DIR/regions-close-over-type-parameter-1.rs:12:5
|
LL | box v as Box<dyn SomeTrait + 'static>
| ^^^^^
@ -7,7 +7,7 @@ LL | box v as Box<dyn SomeTrait + 'static>
= help: consider adding an explicit lifetime bound `A: 'static`...
error[E0309]: the parameter type `A` may not live long enough
--> $DIR/regions-close-over-type-parameter-1.rs:20:5
--> $DIR/regions-close-over-type-parameter-1.rs:21:5
|
LL | box v as Box<dyn SomeTrait + 'b>
| ^^^^^

View file

@ -4,22 +4,22 @@
// an object. This should yield errors unless `A` (and the object)
// both have suitable bounds.
trait SomeTrait { fn get(&self) -> isize; }
fn make_object1<A:SomeTrait>(v: A) -> Box<dyn SomeTrait + 'static> {
box v as Box<dyn SomeTrait + 'static>
//~^ ERROR the parameter type `A` may not live long enough
//~| ERROR the parameter type `A` may not live long enough
trait SomeTrait {
fn get(&self) -> isize;
}
fn make_object2<'a,A:SomeTrait+'a>(v: A) -> Box<dyn SomeTrait + 'a> {
fn make_object1<A: SomeTrait>(v: A) -> Box<dyn SomeTrait + 'static> {
box v as Box<dyn SomeTrait + 'static>
//~^ ERROR the parameter type `A` may not live long enough
}
fn make_object2<'a, A: SomeTrait + 'a>(v: A) -> Box<dyn SomeTrait + 'a> {
box v as Box<dyn SomeTrait + 'a>
}
fn make_object3<'a,'b,A:SomeTrait+'a>(v: A) -> Box<dyn SomeTrait + 'b> {
fn make_object3<'a, 'b, A: SomeTrait + 'a>(v: A) -> Box<dyn SomeTrait + 'b> {
box v as Box<dyn SomeTrait + 'b>
//~^ ERROR the parameter type `A` may not live long enough
//~| ERROR the parameter type `A` may not live long enough
//~^ ERROR the parameter type `A` may not live long enough
}
fn main() { }
fn main() {}

View file

@ -1,60 +1,32 @@
error[E0310]: the parameter type `A` may not live long enough
--> $DIR/regions-close-over-type-parameter-1.rs:10:5
--> $DIR/regions-close-over-type-parameter-1.rs:12:5
|
LL | fn make_object1<A:SomeTrait>(v: A) -> Box<dyn SomeTrait + 'static> {
LL | fn make_object1<A: SomeTrait>(v: A) -> Box<dyn SomeTrait + 'static> {
| -- help: consider adding an explicit lifetime bound...: `A: 'static +`
LL | box v as Box<dyn SomeTrait + 'static>
| ^^^^^
|
note: ...so that the type `A` will meet its required lifetime bounds
--> $DIR/regions-close-over-type-parameter-1.rs:10:5
--> $DIR/regions-close-over-type-parameter-1.rs:12:5
|
LL | box v as Box<dyn SomeTrait + 'static>
| ^^^^^
error[E0310]: the parameter type `A` may not live long enough
--> $DIR/regions-close-over-type-parameter-1.rs:10:5
|
LL | fn make_object1<A:SomeTrait>(v: A) -> Box<dyn SomeTrait + 'static> {
| -- help: consider adding an explicit lifetime bound...: `A: 'static +`
LL | box v as Box<dyn SomeTrait + 'static>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: ...so that it can be closed over into an object
--> $DIR/regions-close-over-type-parameter-1.rs:10:5
|
LL | box v as Box<dyn SomeTrait + 'static>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0309]: the parameter type `A` may not live long enough
--> $DIR/regions-close-over-type-parameter-1.rs:20:5
--> $DIR/regions-close-over-type-parameter-1.rs:21:5
|
LL | fn make_object3<'a,'b,A:SomeTrait+'a>(v: A) -> Box<dyn SomeTrait + 'b> {
| -- help: consider adding an explicit lifetime bound...: `A: 'b +`
LL | fn make_object3<'a, 'b, A: SomeTrait + 'a>(v: A) -> Box<dyn SomeTrait + 'b> {
| -- help: consider adding an explicit lifetime bound...: `A: 'b +`
LL | box v as Box<dyn SomeTrait + 'b>
| ^^^^^
|
note: ...so that the type `A` will meet its required lifetime bounds
--> $DIR/regions-close-over-type-parameter-1.rs:20:5
--> $DIR/regions-close-over-type-parameter-1.rs:21:5
|
LL | box v as Box<dyn SomeTrait + 'b>
| ^^^^^
error[E0309]: the parameter type `A` may not live long enough
--> $DIR/regions-close-over-type-parameter-1.rs:20:5
|
LL | fn make_object3<'a,'b,A:SomeTrait+'a>(v: A) -> Box<dyn SomeTrait + 'b> {
| -- help: consider adding an explicit lifetime bound...: `A: 'b +`
LL | box v as Box<dyn SomeTrait + 'b>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: ...so that it can be closed over into an object
--> $DIR/regions-close-over-type-parameter-1.rs:20:5
|
LL | box v as Box<dyn SomeTrait + 'b>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 4 previous errors
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0309, E0310.
For more information about an error, try `rustc --explain E0309`.

View file

@ -1,11 +0,0 @@
error: lifetime may not live long enough
--> $DIR/regions-escape-method.rs:15:13
|
LL | s.f(|p| p)
| -- ^ returning this value requires that `'1` must outlive `'2`
| ||
| |return type of closure is &'2 i32
| has type `&'1 i32`
error: aborting due to previous error

View file

@ -12,5 +12,5 @@ impl S {
fn main() {
let s = S;
s.f(|p| p) //~ ERROR cannot infer
s.f(|p| p) //~ ERROR lifetime may not live long enough
}

View file

@ -1,32 +1,11 @@
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
error: lifetime may not live long enough
--> $DIR/regions-escape-method.rs:15:13
|
LL | s.f(|p| p)
| ^
|
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 15:9...
--> $DIR/regions-escape-method.rs:15:9
|
LL | s.f(|p| p)
| ^^^^^
note: ...so that the expression is assignable
--> $DIR/regions-escape-method.rs:15:13
|
LL | s.f(|p| p)
| ^
= note: expected `&i32`
found `&i32`
note: but, the lifetime must be valid for the method call at 15:5...
--> $DIR/regions-escape-method.rs:15:5
|
LL | s.f(|p| p)
| ^^^^^^^^^^
note: ...so that a type/lifetime parameter is in scope here
--> $DIR/regions-escape-method.rs:15:5
|
LL | s.f(|p| p)
| ^^^^^^^^^^
| -- ^ returning this value requires that `'1` must outlive `'2`
| ||
| |return type of closure is &'2 i32
| has type `&'1 i32`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0495`.

View file

@ -1,11 +0,0 @@
error: lifetime may not live long enough
--> $DIR/regions-escape-via-trait-or-not.rs:18:14
|
LL | with(|o| o)
| -- ^ returning this value requires that `'1` must outlive `'2`
| ||
| |return type of closure is &'2 isize
| has type `&'1 isize`
error: aborting due to previous error

View file

@ -15,7 +15,7 @@ fn with<R:Deref, F>(f: F) -> isize where F: FnOnce(&isize) -> R {
}
fn return_it() -> isize {
with(|o| o) //~ ERROR cannot infer
with(|o| o) //~ ERROR lifetime may not live long enough
}
fn main() {

View file

@ -1,32 +1,11 @@
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
error: lifetime may not live long enough
--> $DIR/regions-escape-via-trait-or-not.rs:18:14
|
LL | with(|o| o)
| ^
|
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 18:10...
--> $DIR/regions-escape-via-trait-or-not.rs:18:10
|
LL | with(|o| o)
| ^^^^^
note: ...so that the expression is assignable
--> $DIR/regions-escape-via-trait-or-not.rs:18:14
|
LL | with(|o| o)
| ^
= note: expected `&isize`
found `&isize`
note: but, the lifetime must be valid for the expression at 18:5...
--> $DIR/regions-escape-via-trait-or-not.rs:18:5
|
LL | with(|o| o)
| ^^^^
note: ...so type `fn([closure@$DIR/regions-escape-via-trait-or-not.rs:18:10: 18:15]) -> isize {with::<&isize, [closure@$DIR/regions-escape-via-trait-or-not.rs:18:10: 18:15]>}` of expression is valid during the expression
--> $DIR/regions-escape-via-trait-or-not.rs:18:5
|
LL | with(|o| o)
| ^^^^
| -- ^ returning this value requires that `'1` must outlive `'2`
| ||
| |return type of closure is &'2 isize
| has type `&'1 isize`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0495`.

View file

@ -1,11 +0,0 @@
error: lifetime may not live long enough
--> $DIR/regions-infer-call-3.rs:8:24
|
LL | let z = with(|y| { select(x, y) });
| -- ^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
| ||
| |return type of closure is &'2 isize
| has type `&'1 isize`
error: aborting due to previous error

View file

@ -6,7 +6,7 @@ fn with<T, F>(f: F) -> T where F: FnOnce(&isize) -> T {
fn manip<'a>(x: &'a isize) -> isize {
let z = with(|y| { select(x, y) });
//~^ ERROR cannot infer
//~^ ERROR lifetime may not live long enough
*z
}

View file

@ -1,30 +1,11 @@
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'r in function call due to conflicting requirements
error: lifetime may not live long enough
--> $DIR/regions-infer-call-3.rs:8:24
|
LL | let z = with(|y| { select(x, y) });
| ^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 8:18...
--> $DIR/regions-infer-call-3.rs:8:18
|
LL | let z = with(|y| { select(x, y) });
| ^^^^^^^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> $DIR/regions-infer-call-3.rs:8:34
|
LL | let z = with(|y| { select(x, y) });
| ^
note: but, the lifetime must be valid for the call at 8:13...
--> $DIR/regions-infer-call-3.rs:8:13
|
LL | let z = with(|y| { select(x, y) });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so type `&isize` of expression is valid during the expression
--> $DIR/regions-infer-call-3.rs:8:13
|
LL | let z = with(|y| { select(x, y) });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
| -- ^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
| ||
| |return type of closure is &'2 isize
| has type `&'1 isize`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0495`.

View file

@ -1,13 +0,0 @@
error: captured variable cannot escape `FnMut` closure body
--> $DIR/regions-return-ref-to-upvar-issue-17403.rs:7:24
|
LL | let mut f = || &mut x;
| - ^^^^^^ returns a reference to a captured variable which escapes the closure body
| |
| inferred to be a `FnMut` closure
|
= note: `FnMut` closures only have access to their captured variables while they are executing...
= note: ...therefore, they cannot allow references to captured variables to escape
error: aborting due to previous error

View file

@ -4,7 +4,7 @@ fn main() {
// Unboxed closure case
{
let mut x = 0;
let mut f = || &mut x; //~ ERROR cannot infer
let mut f = || &mut x; //~ ERROR captured variable cannot escape `FnMut` closure body
let x = f();
let y = f();
}

View file

@ -1,30 +1,13 @@
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
error: captured variable cannot escape `FnMut` closure body
--> $DIR/regions-return-ref-to-upvar-issue-17403.rs:7:24
|
LL | let mut f = || &mut x;
| ^^^^^^
| - ^^^^^^ returns a reference to a captured variable which escapes the closure body
| |
| inferred to be a `FnMut` closure
|
note: first, the lifetime cannot outlive the lifetime `'_` as defined on the body at 7:21...
--> $DIR/regions-return-ref-to-upvar-issue-17403.rs:7:21
|
LL | let mut f = || &mut x;
| ^^^^^^^^^
note: ...so that closure can access `x`
--> $DIR/regions-return-ref-to-upvar-issue-17403.rs:7:24
|
LL | let mut f = || &mut x;
| ^^^^^^
note: but, the lifetime must be valid for the call at 9:17...
--> $DIR/regions-return-ref-to-upvar-issue-17403.rs:9:17
|
LL | let y = f();
| ^^^
note: ...so type `&mut i32` of expression is valid during the expression
--> $DIR/regions-return-ref-to-upvar-issue-17403.rs:9:17
|
LL | let y = f();
| ^^^
= note: `FnMut` closures only have access to their captured variables while they are executing...
= note: ...therefore, they cannot allow references to captured variables to escape
error: aborting due to previous error
For more information about this error, try `rustc --explain E0495`.

View file

@ -3,8 +3,8 @@
// revisions: legacy v0
//[legacy]compile-flags: -Z symbol-mangling-version=legacy
//[v0]compile-flags: -Z symbol-mangling-version=v0
//[legacy]normalize-stderr-32bit: "hdb62078998ce7ea8" -> "SYMBOL_HASH"
//[legacy]normalize-stderr-64bit: "h62e540f14f879d56" -> "SYMBOL_HASH"
//[legacy]normalize-stderr-32bit: "h5ef5dfc14aeecbfc" -> "SYMBOL_HASH"
//[legacy]normalize-stderr-64bit: "h9e54d216f70fcbc5" -> "SYMBOL_HASH"
#![feature(optin_builtin_traits, rustc_attrs)]
#![allow(dead_code)]