Auto merge of #91799 - matthiaskrgr:rollup-b38xx6i, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #83174 (Suggest using a temporary variable to fix borrowck errors) - #89734 (Point at capture points for non-`'static` reference crossing a `yield` point) - #90270 (Make `Borrow` and `BorrowMut` impls `const`) - #90741 (Const `Option::cloned`) - #91548 (Add spin_loop hint for RISC-V architecture) - #91721 (Minor improvements to `future::join!`'s implementation) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
928783de66
56 changed files with 952 additions and 204 deletions
|
@ -368,6 +368,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
|
|||
error_region,
|
||||
cause.clone(),
|
||||
placeholder_region,
|
||||
vec![],
|
||||
),
|
||||
),
|
||||
(Some(error_region), _) => NiceRegionError::new(
|
||||
|
|
|
@ -15,16 +15,18 @@ use rustc_span::symbol::sym;
|
|||
use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP};
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
|
||||
use crate::borrow_set::TwoPhaseActivation;
|
||||
use crate::borrowck_errors;
|
||||
|
||||
use crate::diagnostics::find_all_local_uses;
|
||||
use crate::{
|
||||
borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf,
|
||||
InitializationRequiringAction, MirBorrowckCtxt, PrefixSet, WriteKind,
|
||||
};
|
||||
|
||||
use super::{
|
||||
explain_borrow::BorrowExplanation, FnSelfUseKind, IncludingDowncast, RegionName,
|
||||
RegionNameSource, UseSpans,
|
||||
explain_borrow::{BorrowExplanation, LaterUseKind},
|
||||
FnSelfUseKind, IncludingDowncast, RegionName, RegionNameSource, UseSpans,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -768,9 +770,92 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
Some((issued_span, span)),
|
||||
);
|
||||
|
||||
self.suggest_using_local_if_applicable(
|
||||
&mut err,
|
||||
location,
|
||||
(place, span),
|
||||
gen_borrow_kind,
|
||||
issued_borrow,
|
||||
explanation,
|
||||
);
|
||||
|
||||
err
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self, err))]
|
||||
fn suggest_using_local_if_applicable(
|
||||
&self,
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
location: Location,
|
||||
(place, span): (Place<'tcx>, Span),
|
||||
gen_borrow_kind: BorrowKind,
|
||||
issued_borrow: &BorrowData<'tcx>,
|
||||
explanation: BorrowExplanation,
|
||||
) {
|
||||
let used_in_call =
|
||||
matches!(explanation, BorrowExplanation::UsedLater(LaterUseKind::Call, _call_span, _));
|
||||
if !used_in_call {
|
||||
debug!("not later used in call");
|
||||
return;
|
||||
}
|
||||
|
||||
let outer_call_loc =
|
||||
if let TwoPhaseActivation::ActivatedAt(loc) = issued_borrow.activation_location {
|
||||
loc
|
||||
} else {
|
||||
issued_borrow.reserve_location
|
||||
};
|
||||
let outer_call_stmt = self.body.stmt_at(outer_call_loc);
|
||||
|
||||
let inner_param_location = location;
|
||||
let Some(inner_param_stmt) = self.body.stmt_at(inner_param_location).left() else {
|
||||
debug!("`inner_param_location` {:?} is not for a statement", inner_param_location);
|
||||
return;
|
||||
};
|
||||
let Some(&inner_param) = inner_param_stmt.kind.as_assign().map(|(p, _)| p) else {
|
||||
debug!(
|
||||
"`inner_param_location` {:?} is not for an assignment: {:?}",
|
||||
inner_param_location, inner_param_stmt
|
||||
);
|
||||
return;
|
||||
};
|
||||
let inner_param_uses = find_all_local_uses::find(self.body, inner_param.local);
|
||||
let Some((inner_call_loc,inner_call_term)) = inner_param_uses.into_iter().find_map(|loc| {
|
||||
let Either::Right(term) = self.body.stmt_at(loc) else {
|
||||
debug!("{:?} is a statement, so it can't be a call", loc);
|
||||
return None;
|
||||
};
|
||||
let TerminatorKind::Call { args, .. } = &term.kind else {
|
||||
debug!("not a call: {:?}", term);
|
||||
return None;
|
||||
};
|
||||
debug!("checking call args for uses of inner_param: {:?}", args);
|
||||
if args.contains(&Operand::Move(inner_param)) {
|
||||
Some((loc,term))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}) else {
|
||||
debug!("no uses of inner_param found as a by-move call arg");
|
||||
return;
|
||||
};
|
||||
debug!("===> outer_call_loc = {:?}, inner_call_loc = {:?}", outer_call_loc, inner_call_loc);
|
||||
|
||||
let inner_call_span = inner_call_term.source_info.span;
|
||||
let outer_call_span = outer_call_stmt.either(|s| s.source_info, |t| t.source_info).span;
|
||||
if outer_call_span == inner_call_span || !outer_call_span.contains(inner_call_span) {
|
||||
// FIXME: This stops the suggestion in some cases where it should be emitted.
|
||||
// Fix the spans for those cases so it's emitted correctly.
|
||||
debug!(
|
||||
"outer span {:?} does not strictly contain inner span {:?}",
|
||||
outer_call_span, inner_call_span
|
||||
);
|
||||
return;
|
||||
}
|
||||
err.span_help(inner_call_span, "try adding a local storing this argument...");
|
||||
err.span_help(outer_call_span, "...and then using that local as the argument to this call");
|
||||
}
|
||||
|
||||
fn suggest_split_at_mut_if_applicable(
|
||||
&self,
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
use std::collections::BTreeSet;
|
||||
|
||||
use rustc_middle::mir::visit::{PlaceContext, Visitor};
|
||||
use rustc_middle::mir::{Body, Local, Location};
|
||||
|
||||
/// Find all uses of (including assignments to) a [`Local`].
|
||||
///
|
||||
/// Uses `BTreeSet` so output is deterministic.
|
||||
pub(super) fn find<'tcx>(body: &Body<'tcx>, local: Local) -> BTreeSet<Location> {
|
||||
let mut visitor = AllLocalUsesVisitor { for_local: local, uses: BTreeSet::default() };
|
||||
visitor.visit_body(body);
|
||||
visitor.uses
|
||||
}
|
||||
|
||||
struct AllLocalUsesVisitor {
|
||||
for_local: Local,
|
||||
uses: BTreeSet<Location>,
|
||||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for AllLocalUsesVisitor {
|
||||
fn visit_local(&mut self, local: &Local, _context: PlaceContext, location: Location) {
|
||||
if *local == self.for_local {
|
||||
self.uses.insert(location);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@ use rustc_target::abi::VariantIdx;
|
|||
use super::borrow_set::BorrowData;
|
||||
use super::MirBorrowckCtxt;
|
||||
|
||||
mod find_all_local_uses;
|
||||
mod find_use;
|
||||
mod outlives_suggestion;
|
||||
mod region_name;
|
||||
|
|
|
@ -384,6 +384,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
sub_r,
|
||||
sup_origin,
|
||||
sup_r,
|
||||
_,
|
||||
) => {
|
||||
if sub_r.is_placeholder() {
|
||||
self.report_placeholder_failure(sub_origin, sub_r, sup_r).emit();
|
||||
|
@ -464,7 +465,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
errors.sort_by_key(|u| match *u {
|
||||
RegionResolutionError::ConcreteFailure(ref sro, _, _) => sro.span(),
|
||||
RegionResolutionError::GenericBoundFailure(ref sro, _, _) => sro.span(),
|
||||
RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _) => rvo.span(),
|
||||
RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _, _) => rvo.span(),
|
||||
RegionResolutionError::UpperBoundUniverseConflict(_, ref rvo, _, _, _) => rvo.span(),
|
||||
});
|
||||
errors
|
||||
|
|
|
@ -67,7 +67,7 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> {
|
|||
pub fn regions(&self) -> Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)> {
|
||||
match (&self.error, self.regions) {
|
||||
(Some(ConcreteFailure(origin, sub, sup)), None) => Some((origin.span(), sub, sup)),
|
||||
(Some(SubSupConflict(_, _, origin, sub, _, sup)), None) => {
|
||||
(Some(SubSupConflict(_, _, origin, sub, _, sup, _)), None) => {
|
||||
Some((origin.span(), sub, sup))
|
||||
}
|
||||
(None, Some((span, sub, sup))) => Some((span, sub, sup)),
|
||||
|
|
|
@ -34,6 +34,7 @@ impl NiceRegionError<'me, 'tcx> {
|
|||
sub_placeholder @ ty::RePlaceholder(_),
|
||||
_,
|
||||
sup_placeholder @ ty::RePlaceholder(_),
|
||||
_,
|
||||
)) => self.try_report_trait_placeholder_mismatch(
|
||||
Some(self.tcx().mk_region(ty::ReVar(*vid))),
|
||||
cause,
|
||||
|
@ -49,6 +50,7 @@ impl NiceRegionError<'me, 'tcx> {
|
|||
sub_placeholder @ ty::RePlaceholder(_),
|
||||
_,
|
||||
_,
|
||||
_,
|
||||
)) => self.try_report_trait_placeholder_mismatch(
|
||||
Some(self.tcx().mk_region(ty::ReVar(*vid))),
|
||||
cause,
|
||||
|
@ -64,6 +66,7 @@ impl NiceRegionError<'me, 'tcx> {
|
|||
_,
|
||||
_,
|
||||
sup_placeholder @ ty::RePlaceholder(_),
|
||||
_,
|
||||
)) => self.try_report_trait_placeholder_mismatch(
|
||||
Some(self.tcx().mk_region(ty::ReVar(*vid))),
|
||||
cause,
|
||||
|
@ -79,6 +82,7 @@ impl NiceRegionError<'me, 'tcx> {
|
|||
_,
|
||||
SubregionOrigin::Subtype(box TypeTrace { cause, values }),
|
||||
sup_placeholder @ ty::RePlaceholder(_),
|
||||
_,
|
||||
)) => self.try_report_trait_placeholder_mismatch(
|
||||
Some(self.tcx().mk_region(ty::ReVar(*vid))),
|
||||
cause,
|
||||
|
|
|
@ -10,7 +10,8 @@ use rustc_hir::def_id::DefId;
|
|||
use rustc_hir::intravisit::{walk_ty, ErasedMap, NestedVisitorMap, Visitor};
|
||||
use rustc_hir::{self as hir, GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, TyKind};
|
||||
use rustc_middle::ty::{
|
||||
self, AssocItemContainer, RegionKind, Ty, TyCtxt, TypeFoldable, TypeVisitor,
|
||||
self, AssocItemContainer, RegionKind, StaticLifetimeVisitor, Ty, TyCtxt, TypeFoldable,
|
||||
TypeVisitor,
|
||||
};
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::{MultiSpan, Span};
|
||||
|
@ -23,7 +24,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
pub(super) fn try_report_static_impl_trait(&self) -> Option<ErrorReported> {
|
||||
debug!("try_report_static_impl_trait(error={:?})", self.error);
|
||||
let tcx = self.tcx();
|
||||
let (var_origin, sub_origin, sub_r, sup_origin, sup_r) = match self.error.as_ref()? {
|
||||
let (var_origin, sub_origin, sub_r, sup_origin, sup_r, spans) = match self.error.as_ref()? {
|
||||
RegionResolutionError::SubSupConflict(
|
||||
_,
|
||||
var_origin,
|
||||
|
@ -31,8 +32,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
sub_r,
|
||||
sup_origin,
|
||||
sup_r,
|
||||
spans,
|
||||
) if **sub_r == RegionKind::ReStatic => {
|
||||
(var_origin, sub_origin, sub_r, sup_origin, sup_r)
|
||||
(var_origin, sub_origin, sub_r, sup_origin, sup_r, spans)
|
||||
}
|
||||
RegionResolutionError::ConcreteFailure(
|
||||
SubregionOrigin::Subtype(box TypeTrace { cause, .. }),
|
||||
|
@ -74,7 +76,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
err.span_label(
|
||||
cause.span,
|
||||
&format!(
|
||||
"...is captured and required to live as long as `'static` here \
|
||||
"...is used and required to live as long as `'static` here \
|
||||
because of an implicit lifetime bound on the {}",
|
||||
match ctxt.assoc_item.container {
|
||||
AssocItemContainer::TraitContainer(id) =>
|
||||
|
@ -123,56 +125,101 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
param_name,
|
||||
lifetime,
|
||||
);
|
||||
err.span_label(param.param_ty_span, &format!("this data with {}...", lifetime));
|
||||
|
||||
let (mention_influencer, influencer_point) =
|
||||
if sup_origin.span().overlaps(param.param_ty_span) {
|
||||
// Account for `async fn` like in `async-await/issues/issue-62097.rs`.
|
||||
// The desugaring of `async `fn`s causes `sup_origin` and `param` to point at the same
|
||||
// place (but with different `ctxt`, hence `overlaps` instead of `==` above).
|
||||
//
|
||||
// This avoids the following:
|
||||
//
|
||||
// LL | pub async fn run_dummy_fn(&self) {
|
||||
// | ^^^^^
|
||||
// | |
|
||||
// | this data with an anonymous lifetime `'_`...
|
||||
// | ...is captured here...
|
||||
(false, sup_origin.span())
|
||||
} else {
|
||||
(!sup_origin.span().overlaps(return_sp), param.param_ty_span)
|
||||
};
|
||||
err.span_label(influencer_point, &format!("this data with {}...", lifetime));
|
||||
|
||||
debug!("try_report_static_impl_trait: param_info={:?}", param);
|
||||
|
||||
// We try to make the output have fewer overlapping spans if possible.
|
||||
if (sp == sup_origin.span() || !return_sp.overlaps(sup_origin.span()))
|
||||
&& sup_origin.span() != return_sp
|
||||
{
|
||||
// FIXME: account for `async fn` like in `async-await/issues/issue-62097.rs`
|
||||
let mut spans = spans.clone();
|
||||
|
||||
// Customize the spans and labels depending on their relative order so
|
||||
// that split sentences flow correctly.
|
||||
if sup_origin.span().overlaps(return_sp) && sp == sup_origin.span() {
|
||||
// Avoid the following:
|
||||
//
|
||||
// error: cannot infer an appropriate lifetime
|
||||
// --> $DIR/must_outlive_least_region_or_bound.rs:18:50
|
||||
// |
|
||||
// LL | fn foo(x: &i32) -> Box<dyn Debug> { Box::new(x) }
|
||||
// | ---- ---------^-
|
||||
//
|
||||
// and instead show:
|
||||
//
|
||||
// error: cannot infer an appropriate lifetime
|
||||
// --> $DIR/must_outlive_least_region_or_bound.rs:18:50
|
||||
// |
|
||||
// LL | fn foo(x: &i32) -> Box<dyn Debug> { Box::new(x) }
|
||||
// | ---- ^
|
||||
err.span_label(
|
||||
sup_origin.span(),
|
||||
"...is captured here, requiring it to live as long as `'static`",
|
||||
);
|
||||
if mention_influencer {
|
||||
spans.push(sup_origin.span());
|
||||
}
|
||||
// We dedup the spans *ignoring* expansion context.
|
||||
spans.sort();
|
||||
spans.dedup_by_key(|span| (span.lo(), span.hi()));
|
||||
|
||||
// We try to make the output have fewer overlapping spans if possible.
|
||||
let require_msg = if spans.is_empty() {
|
||||
"...is used and required to live as long as `'static` here"
|
||||
} else {
|
||||
err.span_label(sup_origin.span(), "...is captured here...");
|
||||
if return_sp < sup_origin.span() {
|
||||
"...and is required to live as long as `'static` here"
|
||||
};
|
||||
let require_span =
|
||||
if sup_origin.span().overlaps(return_sp) { sup_origin.span() } else { return_sp };
|
||||
|
||||
for span in &spans {
|
||||
err.span_label(*span, "...is used here...");
|
||||
}
|
||||
|
||||
if spans.iter().any(|sp| sp.overlaps(return_sp) || *sp > return_sp) {
|
||||
// If any of the "captured here" labels appears on the same line or after
|
||||
// `require_span`, we put it on a note to ensure the text flows by appearing
|
||||
// always at the end.
|
||||
err.span_note(require_span, require_msg);
|
||||
} else {
|
||||
// We don't need a note, it's already at the end, it can be shown as a `span_label`.
|
||||
err.span_label(require_span, require_msg);
|
||||
}
|
||||
|
||||
if let SubregionOrigin::RelateParamBound(_, _, Some(bound)) = sub_origin {
|
||||
err.span_note(*bound, "`'static` lifetime requirement introduced by this bound");
|
||||
}
|
||||
if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = sub_origin {
|
||||
if let ObligationCauseCode::ReturnValue(hir_id)
|
||||
| ObligationCauseCode::BlockTailExpression(hir_id) = &cause.code
|
||||
{
|
||||
let parent_id = tcx.hir().get_parent_item(*hir_id);
|
||||
if let Some(fn_decl) = tcx.hir().fn_decl_by_hir_id(parent_id) {
|
||||
let mut span: MultiSpan = fn_decl.output.span().into();
|
||||
let mut add_label = true;
|
||||
if let hir::FnRetTy::Return(ty) = fn_decl.output {
|
||||
let mut v = StaticLifetimeVisitor(vec![], tcx.hir());
|
||||
v.visit_ty(ty);
|
||||
if !v.0.is_empty() {
|
||||
span = v.0.clone().into();
|
||||
for sp in v.0 {
|
||||
span.push_span_label(
|
||||
sp,
|
||||
"`'static` requirement introduced here".to_string(),
|
||||
);
|
||||
}
|
||||
add_label = false;
|
||||
}
|
||||
}
|
||||
if add_label {
|
||||
span.push_span_label(
|
||||
fn_decl.output.span(),
|
||||
"requirement introduced by this return type".to_string(),
|
||||
);
|
||||
}
|
||||
span.push_span_label(
|
||||
cause.span,
|
||||
"because of this returned expression".to_string(),
|
||||
);
|
||||
err.span_note(
|
||||
return_sp,
|
||||
"...and is required to live as long as `'static` here",
|
||||
);
|
||||
} else {
|
||||
err.span_label(
|
||||
return_sp,
|
||||
"...and is required to live as long as `'static` here",
|
||||
span,
|
||||
"`'static` lifetime requirement introduced by the return type",
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err.span_label(
|
||||
return_sp,
|
||||
"...is captured and required to live as long as `'static` here",
|
||||
);
|
||||
}
|
||||
|
||||
let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id);
|
||||
|
|
|
@ -28,6 +28,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
|||
_sub,
|
||||
sup_origin,
|
||||
_sup,
|
||||
_,
|
||||
) = error.clone()
|
||||
{
|
||||
if let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) = (&sup_origin, &sub_origin) {
|
||||
|
|
|
@ -19,6 +19,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
|
|||
use rustc_middle::ty::{ReEarlyBound, ReEmpty, ReErased, ReFree, ReStatic};
|
||||
use rustc_middle::ty::{ReLateBound, RePlaceholder, ReVar};
|
||||
use rustc_middle::ty::{Region, RegionVid};
|
||||
use rustc_span::Span;
|
||||
use std::fmt;
|
||||
|
||||
/// This function performs lexical region resolution given a complete
|
||||
|
@ -96,6 +97,7 @@ pub enum RegionResolutionError<'tcx> {
|
|||
Region<'tcx>,
|
||||
SubregionOrigin<'tcx>,
|
||||
Region<'tcx>,
|
||||
Vec<Span>, // All the influences on a given value that didn't meet its constraints.
|
||||
),
|
||||
|
||||
/// Indicates a `'b: 'a` constraint where `'a` is in a universe that
|
||||
|
@ -567,7 +569,30 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
|
|||
// if this rule starts to create problems we'll
|
||||
// have to revisit this portion of the code and
|
||||
// think hard about it. =) -- nikomatsakis
|
||||
self.collect_error_for_expanding_node(graph, &mut dup_vec, node_vid, errors);
|
||||
|
||||
// Obtain the spans for all the places that can
|
||||
// influence the constraints on this value for
|
||||
// richer diagnostics in `static_impl_trait`.
|
||||
let influences: Vec<Span> = self
|
||||
.data
|
||||
.constraints
|
||||
.iter()
|
||||
.filter_map(|(constraint, origin)| match (constraint, origin) {
|
||||
(
|
||||
Constraint::VarSubVar(_, sup),
|
||||
SubregionOrigin::DataBorrowed(_, sp),
|
||||
) if sup == &node_vid => Some(*sp),
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
|
||||
self.collect_error_for_expanding_node(
|
||||
graph,
|
||||
&mut dup_vec,
|
||||
node_vid,
|
||||
errors,
|
||||
influences,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -621,6 +646,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
|
|||
dup_vec: &mut IndexVec<RegionVid, Option<RegionVid>>,
|
||||
node_idx: RegionVid,
|
||||
errors: &mut Vec<RegionResolutionError<'tcx>>,
|
||||
influences: Vec<Span>,
|
||||
) {
|
||||
// Errors in expanding nodes result from a lower-bound that is
|
||||
// not contained by an upper-bound.
|
||||
|
@ -667,6 +693,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
|
|||
sup: {:?}",
|
||||
origin, node_idx, lower_bound.region, upper_bound.region
|
||||
);
|
||||
|
||||
errors.push(RegionResolutionError::SubSupConflict(
|
||||
node_idx,
|
||||
origin,
|
||||
|
@ -674,6 +701,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
|
|||
lower_bound.region,
|
||||
upper_bound.origin.clone(),
|
||||
upper_bound.region,
|
||||
influences,
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ use crate::ty::print::{FmtPrinter, Printer};
|
|||
use crate::ty::subst::{Subst, SubstsRef};
|
||||
use crate::ty::{self, List, Ty, TyCtxt};
|
||||
use crate::ty::{AdtDef, InstanceDef, Region, ScalarInt, UserTypeAnnotationIndex};
|
||||
|
||||
use rustc_hir::def::{CtorKind, Namespace};
|
||||
use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
|
||||
use rustc_hir::{self, GeneratorKind};
|
||||
|
@ -30,6 +31,9 @@ use rustc_serialize::{Decodable, Encodable};
|
|||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_target::asm::InlineAsmRegOrRegClass;
|
||||
|
||||
use either::Either;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::convert::TryInto;
|
||||
use std::fmt::{self, Debug, Display, Formatter, Write};
|
||||
|
@ -503,6 +507,16 @@ impl<'tcx> Body<'tcx> {
|
|||
Location { block: bb, statement_index: self[bb].statements.len() }
|
||||
}
|
||||
|
||||
pub fn stmt_at(&self, location: Location) -> Either<&Statement<'tcx>, &Terminator<'tcx>> {
|
||||
let Location { block, statement_index } = location;
|
||||
let block_data = &self.basic_blocks[block];
|
||||
block_data
|
||||
.statements
|
||||
.get(statement_index)
|
||||
.map(Either::Left)
|
||||
.unwrap_or_else(|| Either::Right(block_data.terminator()))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn predecessors(&self) -> &Predecessors {
|
||||
self.predecessor_cache.compute(&self.basic_blocks)
|
||||
|
|
|
@ -1481,40 +1481,8 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
scope_def_id: LocalDefId,
|
||||
) -> Vec<&'tcx hir::Ty<'tcx>> {
|
||||
let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
|
||||
let hir_output = match self.hir().get(hir_id) {
|
||||
Node::Item(hir::Item {
|
||||
kind:
|
||||
ItemKind::Fn(
|
||||
hir::FnSig {
|
||||
decl: hir::FnDecl { output: hir::FnRetTy::Return(ty), .. },
|
||||
..
|
||||
},
|
||||
..,
|
||||
),
|
||||
..
|
||||
})
|
||||
| Node::ImplItem(hir::ImplItem {
|
||||
kind:
|
||||
hir::ImplItemKind::Fn(
|
||||
hir::FnSig {
|
||||
decl: hir::FnDecl { output: hir::FnRetTy::Return(ty), .. },
|
||||
..
|
||||
},
|
||||
_,
|
||||
),
|
||||
..
|
||||
})
|
||||
| Node::TraitItem(hir::TraitItem {
|
||||
kind:
|
||||
hir::TraitItemKind::Fn(
|
||||
hir::FnSig {
|
||||
decl: hir::FnDecl { output: hir::FnRetTy::Return(ty), .. },
|
||||
..
|
||||
},
|
||||
_,
|
||||
),
|
||||
..
|
||||
}) => ty,
|
||||
let hir_output = match self.hir().fn_decl_by_hir_id(hir_id) {
|
||||
Some(hir::FnDecl { output: hir::FnRetTy::Return(ty), .. }) => ty,
|
||||
_ => return vec![],
|
||||
};
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder};
|
|||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{QPath, TyKind, WhereBoundPredicate, WherePredicate};
|
||||
use rustc_span::Span;
|
||||
|
||||
impl<'tcx> TyS<'tcx> {
|
||||
/// Similar to `TyS::is_primitive`, but also considers inferred numeric values to be primitive.
|
||||
|
@ -432,3 +433,22 @@ impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> {
|
|||
hir::intravisit::walk_ty(self, ty);
|
||||
}
|
||||
}
|
||||
|
||||
/// Collect al types that have an implicit `'static` obligation that we could suggest `'_` for.
|
||||
pub struct StaticLifetimeVisitor<'tcx>(pub Vec<Span>, pub crate::hir::map::Map<'tcx>);
|
||||
|
||||
impl<'v> hir::intravisit::Visitor<'v> for StaticLifetimeVisitor<'v> {
|
||||
type Map = rustc_hir::intravisit::ErasedMap<'v>;
|
||||
|
||||
fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<Self::Map> {
|
||||
hir::intravisit::NestedVisitorMap::None
|
||||
}
|
||||
|
||||
fn visit_lifetime(&mut self, lt: &'v hir::Lifetime) {
|
||||
if let hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static =
|
||||
lt.name
|
||||
{
|
||||
self.0.push(lt.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -162,14 +162,16 @@ impl<T, const N: usize> AsMut<[T]> for [T; N] {
|
|||
}
|
||||
|
||||
#[stable(feature = "array_borrow", since = "1.4.0")]
|
||||
impl<T, const N: usize> Borrow<[T]> for [T; N] {
|
||||
#[rustc_const_unstable(feature = "const_borrow", issue = "91522")]
|
||||
impl<T, const N: usize> const Borrow<[T]> for [T; N] {
|
||||
fn borrow(&self) -> &[T] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "array_borrow", since = "1.4.0")]
|
||||
impl<T, const N: usize> BorrowMut<[T]> for [T; N] {
|
||||
#[rustc_const_unstable(feature = "const_borrow", issue = "91522")]
|
||||
impl<T, const N: usize> const BorrowMut<[T]> for [T; N] {
|
||||
fn borrow_mut(&mut self) -> &mut [T] {
|
||||
self
|
||||
}
|
||||
|
|
|
@ -205,7 +205,8 @@ pub trait BorrowMut<Borrowed: ?Sized>: Borrow<Borrowed> {
|
|||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Borrow<T> for T {
|
||||
#[rustc_const_unstable(feature = "const_borrow", issue = "91522")]
|
||||
impl<T: ?Sized> const Borrow<T> for T {
|
||||
#[rustc_diagnostic_item = "noop_method_borrow"]
|
||||
fn borrow(&self) -> &T {
|
||||
self
|
||||
|
@ -213,28 +214,32 @@ impl<T: ?Sized> Borrow<T> for T {
|
|||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> BorrowMut<T> for T {
|
||||
#[rustc_const_unstable(feature = "const_borrow", issue = "91522")]
|
||||
impl<T: ?Sized> const BorrowMut<T> for T {
|
||||
fn borrow_mut(&mut self) -> &mut T {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Borrow<T> for &T {
|
||||
#[rustc_const_unstable(feature = "const_borrow", issue = "91522")]
|
||||
impl<T: ?Sized> const Borrow<T> for &T {
|
||||
fn borrow(&self) -> &T {
|
||||
&**self
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Borrow<T> for &mut T {
|
||||
#[rustc_const_unstable(feature = "const_borrow", issue = "91522")]
|
||||
impl<T: ?Sized> const Borrow<T> for &mut T {
|
||||
fn borrow(&self) -> &T {
|
||||
&**self
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> BorrowMut<T> for &mut T {
|
||||
#[rustc_const_unstable(feature = "const_borrow", issue = "91522")]
|
||||
impl<T: ?Sized> const BorrowMut<T> for &mut T {
|
||||
fn borrow_mut(&mut self) -> &mut T {
|
||||
&mut **self
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#![allow(unused_imports)] // items are used by the macro
|
||||
#![allow(unused_imports, unused_macros)] // items are used by the macro
|
||||
|
||||
use crate::cell::UnsafeCell;
|
||||
use crate::future::{poll_fn, Future};
|
||||
|
@ -45,59 +45,104 @@ use crate::task::{Context, Poll};
|
|||
/// # };
|
||||
/// ```
|
||||
#[unstable(feature = "future_join", issue = "91642")]
|
||||
pub macro join {
|
||||
( $($fut:expr),* $(,)?) => {
|
||||
join! { @count: (), @futures: {}, @rest: ($($fut,)*) }
|
||||
},
|
||||
// Recurse until we have the position of each future in the tuple
|
||||
(
|
||||
// A token for each future that has been expanded: "_ _ _"
|
||||
@count: ($($count:tt)*),
|
||||
// Futures and their positions in the tuple: "{ a => (_), b => (_ _)) }"
|
||||
@futures: { $($fut:tt)* },
|
||||
// Take a future from @rest to expand
|
||||
@rest: ($current:expr, $($rest:tt)*)
|
||||
) => {
|
||||
join! {
|
||||
@count: ($($count)* _),
|
||||
@futures: { $($fut)* $current => ($($count)*), },
|
||||
@rest: ($($rest)*)
|
||||
pub macro join( $($fut:expr),+ $(,)? ) {
|
||||
// Funnel through an internal macro not to leak implementation details.
|
||||
join_internal! {
|
||||
current_position: []
|
||||
futures_and_positions: []
|
||||
munching: [ $($fut)+ ]
|
||||
}
|
||||
}
|
||||
},
|
||||
// Now generate the output future
|
||||
(
|
||||
@count: ($($count:tt)*),
|
||||
@futures: {
|
||||
$( $(@$f:tt)? $fut:expr => ( $($pos:tt)* ), )*
|
||||
},
|
||||
@rest: ()
|
||||
) => {
|
||||
async move {
|
||||
let mut futures = ( $( MaybeDone::Future($fut), )* );
|
||||
|
||||
// FIXME(danielhenrymantilla): a private macro should need no stability guarantee.
|
||||
#[unstable(feature = "future_join", issue = "91642")]
|
||||
/// To be able to *name* the i-th future in the tuple (say we want the .4-th),
|
||||
/// the following trick will be used: `let (_, _, _, _, it, ..) = tuple;`
|
||||
/// In order to do that, we need to generate a `i`-long repetition of `_`,
|
||||
/// for each i-th fut. Hence the recursive muncher approach.
|
||||
macro join_internal {
|
||||
// Recursion step: map each future with its "position" (underscore count).
|
||||
(
|
||||
// Accumulate a token for each future that has been expanded: "_ _ _".
|
||||
current_position: [
|
||||
$($underscores:tt)*
|
||||
]
|
||||
// Accumulate Futures and their positions in the tuple: `_0th () _1st ( _ ) …`.
|
||||
futures_and_positions: [
|
||||
$($acc:tt)*
|
||||
]
|
||||
// Munch one future.
|
||||
munching: [
|
||||
$current:tt
|
||||
$($rest:tt)*
|
||||
]
|
||||
) => (
|
||||
join_internal! {
|
||||
current_position: [
|
||||
$($underscores)*
|
||||
_
|
||||
]
|
||||
futures_and_positions: [
|
||||
$($acc)*
|
||||
$current ( $($underscores)* )
|
||||
]
|
||||
munching: [
|
||||
$($rest)*
|
||||
]
|
||||
}
|
||||
),
|
||||
|
||||
// End of recursion: generate the output future.
|
||||
(
|
||||
current_position: $_:tt
|
||||
futures_and_positions: [
|
||||
$(
|
||||
$fut_expr:tt ( $($pos:tt)* )
|
||||
)*
|
||||
]
|
||||
// Nothing left to munch.
|
||||
munching: []
|
||||
) => (
|
||||
match ( $( MaybeDone::Future($fut_expr), )* ) { futures => async {
|
||||
let mut futures = futures;
|
||||
// SAFETY: this is `pin_mut!`.
|
||||
let mut futures = unsafe { Pin::new_unchecked(&mut futures) };
|
||||
poll_fn(move |cx| {
|
||||
let mut done = true;
|
||||
|
||||
// For each `fut`, pin-project to it, and poll it.
|
||||
$(
|
||||
let ( $($pos,)* fut, .. ) = &mut futures;
|
||||
|
||||
// SAFETY: The futures are never moved
|
||||
done &= unsafe { Pin::new_unchecked(fut).poll(cx).is_ready() };
|
||||
// SAFETY: pinning projection
|
||||
let fut = unsafe {
|
||||
futures.as_mut().map_unchecked_mut(|it| {
|
||||
let ( $($pos,)* fut, .. ) = it;
|
||||
fut
|
||||
})
|
||||
};
|
||||
// Despite how tempting it may be to `let () = fut.poll(cx).ready()?;`
|
||||
// doing so would defeat the point of `join!`: to start polling eagerly all
|
||||
// of the futures, to allow parallelizing the waits.
|
||||
done &= fut.poll(cx).is_ready();
|
||||
)*
|
||||
if !done {
|
||||
return Poll::Pending;
|
||||
}
|
||||
// All ready; time to extract all the outputs.
|
||||
|
||||
if done {
|
||||
// Extract all the outputs
|
||||
Poll::Ready(($({
|
||||
let ( $($pos,)* fut, .. ) = &mut futures;
|
||||
|
||||
// SAFETY: `.take_output()` does not break the `Pin` invariants for that `fut`.
|
||||
let futures = unsafe {
|
||||
futures.as_mut().get_unchecked_mut()
|
||||
};
|
||||
Poll::Ready(
|
||||
($(
|
||||
{
|
||||
let ( $($pos,)* fut, .. ) = &mut *futures;
|
||||
fut.take_output().unwrap()
|
||||
}),*))
|
||||
} else {
|
||||
Poll::Pending
|
||||
}
|
||||
),*) // <- no trailing comma since we don't want 1-tuples.
|
||||
)
|
||||
}).await
|
||||
}
|
||||
}
|
||||
}}
|
||||
),
|
||||
}
|
||||
|
||||
/// Future used by `join!` that stores it's output to
|
||||
|
@ -109,14 +154,14 @@ pub macro join {
|
|||
pub enum MaybeDone<F: Future> {
|
||||
Future(F),
|
||||
Done(F::Output),
|
||||
Took,
|
||||
Taken,
|
||||
}
|
||||
|
||||
#[unstable(feature = "future_join", issue = "91642")]
|
||||
impl<F: Future> MaybeDone<F> {
|
||||
pub fn take_output(&mut self) -> Option<F::Output> {
|
||||
match &*self {
|
||||
MaybeDone::Done(_) => match mem::replace(self, Self::Took) {
|
||||
match *self {
|
||||
MaybeDone::Done(_) => match mem::replace(self, Self::Taken) {
|
||||
MaybeDone::Done(val) => Some(val),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
|
@ -132,13 +177,14 @@ impl<F: Future> Future for MaybeDone<F> {
|
|||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
// SAFETY: pinning in structural for `f`
|
||||
unsafe {
|
||||
match self.as_mut().get_unchecked_mut() {
|
||||
MaybeDone::Future(f) => match Pin::new_unchecked(f).poll(cx) {
|
||||
Poll::Ready(val) => self.set(Self::Done(val)),
|
||||
Poll::Pending => return Poll::Pending,
|
||||
},
|
||||
// Do not mix match ergonomics with unsafe.
|
||||
match *self.as_mut().get_unchecked_mut() {
|
||||
MaybeDone::Future(ref mut f) => {
|
||||
let val = Pin::new_unchecked(f).poll(cx).ready()?;
|
||||
self.set(Self::Done(val));
|
||||
}
|
||||
MaybeDone::Done(_) => {}
|
||||
MaybeDone::Took => unreachable!(),
|
||||
MaybeDone::Taken => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -137,6 +137,11 @@ pub fn spin_loop() {
|
|||
unsafe { crate::arch::arm::__yield() };
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
|
||||
{
|
||||
crate::arch::riscv::pause();
|
||||
}
|
||||
}
|
||||
|
||||
/// An identity function that *__hints__* to the compiler to be maximally pessimistic about what
|
||||
|
|
|
@ -1523,8 +1523,15 @@ impl<T: Clone> Option<&T> {
|
|||
/// ```
|
||||
#[must_use = "`self` will be dropped if the result is not used"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn cloned(self) -> Option<T> {
|
||||
self.map(|t| t.clone())
|
||||
#[rustc_const_unstable(feature = "const_option_cloned", issue = "91582")]
|
||||
pub const fn cloned(self) -> Option<T>
|
||||
where
|
||||
T: ~const Clone,
|
||||
{
|
||||
match self {
|
||||
Some(t) => Some(t.clone()),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1541,9 +1548,17 @@ impl<T: Clone> Option<&mut T> {
|
|||
/// let cloned = opt_x.cloned();
|
||||
/// assert_eq!(cloned, Some(12));
|
||||
/// ```
|
||||
#[must_use = "`self` will be dropped if the result is not used"]
|
||||
#[stable(since = "1.26.0", feature = "option_ref_mut_cloned")]
|
||||
pub fn cloned(self) -> Option<T> {
|
||||
self.map(|t| t.clone())
|
||||
#[rustc_const_unstable(feature = "const_option_cloned", issue = "91582")]
|
||||
pub const fn cloned(self) -> Option<T>
|
||||
where
|
||||
T: ~const Clone,
|
||||
{
|
||||
match self {
|
||||
Some(t) => Some(t.clone()),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -64,6 +64,40 @@ fn test_join() {
|
|||
});
|
||||
}
|
||||
|
||||
/// Tests that `join!(…)` behaves "like a function": evaluating its arguments
|
||||
/// before applying any of its own logic.
|
||||
///
|
||||
/// _e.g._, `join!(async_fn(&borrowed), …)` does not consume `borrowed`;
|
||||
/// and `join!(opt_fut?, …)` does let that `?` refer to the callsite scope.
|
||||
mod test_join_function_like_value_arg_semantics {
|
||||
use super::*;
|
||||
|
||||
async fn async_fn(_: impl Sized) {}
|
||||
|
||||
// no need to _run_ this test, just to compile it.
|
||||
fn _join_does_not_unnecessarily_move_mentioned_bindings() {
|
||||
let not_copy = vec![()];
|
||||
let _ = join!(async_fn(¬_copy)); // should not move `not_copy`
|
||||
let _ = ¬_copy; // OK
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn join_lets_control_flow_effects_such_as_try_flow_through() {
|
||||
let maybe_fut = None;
|
||||
if false {
|
||||
*&mut { maybe_fut } = Some(async {});
|
||||
loop {}
|
||||
}
|
||||
assert!(Option::is_none(&try { join!(maybe_fut?, async { unreachable!() }) }));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn join_is_able_to_handle_temporaries() {
|
||||
let _ = join!(async_fn(&String::from("temporary")));
|
||||
let () = block_on(join!(async_fn(&String::from("temporary"))));
|
||||
}
|
||||
}
|
||||
|
||||
fn block_on(fut: impl Future) {
|
||||
struct Waker;
|
||||
impl Wake for Waker {
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#![feature(str_internals)]
|
||||
#![feature(test)]
|
||||
#![feature(trusted_len)]
|
||||
#![feature(try_blocks)]
|
||||
#![feature(try_trait_v2)]
|
||||
#![feature(slice_internals)]
|
||||
#![feature(slice_partition_dedup)]
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit cfba59fccd90b3b52a614120834320f764ab08d1
|
||||
Subproject commit b70ae88ef2a6c83acad0a1e83d5bd78f9655fd05
|
|
@ -4,7 +4,7 @@ error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime
|
|||
LL | fn baz<'a,'b>(x: &'a u32) -> &'static u32 {
|
||||
| ------- this data with lifetime `'a`...
|
||||
LL | bar(foo, x)
|
||||
| ----^^^---- ...is captured and required to live as long as `'static` here
|
||||
| ^^^ - ...is used and required to live as long as `'static` here
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -5,7 +5,16 @@ LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> {
|
|||
| -------- this data with lifetime `'a`...
|
||||
...
|
||||
LL | bar(foo, x)
|
||||
| ----^^^---- ...is captured and required to live as long as `'static` here
|
||||
| ^^^ - ...is used and required to live as long as `'static` here
|
||||
|
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/project-fn-ret-invariant.rs:45:37
|
||||
|
|
||||
LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> {
|
||||
| ^^^^^^^ `'static` requirement introduced here
|
||||
...
|
||||
LL | bar(foo, x)
|
||||
| ----------- because of this returned expression
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -2,12 +2,15 @@ error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'
|
|||
--> $DIR/issue-62097.rs:12:31
|
||||
|
|
||||
LL | pub async fn run_dummy_fn(&self) {
|
||||
| ^^^^^
|
||||
| |
|
||||
| this data with an anonymous lifetime `'_`...
|
||||
| ...is captured here...
|
||||
| ^^^^^ this data with an anonymous lifetime `'_`...
|
||||
LL | foo(|| self.bar()).await;
|
||||
| --- ...and is required to live as long as `'static` here
|
||||
| --- ...is used and required to live as long as `'static` here
|
||||
|
|
||||
note: `'static` lifetime requirement introduced by this bound
|
||||
--> $DIR/issue-62097.rs:4:19
|
||||
|
|
||||
LL | F: FnOnce() + 'static
|
||||
| ^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
21
src/test/ui/async-await/issues/issue-72312.nll.stderr
Normal file
21
src/test/ui/async-await/issues/issue-72312.nll.stderr
Normal file
|
@ -0,0 +1,21 @@
|
|||
error[E0521]: borrowed data escapes outside of associated function
|
||||
--> $DIR/issue-72312.rs:13:24
|
||||
|
|
||||
LL | pub async fn start(&self) {
|
||||
| -----
|
||||
| |
|
||||
| `self` is a reference that is only valid in the associated function body
|
||||
| let's call the lifetime of this reference `'1`
|
||||
...
|
||||
LL | require_static(async move {
|
||||
| ________________________^
|
||||
LL | | &self;
|
||||
LL | | });
|
||||
| | ^
|
||||
| | |
|
||||
| |_________`self` escapes the associated function body here
|
||||
| argument requires that `'1` must outlive `'static`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0521`.
|
19
src/test/ui/async-await/issues/issue-72312.rs
Normal file
19
src/test/ui/async-await/issues/issue-72312.rs
Normal file
|
@ -0,0 +1,19 @@
|
|||
// edition:2018
|
||||
fn require_static<T: 'static>(val: T) -> T {
|
||||
//~^ NOTE 'static` lifetime requirement introduced by this bound
|
||||
val
|
||||
}
|
||||
|
||||
struct Problem;
|
||||
|
||||
impl Problem {
|
||||
pub async fn start(&self) { //~ ERROR E0759
|
||||
//~^ NOTE this data with an anonymous lifetime `'_`
|
||||
//~| NOTE in this expansion of desugaring of `async` block or function
|
||||
require_static(async move { //~ NOTE ...and is required to live as long as `'static` here
|
||||
&self; //~ NOTE ...is used here...
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
23
src/test/ui/async-await/issues/issue-72312.stderr
Normal file
23
src/test/ui/async-await/issues/issue-72312.stderr
Normal file
|
@ -0,0 +1,23 @@
|
|||
error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
|
||||
--> $DIR/issue-72312.rs:10:24
|
||||
|
|
||||
LL | pub async fn start(&self) {
|
||||
| ^^^^^ this data with an anonymous lifetime `'_`...
|
||||
...
|
||||
LL | &self;
|
||||
| ----- ...is used here...
|
||||
|
|
||||
note: ...and is required to live as long as `'static` here
|
||||
--> $DIR/issue-72312.rs:13:9
|
||||
|
|
||||
LL | require_static(async move {
|
||||
| ^^^^^^^^^^^^^^
|
||||
note: `'static` lifetime requirement introduced by this bound
|
||||
--> $DIR/issue-72312.rs:2:22
|
||||
|
|
||||
LL | fn require_static<T: 'static>(val: T) -> T {
|
||||
| ^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0759`.
|
27
src/test/ui/borrowck/suggest-local-var-double-mut.rs
Normal file
27
src/test/ui/borrowck/suggest-local-var-double-mut.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
// See issue #77834.
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
mod method_syntax {
|
||||
struct Foo;
|
||||
|
||||
impl Foo {
|
||||
fn foo(&mut self, _: f32) -> i32 { todo!() }
|
||||
fn bar(&mut self) -> f32 { todo!() }
|
||||
fn baz(&mut self) {
|
||||
self.foo(self.bar()); //~ ERROR
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod fully_qualified_syntax {
|
||||
struct Foo;
|
||||
|
||||
impl Foo {
|
||||
fn foo(&mut self, _: f32) -> i32 { todo!() }
|
||||
fn bar(&mut self) -> f32 { todo!() }
|
||||
fn baz(&mut self) {
|
||||
Self::foo(self, Self::bar(self)); //~ ERROR
|
||||
}
|
||||
}
|
||||
}
|
44
src/test/ui/borrowck/suggest-local-var-double-mut.stderr
Normal file
44
src/test/ui/borrowck/suggest-local-var-double-mut.stderr
Normal file
|
@ -0,0 +1,44 @@
|
|||
error[E0499]: cannot borrow `*self` as mutable more than once at a time
|
||||
--> $DIR/suggest-local-var-double-mut.rs:12:22
|
||||
|
|
||||
LL | self.foo(self.bar());
|
||||
| ---------^^^^^^^^^^-
|
||||
| | | |
|
||||
| | | second mutable borrow occurs here
|
||||
| | first borrow later used by call
|
||||
| first mutable borrow occurs here
|
||||
|
|
||||
help: try adding a local storing this argument...
|
||||
--> $DIR/suggest-local-var-double-mut.rs:12:22
|
||||
|
|
||||
LL | self.foo(self.bar());
|
||||
| ^^^^^^^^^^
|
||||
help: ...and then using that local as the argument to this call
|
||||
--> $DIR/suggest-local-var-double-mut.rs:12:13
|
||||
|
|
||||
LL | self.foo(self.bar());
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0499]: cannot borrow `*self` as mutable more than once at a time
|
||||
--> $DIR/suggest-local-var-double-mut.rs:24:39
|
||||
|
|
||||
LL | Self::foo(self, Self::bar(self));
|
||||
| --------- ---- ^^^^ second mutable borrow occurs here
|
||||
| | |
|
||||
| | first mutable borrow occurs here
|
||||
| first borrow later used by call
|
||||
|
|
||||
help: try adding a local storing this argument...
|
||||
--> $DIR/suggest-local-var-double-mut.rs:24:29
|
||||
|
|
||||
LL | Self::foo(self, Self::bar(self));
|
||||
| ^^^^^^^^^^^^^^^
|
||||
help: ...and then using that local as the argument to this call
|
||||
--> $DIR/suggest-local-var-double-mut.rs:24:13
|
||||
|
|
||||
LL | Self::foo(self, Self::bar(self));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0499`.
|
|
@ -0,0 +1,33 @@
|
|||
error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
|
||||
--> $DIR/suggest-local-var-imm-and-mut.rs:12:22
|
||||
|
|
||||
LL | self.foo(self.bar());
|
||||
| ---------^^^^^^^^^^-
|
||||
| | | |
|
||||
| | | mutable borrow occurs here
|
||||
| | immutable borrow later used by call
|
||||
| immutable borrow occurs here
|
||||
|
|
||||
help: try adding a local storing this argument...
|
||||
--> $DIR/suggest-local-var-imm-and-mut.rs:12:22
|
||||
|
|
||||
LL | self.foo(self.bar());
|
||||
| ^^^^^^^^^^
|
||||
help: ...and then using that local as the argument to this call
|
||||
--> $DIR/suggest-local-var-imm-and-mut.rs:12:13
|
||||
|
|
||||
LL | self.foo(self.bar());
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
|
||||
--> $DIR/suggest-local-var-imm-and-mut.rs:24:39
|
||||
|
|
||||
LL | Self::foo(self, Self::bar(self));
|
||||
| --------- ---- ^^^^ mutable borrow occurs here
|
||||
| | |
|
||||
| | immutable borrow occurs here
|
||||
| immutable borrow later used by call
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0502`.
|
27
src/test/ui/borrowck/suggest-local-var-imm-and-mut.rs
Normal file
27
src/test/ui/borrowck/suggest-local-var-imm-and-mut.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
// See issue #77834.
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
mod method_syntax {
|
||||
struct Foo;
|
||||
|
||||
impl Foo {
|
||||
fn foo(&self, _: f32) -> i32 { todo!() }
|
||||
fn bar(&mut self) -> f32 { todo!() }
|
||||
fn baz(&mut self) {
|
||||
self.foo(self.bar()); //~ ERROR
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod fully_qualified_syntax {
|
||||
struct Foo;
|
||||
|
||||
impl Foo {
|
||||
fn foo(&self, _: f32) -> i32 { todo!() }
|
||||
fn bar(&mut self) -> f32 { todo!() }
|
||||
fn baz(&mut self) {
|
||||
Self::foo(self, Self::bar(self)); //~ ERROR
|
||||
}
|
||||
}
|
||||
}
|
22
src/test/ui/borrowck/suggest-local-var-imm-and-mut.stderr
Normal file
22
src/test/ui/borrowck/suggest-local-var-imm-and-mut.stderr
Normal file
|
@ -0,0 +1,22 @@
|
|||
error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
|
||||
--> $DIR/suggest-local-var-imm-and-mut.rs:12:22
|
||||
|
|
||||
LL | self.foo(self.bar());
|
||||
| ---------^^^^^^^^^^-
|
||||
| | | |
|
||||
| | | mutable borrow occurs here
|
||||
| | immutable borrow later used by call
|
||||
| immutable borrow occurs here
|
||||
|
||||
error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
|
||||
--> $DIR/suggest-local-var-imm-and-mut.rs:24:29
|
||||
|
|
||||
LL | Self::foo(self, Self::bar(self));
|
||||
| --------- ---- ^^^^^^^^^^^^^^^ mutable borrow occurs here
|
||||
| | |
|
||||
| | immutable borrow occurs here
|
||||
| immutable borrow later used by call
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0502`.
|
|
@ -13,6 +13,23 @@ LL | |
|
|||
LL | | 0
|
||||
LL | | });
|
||||
| |______- immutable borrow occurs here
|
||||
|
|
||||
help: try adding a local storing this argument...
|
||||
--> $DIR/two-phase-cannot-nest-mut-self-calls.rs:16:9
|
||||
|
|
||||
LL | vec.push(2);
|
||||
| ^^^^^^^^^^^
|
||||
help: ...and then using that local as the argument to this call
|
||||
--> $DIR/two-phase-cannot-nest-mut-self-calls.rs:14:5
|
||||
|
|
||||
LL | / vec.get({
|
||||
LL | |
|
||||
LL | | vec.push(2);
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | 0
|
||||
LL | | });
|
||||
| |______^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -8,13 +8,18 @@ LL | bar(|| {
|
|||
LL | |
|
||||
LL | | let _ = x;
|
||||
LL | | })
|
||||
| |_____^ ...is captured here...
|
||||
| |_____^ ...is used here...
|
||||
|
|
||||
note: ...and is required to live as long as `'static` here
|
||||
--> $DIR/closure-bounds-static-cant-capture-borrowed.rs:5:5
|
||||
|
|
||||
LL | bar(|| {
|
||||
| ^^^
|
||||
note: `'static` lifetime requirement introduced by this bound
|
||||
--> $DIR/closure-bounds-static-cant-capture-borrowed.rs:1:39
|
||||
|
|
||||
LL | fn bar<F>(blk: F) where F: FnOnce() + 'static {
|
||||
| ^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -7,6 +7,17 @@ LL | v.push(v.pop().unwrap());
|
|||
| | | second mutable borrow occurs here
|
||||
| | first borrow later used by call
|
||||
| first mutable borrow occurs here
|
||||
|
|
||||
help: try adding a local storing this argument...
|
||||
--> $DIR/one_line.rs:3:12
|
||||
|
|
||||
LL | v.push(v.pop().unwrap());
|
||||
| ^^^^^^^
|
||||
help: ...and then using that local as the argument to this call
|
||||
--> $DIR/one_line.rs:3:5
|
||||
|
|
||||
LL | v.push(v.pop().unwrap());
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ LL | fn dangle(x: &mut i32) -> &'static mut i32 {
|
|||
| -------- this data with an anonymous lifetime `'_`...
|
||||
...
|
||||
LL | x
|
||||
| ^ ...is captured here...
|
||||
| ^ ...is used here...
|
||||
...
|
||||
LL | GeneratorState::Complete(c) => return c,
|
||||
| - ...and is required to live as long as `'static` here
|
||||
|
|
|
@ -4,7 +4,9 @@ error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'sta
|
|||
LL | fn f(x: &impl for<'a> X<Y<'a> = &'a ()>) -> &'static () {
|
||||
| ------------------------------- this data with an anonymous lifetime `'_`...
|
||||
LL | x.m()
|
||||
| --^-- ...is captured and required to live as long as `'static` here
|
||||
| - ^
|
||||
| |
|
||||
| ...is used and required to live as long as `'static` here
|
||||
|
||||
error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
|
||||
--> $DIR/projection-type-lifetime-mismatch.rs:22:7
|
||||
|
@ -12,7 +14,9 @@ error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'sta
|
|||
LL | fn g<T: for<'a> X<Y<'a> = &'a ()>>(x: &T) -> &'static () {
|
||||
| -- this data with an anonymous lifetime `'_`...
|
||||
LL | x.m()
|
||||
| --^-- ...is captured and required to live as long as `'static` here
|
||||
| - ^
|
||||
| |
|
||||
| ...is used and required to live as long as `'static` here
|
||||
|
||||
error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
|
||||
--> $DIR/projection-type-lifetime-mismatch.rs:27:7
|
||||
|
@ -20,7 +24,9 @@ error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'sta
|
|||
LL | fn h(x: &()) -> &'static () {
|
||||
| --- this data with an anonymous lifetime `'_`...
|
||||
LL | x.m()
|
||||
| --^-- ...is captured and required to live as long as `'static` here
|
||||
| - ^
|
||||
| |
|
||||
| ...is used and required to live as long as `'static` here
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime
|
|||
LL | fn with_dyn_debug_static<'a>(x: Box<dyn Debug + 'a>) {
|
||||
| ------------------- this data with lifetime `'a`...
|
||||
LL | static_val(x);
|
||||
| ^ ...is captured here...
|
||||
| ^ ...is used here...
|
||||
|
|
||||
note: ...and is required to live as long as `'static` here
|
||||
--> $DIR/dyn-trait.rs:20:5
|
||||
|
|
|
@ -28,7 +28,7 @@ error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'sta
|
|||
--> $DIR/must_outlive_least_region_or_bound.rs:9:46
|
||||
|
|
||||
LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
|
||||
| ---- ^ ...is captured here...
|
||||
| ---- ^ ...is used here...
|
||||
| |
|
||||
| this data with an anonymous lifetime `'_`...
|
||||
|
|
||||
|
@ -50,7 +50,7 @@ error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime
|
|||
--> $DIR/must_outlive_least_region_or_bound.rs:11:55
|
||||
|
|
||||
LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
|
||||
| ------- ^ ...is captured here...
|
||||
| ------- ^ ...is used here...
|
||||
| |
|
||||
| this data with lifetime `'a`...
|
||||
|
|
||||
|
@ -80,7 +80,7 @@ error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'sta
|
|||
--> $DIR/must_outlive_least_region_or_bound.rs:24:65
|
||||
|
|
||||
LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) }
|
||||
| ---- this data with an anonymous lifetime `'_`... ^ ...is captured here, requiring it to live as long as `'static`
|
||||
| ---- this data with an anonymous lifetime `'_`... ^ ...is used and required to live as long as `'static` here
|
||||
|
|
||||
help: to declare that the trait object captures data from argument `x`, you can add an explicit `'_` lifetime bound
|
||||
|
|
||||
|
@ -95,7 +95,7 @@ error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime
|
|||
--> $DIR/must_outlive_least_region_or_bound.rs:29:69
|
||||
|
|
||||
LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
|
||||
| ------- this data with lifetime `'a`... ^ ...is captured here...
|
||||
| ------- this data with lifetime `'a`... ^ ...is used here...
|
||||
|
|
||||
note: ...and is required to live as long as `'static` here
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:29:34
|
||||
|
@ -136,10 +136,17 @@ error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'sta
|
|||
--> $DIR/must_outlive_least_region_or_bound.rs:16:50
|
||||
|
|
||||
LL | fn elided3(x: &i32) -> Box<dyn Debug> { Box::new(x) }
|
||||
| ---- ^ ...is captured here, requiring it to live as long as `'static`
|
||||
| ---- ^ ...is used and required to live as long as `'static` here
|
||||
| |
|
||||
| this data with an anonymous lifetime `'_`...
|
||||
|
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:16:28
|
||||
|
|
||||
LL | fn elided3(x: &i32) -> Box<dyn Debug> { Box::new(x) }
|
||||
| ^^^^^^^^^ ----------- because of this returned expression
|
||||
| |
|
||||
| `'static` requirement introduced here
|
||||
help: to declare that the trait object captures data from argument `x`, you can add an explicit `'_` lifetime bound
|
||||
|
|
||||
LL | fn elided3(x: &i32) -> Box<dyn Debug + '_> { Box::new(x) }
|
||||
|
@ -149,10 +156,17 @@ error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime
|
|||
--> $DIR/must_outlive_least_region_or_bound.rs:18:59
|
||||
|
|
||||
LL | fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug> { Box::new(x) }
|
||||
| ------- ^ ...is captured here, requiring it to live as long as `'static`
|
||||
| ------- ^ ...is used and required to live as long as `'static` here
|
||||
| |
|
||||
| this data with lifetime `'a`...
|
||||
|
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:18:37
|
||||
|
|
||||
LL | fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug> { Box::new(x) }
|
||||
| ^^^^^^^^^ ----------- because of this returned expression
|
||||
| |
|
||||
| `'static` requirement introduced here
|
||||
help: to declare that the trait object captures data from argument `x`, you can add an explicit `'a` lifetime bound
|
||||
|
|
||||
LL | fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug + 'a> { Box::new(x) }
|
||||
|
@ -162,10 +176,17 @@ error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'sta
|
|||
--> $DIR/must_outlive_least_region_or_bound.rs:20:60
|
||||
|
|
||||
LL | fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) }
|
||||
| ---- ^ ...is captured here, requiring it to live as long as `'static`
|
||||
| ---- ^ ...is used and required to live as long as `'static` here
|
||||
| |
|
||||
| this data with an anonymous lifetime `'_`...
|
||||
|
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:20:40
|
||||
|
|
||||
LL | fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) }
|
||||
| ^^^^^^^ ----------- because of this returned expression
|
||||
| |
|
||||
| `'static` requirement introduced here
|
||||
help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x`
|
||||
|
|
||||
LL | fn elided4(x: &i32) -> Box<dyn Debug + '_> { Box::new(x) }
|
||||
|
@ -179,8 +200,15 @@ error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime
|
|||
--> $DIR/must_outlive_least_region_or_bound.rs:22:69
|
||||
|
|
||||
LL | fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) }
|
||||
| ------- this data with lifetime `'a`... ^ ...is captured here, requiring it to live as long as `'static`
|
||||
| ------- this data with lifetime `'a`... ^ ...is used and required to live as long as `'static` here
|
||||
|
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/must_outlive_least_region_or_bound.rs:22:49
|
||||
|
|
||||
LL | fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) }
|
||||
| ^^^^^^^ ----------- because of this returned expression
|
||||
| |
|
||||
| `'static` requirement introduced here
|
||||
help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x`
|
||||
|
|
||||
LL | fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'a> { Box::new(x) }
|
||||
|
|
|
@ -4,7 +4,7 @@ error[E0759]: `value` has an anonymous lifetime `'_` but it needs to satisfy a `
|
|||
LL | fn foo<T: Any>(value: &T) -> Box<dyn Any> {
|
||||
| -- this data with an anonymous lifetime `'_`...
|
||||
LL | Box::new(value) as Box<dyn Any>
|
||||
| ^^^^^ ...is captured here, requiring it to live as long as `'static`
|
||||
| ^^^^^ ...is used and required to live as long as `'static` here
|
||||
|
|
||||
help: to declare that the trait object captures data from argument `value`, you can add an explicit `'_` lifetime bound
|
||||
|
|
||||
|
|
|
@ -4,7 +4,7 @@ error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'sta
|
|||
LL | fn foo(x: &u32) -> &'static u32 {
|
||||
| ---- this data with an anonymous lifetime `'_`...
|
||||
LL | &*x
|
||||
| ^^^ ...is captured and required to live as long as `'static` here
|
||||
| ^^^ ...is used and required to live as long as `'static` here
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ error[E0759]: `foo` has an anonymous lifetime `'_` but it needs to satisfy a `'s
|
|||
LL | fn inner(mut foo: &[u8]) {
|
||||
| ----- this data with an anonymous lifetime `'_`...
|
||||
LL | let refcell = RefCell::new(&mut foo);
|
||||
| ^^^^^^^^ ...is captured here...
|
||||
| ^^^^^^^^ ...is used here...
|
||||
...
|
||||
LL | read_thing(read);
|
||||
| ---- ...and is required to live as long as `'static` here
|
||||
|
|
|
@ -4,7 +4,7 @@ error[E0759]: `fn` parameter has lifetime `'a` but it needs to satisfy a `'stati
|
|||
LL | fn foo<'a>(_: &'a u32) -> &'static u32 {
|
||||
| ------- this data with lifetime `'a`...
|
||||
LL | <Foo<'a>>::C
|
||||
| ^^^^^^^^^^^^ ...is captured and required to live as long as `'static` here
|
||||
| ^^^^^^^^^^^^ ...is used and required to live as long as `'static` here
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -5,8 +5,16 @@ LL | fn load(ss: &mut SomeStruct) -> Box<dyn SomeTrait> {
|
|||
| --------------- this data with an anonymous lifetime `'_`...
|
||||
...
|
||||
LL | ss.r
|
||||
| ^^^^ ...is captured and required to live as long as `'static` here
|
||||
| ^^^^ ...is used and required to live as long as `'static` here
|
||||
|
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/object-lifetime-default-from-box-error.rs:14:37
|
||||
|
|
||||
LL | fn load(ss: &mut SomeStruct) -> Box<dyn SomeTrait> {
|
||||
| ^^^^^^^^^^^^^ `'static` requirement introduced here
|
||||
...
|
||||
LL | ss.r
|
||||
| ---- because of this returned expression
|
||||
help: to declare that the trait object captures data from argument `ss`, you can add an explicit `'_` lifetime bound
|
||||
|
|
||||
LL | fn load(ss: &mut SomeStruct) -> Box<dyn SomeTrait + '_> {
|
||||
|
|
|
@ -4,7 +4,7 @@ error[E0759]: `v` has an anonymous lifetime `'_` but it needs to satisfy a `'sta
|
|||
LL | fn a(v: &[u8]) -> Box<dyn Foo + 'static> {
|
||||
| ----- this data with an anonymous lifetime `'_`...
|
||||
LL | let x: Box<dyn Foo + 'static> = Box::new(v);
|
||||
| ^ ...is captured here, requiring it to live as long as `'static`
|
||||
| ^ ...is used and required to live as long as `'static` here
|
||||
|
|
||||
help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v`
|
||||
|
|
||||
|
@ -21,8 +21,15 @@ error[E0759]: `v` has an anonymous lifetime `'_` but it needs to satisfy a `'sta
|
|||
LL | fn b(v: &[u8]) -> Box<dyn Foo + 'static> {
|
||||
| ----- this data with an anonymous lifetime `'_`...
|
||||
LL | Box::new(v)
|
||||
| ^ ...is captured here, requiring it to live as long as `'static`
|
||||
| ^ ...is used and required to live as long as `'static` here
|
||||
|
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/region-object-lifetime-in-coercion.rs:12:33
|
||||
|
|
||||
LL | fn b(v: &[u8]) -> Box<dyn Foo + 'static> {
|
||||
| ^^^^^^^ `'static` requirement introduced here
|
||||
LL | Box::new(v)
|
||||
| ----------- because of this returned expression
|
||||
help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v`
|
||||
|
|
||||
LL | fn b(v: &[u8]) -> Box<dyn Foo + '_> {
|
||||
|
@ -39,8 +46,16 @@ LL | fn c(v: &[u8]) -> Box<dyn Foo> {
|
|||
| ----- this data with an anonymous lifetime `'_`...
|
||||
...
|
||||
LL | Box::new(v)
|
||||
| ^ ...is captured here, requiring it to live as long as `'static`
|
||||
| ^ ...is used and required to live as long as `'static` here
|
||||
|
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/region-object-lifetime-in-coercion.rs:16:23
|
||||
|
|
||||
LL | fn c(v: &[u8]) -> Box<dyn Foo> {
|
||||
| ^^^^^^^ `'static` requirement introduced here
|
||||
...
|
||||
LL | Box::new(v)
|
||||
| ----------- because of this returned expression
|
||||
help: to declare that the trait object captures data from argument `v`, you can add an explicit `'_` lifetime bound
|
||||
|
|
||||
LL | fn c(v: &[u8]) -> Box<dyn Foo + '_> {
|
||||
|
|
|
@ -4,7 +4,7 @@ error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'
|
|||
LL | pub fn chase_cat(&mut self) {
|
||||
| --------- this data with an anonymous lifetime `'_`...
|
||||
LL | let p: &'static mut usize = &mut self.cats_chased;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ ...is captured and required to live as long as `'static` here
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ ...is used and required to live as long as `'static` here
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -4,8 +4,15 @@ error[E0759]: `v` has lifetime `'a` but it needs to satisfy a `'static` lifetime
|
|||
LL | fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> {
|
||||
| ------------------ this data with lifetime `'a`...
|
||||
LL | Box::new(B(&*v)) as Box<dyn X>
|
||||
| ^^^ ...is captured here, requiring it to live as long as `'static`
|
||||
| ^^^ ...is used and required to live as long as `'static` here
|
||||
|
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/regions-close-object-into-object-2.rs:8:60
|
||||
|
|
||||
LL | fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> {
|
||||
| ^^^^^^^ `'static` requirement introduced here
|
||||
LL | Box::new(B(&*v)) as Box<dyn X>
|
||||
| ------------------------------ because of this returned expression
|
||||
help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v`
|
||||
|
|
||||
LL | fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'a> {
|
||||
|
|
|
@ -4,8 +4,15 @@ error[E0759]: `v` has lifetime `'a` but it needs to satisfy a `'static` lifetime
|
|||
LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
|
||||
| ---------------- this data with lifetime `'a`...
|
||||
LL | Box::new(B(&*v)) as Box<dyn X>
|
||||
| ^^^ ...is captured here, requiring it to live as long as `'static`
|
||||
| ^^^ ...is used and required to live as long as `'static` here
|
||||
|
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/regions-close-object-into-object-4.rs:8:52
|
||||
|
|
||||
LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
|
||||
| ^^^^^^^ `'static` requirement introduced here
|
||||
LL | Box::new(B(&*v)) as Box<dyn X>
|
||||
| ------------------------------ because of this returned expression
|
||||
help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v`
|
||||
|
|
||||
LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'a> {
|
||||
|
|
|
@ -5,8 +5,16 @@ LL | fn static_proc(x: &isize) -> Box<dyn FnMut() -> (isize) + 'static> {
|
|||
| ------ this data with an anonymous lifetime `'_`...
|
||||
LL | // This is illegal, because the region bound on `proc` is 'static.
|
||||
LL | Box::new(move || { *x })
|
||||
| ^^^^^^^^^^^^^^ ...is captured here, requiring it to live as long as `'static`
|
||||
| ^^^^^^^^^^^^^^ ...is used and required to live as long as `'static` here
|
||||
|
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/regions-proc-bound-capture.rs:7:59
|
||||
|
|
||||
LL | fn static_proc(x: &isize) -> Box<dyn FnMut() -> (isize) + 'static> {
|
||||
| ^^^^^^^ `'static` requirement introduced here
|
||||
LL | // This is illegal, because the region bound on `proc` is 'static.
|
||||
LL | Box::new(move || { *x })
|
||||
| ------------------------ because of this returned expression
|
||||
help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x`
|
||||
|
|
||||
LL | fn static_proc(x: &isize) -> Box<dyn FnMut() -> (isize) + '_> {
|
||||
|
|
|
@ -17,7 +17,7 @@ error[E0759]: `u` has an anonymous lifetime `'_` but it needs to satisfy a `'sta
|
|||
LL | fn error(u: &(), v: &()) {
|
||||
| --- this data with an anonymous lifetime `'_`...
|
||||
LL | static_id(&u);
|
||||
| ^^^^^^^^^ -- ...is captured here...
|
||||
| ^^^^^^^^^ -- ...is used here...
|
||||
|
|
||||
note: ...and is required to live as long as `'static` here
|
||||
--> $DIR/regions-static-bound.rs:10:5
|
||||
|
@ -32,7 +32,7 @@ LL | fn error(u: &(), v: &()) {
|
|||
| --- this data with an anonymous lifetime `'_`...
|
||||
LL | static_id(&u);
|
||||
LL | static_id_indirect(&v);
|
||||
| ^^^^^^^^^^^^^^^^^^ -- ...is captured here...
|
||||
| ^^^^^^^^^^^^^^^^^^ -- ...is used here...
|
||||
|
|
||||
note: ...and is required to live as long as `'static` here
|
||||
--> $DIR/regions-static-bound.rs:11:5
|
||||
|
|
|
@ -22,7 +22,7 @@ error[E0772]: `val` has lifetime `'a` but calling `use_self` introduces an impli
|
|||
LL | fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32> + 'a>) -> &'a () {
|
||||
| -------------------------------------- this data with lifetime `'a`...
|
||||
LL | val.use_self()
|
||||
| ^^^^^^^^ ...is captured and required to live as long as `'static` here
|
||||
| ^^^^^^^^ ...is used and required to live as long as `'static` here
|
||||
|
|
||||
note: the used `impl` has a `'static` requirement
|
||||
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:60:30
|
||||
|
|
|
@ -4,7 +4,7 @@ error[E0759]: `val` has lifetime `'a` but it needs to satisfy a `'static` lifeti
|
|||
LL | fn use_it<'a, T>(val: &'a dyn ObjectTrait<T>) -> impl OtherTrait<'a> + 'a {
|
||||
| ---------------------- this data with lifetime `'a`...
|
||||
LL | val.use_self::<T>()
|
||||
| ^^^^^^^^ ...is captured and required to live as long as `'static` here
|
||||
| ^^^^^^^^ ...is used and required to live as long as `'static` here
|
||||
|
|
||||
note: the used `impl` has a `'static` requirement
|
||||
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:14:32
|
||||
|
@ -24,7 +24,7 @@ error[E0772]: `val` has lifetime `'a` but calling `use_self` introduces an impli
|
|||
LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
|
||||
| ------------------- this data with lifetime `'a`...
|
||||
LL | val.use_self()
|
||||
| ^^^^^^^^ ...is captured and required to live as long as `'static` here because of an implicit lifetime bound on the inherent `impl`
|
||||
| ^^^^^^^^ ...is used and required to live as long as `'static` here because of an implicit lifetime bound on the inherent `impl`
|
||||
|
|
||||
note: the used `impl` has a `'static` requirement
|
||||
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:64:14
|
||||
|
@ -44,7 +44,7 @@ error[E0759]: `val` has lifetime `'a` but it needs to satisfy a `'static` lifeti
|
|||
LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> {
|
||||
| ------------------- this data with lifetime `'a`...
|
||||
LL | val.use_self()
|
||||
| ^^^^^^^^ ...is captured and required to live as long as `'static` here
|
||||
| ^^^^^^^^ ...is used and required to live as long as `'static` here
|
||||
|
|
||||
note: the used `impl` has a `'static` requirement
|
||||
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:85:26
|
||||
|
@ -69,7 +69,7 @@ error[E0759]: `val` has lifetime `'a` but it needs to satisfy a `'static` lifeti
|
|||
LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
|
||||
| ------------------- this data with lifetime `'a`...
|
||||
LL | MyTrait::use_self(val)
|
||||
| ^^^ ...is captured here...
|
||||
| ^^^ ...is used here...
|
||||
|
|
||||
note: ...and is required to live as long as `'static` here
|
||||
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:108:9
|
||||
|
@ -95,7 +95,7 @@ error[E0772]: `val` has lifetime `'a` but calling `use_self` introduces an impli
|
|||
LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () {
|
||||
| ------------------- this data with lifetime `'a`...
|
||||
LL | val.use_self()
|
||||
| ^^^^^^^^ ...is captured and required to live as long as `'static` here
|
||||
| ^^^^^^^^ ...is used and required to live as long as `'static` here
|
||||
|
|
||||
note: the used `impl` has a `'static` requirement
|
||||
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:31:26
|
||||
|
@ -115,7 +115,7 @@ error[E0772]: `val` has lifetime `'a` but calling `use_self` introduces an impli
|
|||
LL | fn use_it<'a>(val: &'a Box<dyn ObjectTrait + 'a>) -> &'a () {
|
||||
| ----------------------------- this data with lifetime `'a`...
|
||||
LL | val.use_self()
|
||||
| ^^^^^^^^ ...is captured and required to live as long as `'static` here
|
||||
| ^^^^^^^^ ...is used and required to live as long as `'static` here
|
||||
|
|
||||
note: the used `impl` has a `'static` requirement
|
||||
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:48:30
|
||||
|
|
|
@ -7,7 +7,7 @@ LL | fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> {
|
|||
LL | remaining: self.0.iter(),
|
||||
| ------ ^^^^
|
||||
| |
|
||||
| ...is captured here...
|
||||
| ...is used here...
|
||||
|
|
||||
note: ...and is required to live as long as `'static` here
|
||||
--> $DIR/trait-object-nested-in-impl-trait.rs:27:23
|
||||
|
@ -32,7 +32,7 @@ LL | fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> + '_ {
|
|||
LL | remaining: self.0.iter(),
|
||||
| ------ ^^^^
|
||||
| |
|
||||
| ...is captured here...
|
||||
| ...is used here...
|
||||
|
|
||||
note: ...and is required to live as long as `'static` here
|
||||
--> $DIR/trait-object-nested-in-impl-trait.rs:38:23
|
||||
|
@ -53,7 +53,7 @@ LL | fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> + 'a {
|
|||
LL | remaining: self.0.iter(),
|
||||
| ------ ^^^^
|
||||
| |
|
||||
| ...is captured here...
|
||||
| ...is used here...
|
||||
|
|
||||
note: ...and is required to live as long as `'static` here
|
||||
--> $DIR/trait-object-nested-in-impl-trait.rs:49:30
|
||||
|
@ -74,7 +74,7 @@ LL | fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> {
|
|||
LL | remaining: self.0.iter(),
|
||||
| ------ ^^^^
|
||||
| |
|
||||
| ...is captured here...
|
||||
| ...is used here...
|
||||
|
|
||||
note: ...and is required to live as long as `'static` here
|
||||
--> $DIR/trait-object-nested-in-impl-trait.rs:60:30
|
||||
|
|
|
@ -29,4 +29,22 @@ fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
|
|||
y.get_b() // ERROR
|
||||
}
|
||||
|
||||
fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
|
||||
<_ as Bar>::get_b(x) // ERROR
|
||||
//~^ ERROR `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
|
||||
}
|
||||
|
||||
fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
|
||||
<_ as Bar<'_, '_>>::get_b(x) // ERROR
|
||||
//~^ ERROR `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
|
||||
}
|
||||
|
||||
fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
|
||||
let y = x as &dyn Bar<'_, '_>;
|
||||
//~^ ERROR `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
|
||||
y.get_b(); // ERROR
|
||||
let z = y;
|
||||
z.get_b() // ERROR
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -36,12 +36,88 @@ LL | fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
|
|||
LL | let y = x as &dyn Bar<'_, '_>;
|
||||
| - ^^
|
||||
| |
|
||||
| ...is captured here...
|
||||
| ...is used here...
|
||||
LL |
|
||||
LL | y.get_b() // ERROR
|
||||
| --------- ...and is required to live as long as `'static` here
|
||||
| - ...is used here...
|
||||
|
|
||||
note: ...and is required to live as long as `'static` here
|
||||
--> $DIR/type-checking-test-4.rs:29:5
|
||||
|
|
||||
LL | y.get_b() // ERROR
|
||||
| ^^^^^^^^^
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/type-checking-test-4.rs:26:48
|
||||
|
|
||||
LL | fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
|
||||
| ^^^^^^^ `'static` requirement introduced here
|
||||
...
|
||||
LL | y.get_b() // ERROR
|
||||
| --------- because of this returned expression
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
|
||||
--> $DIR/type-checking-test-4.rs:33:5
|
||||
|
|
||||
LL | fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
|
||||
| ------------ this data with lifetime `'a`...
|
||||
LL | <_ as Bar>::get_b(x) // ERROR
|
||||
| ^^^^^^^^^^^^^^^^^ ...is used and required to live as long as `'static` here
|
||||
|
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/type-checking-test-4.rs:32:48
|
||||
|
|
||||
LL | fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
|
||||
| ^^^^^^^ `'static` requirement introduced here
|
||||
LL | <_ as Bar>::get_b(x) // ERROR
|
||||
| -------------------- because of this returned expression
|
||||
|
||||
error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
|
||||
--> $DIR/type-checking-test-4.rs:38:15
|
||||
|
|
||||
LL | fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
|
||||
| ------------ this data with lifetime `'a`...
|
||||
LL | <_ as Bar<'_, '_>>::get_b(x) // ERROR
|
||||
| ----------^^------------- ...is used and required to live as long as `'static` here
|
||||
|
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/type-checking-test-4.rs:37:48
|
||||
|
|
||||
LL | fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
|
||||
| ^^^^^^^ `'static` requirement introduced here
|
||||
LL | <_ as Bar<'_, '_>>::get_b(x) // ERROR
|
||||
| ---------------------------- because of this returned expression
|
||||
|
||||
error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
|
||||
--> $DIR/type-checking-test-4.rs:43:27
|
||||
|
|
||||
LL | fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
|
||||
| ------------ this data with lifetime `'a`...
|
||||
LL | let y = x as &dyn Bar<'_, '_>;
|
||||
| - ^^
|
||||
| |
|
||||
| ...is used here...
|
||||
LL |
|
||||
LL | y.get_b(); // ERROR
|
||||
| - ...is used here...
|
||||
LL | let z = y;
|
||||
LL | z.get_b() // ERROR
|
||||
| - ...is used here...
|
||||
|
|
||||
note: ...and is required to live as long as `'static` here
|
||||
--> $DIR/type-checking-test-4.rs:47:5
|
||||
|
|
||||
LL | z.get_b() // ERROR
|
||||
| ^^^^^^^^^
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/type-checking-test-4.rs:42:48
|
||||
|
|
||||
LL | fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
|
||||
| ^^^^^^^ `'static` requirement introduced here
|
||||
...
|
||||
LL | z.get_b() // ERROR
|
||||
| --------- because of this returned expression
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0308, E0759.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
||||
|
|
|
@ -5,8 +5,18 @@ LL | fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
|
|||
| ---- this data with an anonymous lifetime `'_`...
|
||||
LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
|
||||
LL | Box::new(items.iter())
|
||||
| ---------------^^^^--- ...is captured and required to live as long as `'static` here
|
||||
| ----- ^^^^
|
||||
| |
|
||||
| ...is used and required to live as long as `'static` here
|
||||
|
|
||||
note: `'static` lifetime requirement introduced by the return type
|
||||
--> $DIR/dyn-trait-underscore.rs:6:29
|
||||
|
|
||||
LL | fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ `'static` requirement introduced here
|
||||
LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
|
||||
LL | Box::new(items.iter())
|
||||
| ---------------------- because of this returned expression
|
||||
help: to declare that the trait object captures data from argument `items`, you can add an explicit `'_` lifetime bound
|
||||
|
|
||||
LL | fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T> + '_> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue