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:
commit
52b605c8cb
81 changed files with 620 additions and 2765 deletions
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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: ®ion::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<®ion::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: ®ion::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: ®ion::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: ®ion::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: ®ion::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,
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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: ®ion::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: ®ion::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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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(_)
|
||||
|
|
|
@ -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, ®ion_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)
|
||||
}
|
|
@ -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>,
|
||||
|
|
|
@ -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: ®ion::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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -284,7 +284,6 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||
},
|
||||
|
||||
ty::ReLateBound(..)
|
||||
| ty::ReScope(..)
|
||||
| ty::ReVar(..)
|
||||
| ty::RePlaceholder(..)
|
||||
| ty::ReEmpty(_)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
®ion_scope_tree,
|
||||
&outlives_env,
|
||||
RegionckMode::default(),
|
||||
);
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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(),
|
||||
®ion_scope_tree,
|
||||
&outlives_env,
|
||||
RegionckMode::default(),
|
||||
);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
®ion_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,
|
||||
®ion_scope_tree,
|
||||
&outlives_env,
|
||||
RegionckMode::default(),
|
||||
);
|
||||
infcx.resolve_regions_and_report_errors(impl_did, &outlives_env, RegionckMode::default());
|
||||
|
||||
CoerceUnsizedInfo { custom_kind: kind }
|
||||
})
|
||||
|
|
|
@ -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(_) => {
|
||||
|
|
|
@ -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(..) => {
|
||||
|
|
|
@ -444,7 +444,6 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
|||
}
|
||||
|
||||
ty::ReFree(..)
|
||||
| ty::ReScope(..)
|
||||
| ty::ReVar(..)
|
||||
| ty::RePlaceholder(..)
|
||||
| ty::ReEmpty(_)
|
||||
|
|
|
@ -447,7 +447,6 @@ impl Clean<Option<Lifetime>> for ty::RegionKind {
|
|||
|
||||
ty::ReLateBound(..)
|
||||
| ty::ReFree(..)
|
||||
| ty::ReScope(..)
|
||||
| ty::ReVar(..)
|
||||
| ty::RePlaceholder(..)
|
||||
| ty::ReEmpty(_)
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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`.
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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`.
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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() {}
|
|
@ -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`.
|
|
@ -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
|
||||
|
|
@ -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() {}
|
||||
|
|
|
@ -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`.
|
||||
|
|
28
src/test/ui/error-codes/E0490.nll.stderr
Normal file
28
src/test/ui/error-codes/E0490.nll.stderr
Normal 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`.
|
8
src/test/ui/error-codes/E0490.rs
Normal file
8
src/test/ui/error-codes/E0490.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
fn f<'a, 'b>(y: &'b ()) {
|
||||
let x: &'a _ = &y;
|
||||
//~^ E0490
|
||||
//~| E0495
|
||||
//~| E0495
|
||||
}
|
||||
|
||||
fn main() {}
|
76
src/test/ui/error-codes/E0490.stderr
Normal file
76
src/test/ui/error-codes/E0490.stderr
Normal 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`.
|
|
@ -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
|
||||
|
|
@ -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() {}
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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>
|
||||
| ^^^^^
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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() {
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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)]
|
||||
|
|
Loading…
Add table
Reference in a new issue