1
Fork 0

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:
bors 2021-12-11 18:56:59 +00:00
commit 928783de66
56 changed files with 952 additions and 204 deletions

View file

@ -368,6 +368,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
error_region, error_region,
cause.clone(), cause.clone(),
placeholder_region, placeholder_region,
vec![],
), ),
), ),
(Some(error_region), _) => NiceRegionError::new( (Some(error_region), _) => NiceRegionError::new(

View file

@ -15,16 +15,18 @@ use rustc_span::symbol::sym;
use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP}; use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP};
use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::infer::InferCtxtExt;
use crate::borrow_set::TwoPhaseActivation;
use crate::borrowck_errors; use crate::borrowck_errors;
use crate::diagnostics::find_all_local_uses;
use crate::{ use crate::{
borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf, borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf,
InitializationRequiringAction, MirBorrowckCtxt, PrefixSet, WriteKind, InitializationRequiringAction, MirBorrowckCtxt, PrefixSet, WriteKind,
}; };
use super::{ use super::{
explain_borrow::BorrowExplanation, FnSelfUseKind, IncludingDowncast, RegionName, explain_borrow::{BorrowExplanation, LaterUseKind},
RegionNameSource, UseSpans, FnSelfUseKind, IncludingDowncast, RegionName, RegionNameSource, UseSpans,
}; };
#[derive(Debug)] #[derive(Debug)]
@ -768,9 +770,92 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
Some((issued_span, span)), Some((issued_span, span)),
); );
self.suggest_using_local_if_applicable(
&mut err,
location,
(place, span),
gen_borrow_kind,
issued_borrow,
explanation,
);
err 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( fn suggest_split_at_mut_if_applicable(
&self, &self,
err: &mut DiagnosticBuilder<'_>, err: &mut DiagnosticBuilder<'_>,

View file

@ -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);
}
}
}

View file

@ -19,6 +19,7 @@ use rustc_target::abi::VariantIdx;
use super::borrow_set::BorrowData; use super::borrow_set::BorrowData;
use super::MirBorrowckCtxt; use super::MirBorrowckCtxt;
mod find_all_local_uses;
mod find_use; mod find_use;
mod outlives_suggestion; mod outlives_suggestion;
mod region_name; mod region_name;

View file

@ -384,6 +384,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
sub_r, sub_r,
sup_origin, sup_origin,
sup_r, sup_r,
_,
) => { ) => {
if sub_r.is_placeholder() { if sub_r.is_placeholder() {
self.report_placeholder_failure(sub_origin, sub_r, sup_r).emit(); 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 { errors.sort_by_key(|u| match *u {
RegionResolutionError::ConcreteFailure(ref sro, _, _) => sro.span(), RegionResolutionError::ConcreteFailure(ref sro, _, _) => sro.span(),
RegionResolutionError::GenericBoundFailure(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(), RegionResolutionError::UpperBoundUniverseConflict(_, ref rvo, _, _, _) => rvo.span(),
}); });
errors errors

View file

@ -67,7 +67,7 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> {
pub fn regions(&self) -> Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)> { pub fn regions(&self) -> Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)> {
match (&self.error, self.regions) { match (&self.error, self.regions) {
(Some(ConcreteFailure(origin, sub, sup)), None) => Some((origin.span(), sub, sup)), (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)) Some((origin.span(), sub, sup))
} }
(None, Some((span, sub, sup))) => Some((span, sub, sup)), (None, Some((span, sub, sup))) => Some((span, sub, sup)),

View file

@ -34,6 +34,7 @@ impl NiceRegionError<'me, 'tcx> {
sub_placeholder @ ty::RePlaceholder(_), sub_placeholder @ ty::RePlaceholder(_),
_, _,
sup_placeholder @ ty::RePlaceholder(_), sup_placeholder @ ty::RePlaceholder(_),
_,
)) => self.try_report_trait_placeholder_mismatch( )) => self.try_report_trait_placeholder_mismatch(
Some(self.tcx().mk_region(ty::ReVar(*vid))), Some(self.tcx().mk_region(ty::ReVar(*vid))),
cause, cause,
@ -49,6 +50,7 @@ impl NiceRegionError<'me, 'tcx> {
sub_placeholder @ ty::RePlaceholder(_), sub_placeholder @ ty::RePlaceholder(_),
_, _,
_, _,
_,
)) => self.try_report_trait_placeholder_mismatch( )) => self.try_report_trait_placeholder_mismatch(
Some(self.tcx().mk_region(ty::ReVar(*vid))), Some(self.tcx().mk_region(ty::ReVar(*vid))),
cause, cause,
@ -64,6 +66,7 @@ impl NiceRegionError<'me, 'tcx> {
_, _,
_, _,
sup_placeholder @ ty::RePlaceholder(_), sup_placeholder @ ty::RePlaceholder(_),
_,
)) => self.try_report_trait_placeholder_mismatch( )) => self.try_report_trait_placeholder_mismatch(
Some(self.tcx().mk_region(ty::ReVar(*vid))), Some(self.tcx().mk_region(ty::ReVar(*vid))),
cause, cause,
@ -79,6 +82,7 @@ impl NiceRegionError<'me, 'tcx> {
_, _,
SubregionOrigin::Subtype(box TypeTrace { cause, values }), SubregionOrigin::Subtype(box TypeTrace { cause, values }),
sup_placeholder @ ty::RePlaceholder(_), sup_placeholder @ ty::RePlaceholder(_),
_,
)) => self.try_report_trait_placeholder_mismatch( )) => self.try_report_trait_placeholder_mismatch(
Some(self.tcx().mk_region(ty::ReVar(*vid))), Some(self.tcx().mk_region(ty::ReVar(*vid))),
cause, cause,

View file

@ -10,7 +10,8 @@ use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{walk_ty, ErasedMap, NestedVisitorMap, Visitor}; use rustc_hir::intravisit::{walk_ty, ErasedMap, NestedVisitorMap, Visitor};
use rustc_hir::{self as hir, GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, TyKind}; use rustc_hir::{self as hir, GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, TyKind};
use rustc_middle::ty::{ 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::symbol::Ident;
use rustc_span::{MultiSpan, Span}; 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> { pub(super) fn try_report_static_impl_trait(&self) -> Option<ErrorReported> {
debug!("try_report_static_impl_trait(error={:?})", self.error); debug!("try_report_static_impl_trait(error={:?})", self.error);
let tcx = self.tcx(); 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( RegionResolutionError::SubSupConflict(
_, _,
var_origin, var_origin,
@ -31,8 +32,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
sub_r, sub_r,
sup_origin, sup_origin,
sup_r, sup_r,
spans,
) if **sub_r == RegionKind::ReStatic => { ) 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( RegionResolutionError::ConcreteFailure(
SubregionOrigin::Subtype(box TypeTrace { cause, .. }), SubregionOrigin::Subtype(box TypeTrace { cause, .. }),
@ -74,7 +76,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
err.span_label( err.span_label(
cause.span, cause.span,
&format!( &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 {}", because of an implicit lifetime bound on the {}",
match ctxt.assoc_item.container { match ctxt.assoc_item.container {
AssocItemContainer::TraitContainer(id) => AssocItemContainer::TraitContainer(id) =>
@ -123,56 +125,101 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
param_name, param_name,
lifetime, 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); debug!("try_report_static_impl_trait: param_info={:?}", param);
// We try to make the output have fewer overlapping spans if possible. let mut spans = spans.clone();
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`
// Customize the spans and labels depending on their relative order so if mention_influencer {
// that split sentences flow correctly. spans.push(sup_origin.span());
if sup_origin.span().overlaps(return_sp) && sp == sup_origin.span() { }
// Avoid the following: // We dedup the spans *ignoring* expansion context.
// spans.sort();
// error: cannot infer an appropriate lifetime spans.dedup_by_key(|span| (span.lo(), span.hi()));
// --> $DIR/must_outlive_least_region_or_bound.rs:18:50
// | // We try to make the output have fewer overlapping spans if possible.
// LL | fn foo(x: &i32) -> Box<dyn Debug> { Box::new(x) } let require_msg = if spans.is_empty() {
// | ---- ---------^- "...is used and required to live as long as `'static` here"
//
// 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`",
);
} else { } else {
err.span_label(sup_origin.span(), "...is captured here..."); "...and is required to live as long as `'static` here"
if return_sp < sup_origin.span() { };
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( err.span_note(
return_sp, span,
"...and is required to live as long as `'static` here", "`'static` lifetime requirement introduced by the return type",
);
} else {
err.span_label(
return_sp,
"...and is required to live as long as `'static` here",
); );
} }
} }
} 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); let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id);

View file

@ -28,6 +28,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
_sub, _sub,
sup_origin, sup_origin,
_sup, _sup,
_,
) = error.clone() ) = error.clone()
{ {
if let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) = (&sup_origin, &sub_origin) { if let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) = (&sup_origin, &sub_origin) {

View file

@ -19,6 +19,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{ReEarlyBound, ReEmpty, ReErased, ReFree, ReStatic}; use rustc_middle::ty::{ReEarlyBound, ReEmpty, ReErased, ReFree, ReStatic};
use rustc_middle::ty::{ReLateBound, RePlaceholder, ReVar}; use rustc_middle::ty::{ReLateBound, RePlaceholder, ReVar};
use rustc_middle::ty::{Region, RegionVid}; use rustc_middle::ty::{Region, RegionVid};
use rustc_span::Span;
use std::fmt; use std::fmt;
/// This function performs lexical region resolution given a complete /// This function performs lexical region resolution given a complete
@ -96,6 +97,7 @@ pub enum RegionResolutionError<'tcx> {
Region<'tcx>, Region<'tcx>,
SubregionOrigin<'tcx>, SubregionOrigin<'tcx>,
Region<'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 /// 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 // if this rule starts to create problems we'll
// have to revisit this portion of the code and // have to revisit this portion of the code and
// think hard about it. =) -- nikomatsakis // 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>>, dup_vec: &mut IndexVec<RegionVid, Option<RegionVid>>,
node_idx: RegionVid, node_idx: RegionVid,
errors: &mut Vec<RegionResolutionError<'tcx>>, errors: &mut Vec<RegionResolutionError<'tcx>>,
influences: Vec<Span>,
) { ) {
// Errors in expanding nodes result from a lower-bound that is // Errors in expanding nodes result from a lower-bound that is
// not contained by an upper-bound. // not contained by an upper-bound.
@ -667,6 +693,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
sup: {:?}", sup: {:?}",
origin, node_idx, lower_bound.region, upper_bound.region origin, node_idx, lower_bound.region, upper_bound.region
); );
errors.push(RegionResolutionError::SubSupConflict( errors.push(RegionResolutionError::SubSupConflict(
node_idx, node_idx,
origin, origin,
@ -674,6 +701,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
lower_bound.region, lower_bound.region,
upper_bound.origin.clone(), upper_bound.origin.clone(),
upper_bound.region, upper_bound.region,
influences,
)); ));
return; return;
} }

View file

@ -12,6 +12,7 @@ use crate::ty::print::{FmtPrinter, Printer};
use crate::ty::subst::{Subst, SubstsRef}; use crate::ty::subst::{Subst, SubstsRef};
use crate::ty::{self, List, Ty, TyCtxt}; use crate::ty::{self, List, Ty, TyCtxt};
use crate::ty::{AdtDef, InstanceDef, Region, ScalarInt, UserTypeAnnotationIndex}; use crate::ty::{AdtDef, InstanceDef, Region, ScalarInt, UserTypeAnnotationIndex};
use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::def::{CtorKind, Namespace};
use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
use rustc_hir::{self, GeneratorKind}; use rustc_hir::{self, GeneratorKind};
@ -30,6 +31,9 @@ use rustc_serialize::{Decodable, Encodable};
use rustc_span::symbol::Symbol; use rustc_span::symbol::Symbol;
use rustc_span::{Span, DUMMY_SP}; use rustc_span::{Span, DUMMY_SP};
use rustc_target::asm::InlineAsmRegOrRegClass; use rustc_target::asm::InlineAsmRegOrRegClass;
use either::Either;
use std::borrow::Cow; use std::borrow::Cow;
use std::convert::TryInto; use std::convert::TryInto;
use std::fmt::{self, Debug, Display, Formatter, Write}; 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() } 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] #[inline]
pub fn predecessors(&self) -> &Predecessors { pub fn predecessors(&self) -> &Predecessors {
self.predecessor_cache.compute(&self.basic_blocks) self.predecessor_cache.compute(&self.basic_blocks)

View file

@ -1481,40 +1481,8 @@ impl<'tcx> TyCtxt<'tcx> {
scope_def_id: LocalDefId, scope_def_id: LocalDefId,
) -> Vec<&'tcx hir::Ty<'tcx>> { ) -> Vec<&'tcx hir::Ty<'tcx>> {
let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id); let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
let hir_output = match self.hir().get(hir_id) { let hir_output = match self.hir().fn_decl_by_hir_id(hir_id) {
Node::Item(hir::Item { Some(hir::FnDecl { output: hir::FnRetTy::Return(ty), .. }) => ty,
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,
_ => return vec![], _ => return vec![],
}; };

View file

@ -6,6 +6,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::{QPath, TyKind, WhereBoundPredicate, WherePredicate}; use rustc_hir::{QPath, TyKind, WhereBoundPredicate, WherePredicate};
use rustc_span::Span;
impl<'tcx> TyS<'tcx> { impl<'tcx> TyS<'tcx> {
/// Similar to `TyS::is_primitive`, but also considers inferred numeric values to be primitive. /// 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); 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);
}
}
}

View file

@ -162,14 +162,16 @@ impl<T, const N: usize> AsMut<[T]> for [T; N] {
} }
#[stable(feature = "array_borrow", since = "1.4.0")] #[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] { fn borrow(&self) -> &[T] {
self self
} }
} }
#[stable(feature = "array_borrow", since = "1.4.0")] #[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] { fn borrow_mut(&mut self) -> &mut [T] {
self self
} }

View file

@ -205,7 +205,8 @@ pub trait BorrowMut<Borrowed: ?Sized>: Borrow<Borrowed> {
} }
#[stable(feature = "rust1", since = "1.0.0")] #[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"] #[rustc_diagnostic_item = "noop_method_borrow"]
fn borrow(&self) -> &T { fn borrow(&self) -> &T {
self self
@ -213,28 +214,32 @@ impl<T: ?Sized> Borrow<T> for T {
} }
#[stable(feature = "rust1", since = "1.0.0")] #[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 { fn borrow_mut(&mut self) -> &mut T {
self self
} }
} }
#[stable(feature = "rust1", since = "1.0.0")] #[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 { fn borrow(&self) -> &T {
&**self &**self
} }
} }
#[stable(feature = "rust1", since = "1.0.0")] #[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 { fn borrow(&self) -> &T {
&**self &**self
} }
} }
#[stable(feature = "rust1", since = "1.0.0")] #[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 { fn borrow_mut(&mut self) -> &mut T {
&mut **self &mut **self
} }

View file

@ -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::cell::UnsafeCell;
use crate::future::{poll_fn, Future}; use crate::future::{poll_fn, Future};
@ -45,59 +45,104 @@ use crate::task::{Context, Poll};
/// # }; /// # };
/// ``` /// ```
#[unstable(feature = "future_join", issue = "91642")] #[unstable(feature = "future_join", issue = "91642")]
pub macro join { pub macro join( $($fut:expr),+ $(,)? ) {
( $($fut:expr),* $(,)?) => { // Funnel through an internal macro not to leak implementation details.
join! { @count: (), @futures: {}, @rest: ($($fut,)*) } join_internal! {
}, current_position: []
// Recurse until we have the position of each future in the tuple futures_and_positions: []
( munching: [ $($fut)+ ]
// 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)*)
} }
}, }
// 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| { poll_fn(move |cx| {
let mut done = true; let mut done = true;
// For each `fut`, pin-project to it, and poll it.
$( $(
let ( $($pos,)* fut, .. ) = &mut futures; // SAFETY: pinning projection
let fut = unsafe {
// SAFETY: The futures are never moved futures.as_mut().map_unchecked_mut(|it| {
done &= unsafe { Pin::new_unchecked(fut).poll(cx).is_ready() }; 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 { // SAFETY: `.take_output()` does not break the `Pin` invariants for that `fut`.
// Extract all the outputs let futures = unsafe {
Poll::Ready(($({ futures.as_mut().get_unchecked_mut()
let ( $($pos,)* fut, .. ) = &mut futures; };
Poll::Ready(
($(
{
let ( $($pos,)* fut, .. ) = &mut *futures;
fut.take_output().unwrap() fut.take_output().unwrap()
}),*))
} else {
Poll::Pending
} }
),*) // <- no trailing comma since we don't want 1-tuples.
)
}).await }).await
} }}
} ),
} }
/// Future used by `join!` that stores it's output to /// Future used by `join!` that stores it's output to
@ -109,14 +154,14 @@ pub macro join {
pub enum MaybeDone<F: Future> { pub enum MaybeDone<F: Future> {
Future(F), Future(F),
Done(F::Output), Done(F::Output),
Took, Taken,
} }
#[unstable(feature = "future_join", issue = "91642")] #[unstable(feature = "future_join", issue = "91642")]
impl<F: Future> MaybeDone<F> { impl<F: Future> MaybeDone<F> {
pub fn take_output(&mut self) -> Option<F::Output> { pub fn take_output(&mut self) -> Option<F::Output> {
match &*self { match *self {
MaybeDone::Done(_) => match mem::replace(self, Self::Took) { MaybeDone::Done(_) => match mem::replace(self, Self::Taken) {
MaybeDone::Done(val) => Some(val), MaybeDone::Done(val) => Some(val),
_ => unreachable!(), _ => 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> { fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
// SAFETY: pinning in structural for `f` // SAFETY: pinning in structural for `f`
unsafe { unsafe {
match self.as_mut().get_unchecked_mut() { // Do not mix match ergonomics with unsafe.
MaybeDone::Future(f) => match Pin::new_unchecked(f).poll(cx) { match *self.as_mut().get_unchecked_mut() {
Poll::Ready(val) => self.set(Self::Done(val)), MaybeDone::Future(ref mut f) => {
Poll::Pending => return Poll::Pending, let val = Pin::new_unchecked(f).poll(cx).ready()?;
}, self.set(Self::Done(val));
}
MaybeDone::Done(_) => {} MaybeDone::Done(_) => {}
MaybeDone::Took => unreachable!(), MaybeDone::Taken => unreachable!(),
} }
} }

View file

@ -137,6 +137,11 @@ pub fn spin_loop() {
unsafe { crate::arch::arm::__yield() }; 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 /// An identity function that *__hints__* to the compiler to be maximally pessimistic about what

View file

@ -1523,8 +1523,15 @@ impl<T: Clone> Option<&T> {
/// ``` /// ```
#[must_use = "`self` will be dropped if the result is not used"] #[must_use = "`self` will be dropped if the result is not used"]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn cloned(self) -> Option<T> { #[rustc_const_unstable(feature = "const_option_cloned", issue = "91582")]
self.map(|t| t.clone()) 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(); /// let cloned = opt_x.cloned();
/// assert_eq!(cloned, Some(12)); /// 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")] #[stable(since = "1.26.0", feature = "option_ref_mut_cloned")]
pub fn cloned(self) -> Option<T> { #[rustc_const_unstable(feature = "const_option_cloned", issue = "91582")]
self.map(|t| t.clone()) pub const fn cloned(self) -> Option<T>
where
T: ~const Clone,
{
match self {
Some(t) => Some(t.clone()),
None => None,
}
} }
} }

View file

@ -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(&not_copy)); // should not move `not_copy`
let _ = &not_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) { fn block_on(fut: impl Future) {
struct Waker; struct Waker;
impl Wake for Waker { impl Wake for Waker {

View file

@ -49,6 +49,7 @@
#![feature(str_internals)] #![feature(str_internals)]
#![feature(test)] #![feature(test)]
#![feature(trusted_len)] #![feature(trusted_len)]
#![feature(try_blocks)]
#![feature(try_trait_v2)] #![feature(try_trait_v2)]
#![feature(slice_internals)] #![feature(slice_internals)]
#![feature(slice_partition_dedup)] #![feature(slice_partition_dedup)]

@ -1 +1 @@
Subproject commit cfba59fccd90b3b52a614120834320f764ab08d1 Subproject commit b70ae88ef2a6c83acad0a1e83d5bd78f9655fd05

View file

@ -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 { LL | fn baz<'a,'b>(x: &'a u32) -> &'static u32 {
| ------- this data with lifetime `'a`... | ------- this data with lifetime `'a`...
LL | bar(foo, x) 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 error: aborting due to previous error

View file

@ -5,7 +5,16 @@ LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> {
| -------- this data with lifetime `'a`... | -------- this data with lifetime `'a`...
... ...
LL | bar(foo, x) 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 error: aborting due to previous error

View file

@ -2,12 +2,15 @@ error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'
--> $DIR/issue-62097.rs:12:31 --> $DIR/issue-62097.rs:12:31
| |
LL | pub async fn run_dummy_fn(&self) { LL | pub async fn run_dummy_fn(&self) {
| ^^^^^ | ^^^^^ this data with an anonymous lifetime `'_`...
| |
| this data with an anonymous lifetime `'_`...
| ...is captured here...
LL | foo(|| self.bar()).await; 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 error: aborting due to previous error

View 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`.

View 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() {}

View 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`.

View 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
}
}
}

View 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`.

View file

@ -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`.

View 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
}
}
}

View 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`.

View file

@ -13,6 +13,23 @@ LL | |
LL | | 0 LL | | 0
LL | | }); LL | | });
| |______- immutable borrow occurs here | |______- 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 error: aborting due to previous error

View file

@ -8,13 +8,18 @@ LL | bar(|| {
LL | | LL | |
LL | | let _ = x; LL | | let _ = x;
LL | | }) LL | | })
| |_____^ ...is captured here... | |_____^ ...is used here...
| |
note: ...and is required to live as long as `'static` here note: ...and is required to live as long as `'static` here
--> $DIR/closure-bounds-static-cant-capture-borrowed.rs:5:5 --> $DIR/closure-bounds-static-cant-capture-borrowed.rs:5:5
| |
LL | bar(|| { 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 error: aborting due to previous error

View file

@ -7,6 +7,17 @@ LL | v.push(v.pop().unwrap());
| | | second mutable borrow occurs here | | | second mutable borrow occurs here
| | first borrow later used by call | | first borrow later used by call
| first mutable borrow occurs here | 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 error: aborting due to previous error

View file

@ -5,7 +5,7 @@ LL | fn dangle(x: &mut i32) -> &'static mut i32 {
| -------- this data with an anonymous lifetime `'_`... | -------- this data with an anonymous lifetime `'_`...
... ...
LL | x LL | x
| ^ ...is captured here... | ^ ...is used here...
... ...
LL | GeneratorState::Complete(c) => return c, LL | GeneratorState::Complete(c) => return c,
| - ...and is required to live as long as `'static` here | - ...and is required to live as long as `'static` here

View file

@ -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 () { LL | fn f(x: &impl for<'a> X<Y<'a> = &'a ()>) -> &'static () {
| ------------------------------- this data with an anonymous lifetime `'_`... | ------------------------------- this data with an anonymous lifetime `'_`...
LL | x.m() 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 error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
--> $DIR/projection-type-lifetime-mismatch.rs:22:7 --> $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 () { LL | fn g<T: for<'a> X<Y<'a> = &'a ()>>(x: &T) -> &'static () {
| -- this data with an anonymous lifetime `'_`... | -- this data with an anonymous lifetime `'_`...
LL | x.m() 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 error[E0759]: `x` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
--> $DIR/projection-type-lifetime-mismatch.rs:27:7 --> $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 () { LL | fn h(x: &()) -> &'static () {
| --- this data with an anonymous lifetime `'_`... | --- this data with an anonymous lifetime `'_`...
LL | x.m() 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 error: aborting due to 3 previous errors

View file

@ -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>) { LL | fn with_dyn_debug_static<'a>(x: Box<dyn Debug + 'a>) {
| ------------------- this data with lifetime `'a`... | ------------------- this data with lifetime `'a`...
LL | static_val(x); LL | static_val(x);
| ^ ...is captured here... | ^ ...is used here...
| |
note: ...and is required to live as long as `'static` here note: ...and is required to live as long as `'static` here
--> $DIR/dyn-trait.rs:20:5 --> $DIR/dyn-trait.rs:20:5

View file

@ -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 --> $DIR/must_outlive_least_region_or_bound.rs:9:46
| |
LL | fn elided2(x: &i32) -> impl Copy + 'static { x } LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
| ---- ^ ...is captured here... | ---- ^ ...is used here...
| | | |
| this data with an anonymous lifetime `'_`... | 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 --> $DIR/must_outlive_least_region_or_bound.rs:11:55
| |
LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x } LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
| ------- ^ ...is captured here... | ------- ^ ...is used here...
| | | |
| this data with lifetime `'a`... | 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 --> $DIR/must_outlive_least_region_or_bound.rs:24:65
| |
LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) } 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 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 --> $DIR/must_outlive_least_region_or_bound.rs:29:69
| |
LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } 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 note: ...and is required to live as long as `'static` here
--> $DIR/must_outlive_least_region_or_bound.rs:29:34 --> $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 --> $DIR/must_outlive_least_region_or_bound.rs:16:50
| |
LL | fn elided3(x: &i32) -> Box<dyn Debug> { Box::new(x) } 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 `'_`... | 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 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) } 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 --> $DIR/must_outlive_least_region_or_bound.rs:18:59
| |
LL | fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug> { Box::new(x) } 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`... | 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 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) } 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 --> $DIR/must_outlive_least_region_or_bound.rs:20:60
| |
LL | fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) } 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 `'_`... | 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` 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) } 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 --> $DIR/must_outlive_least_region_or_bound.rs:22:69
| |
LL | fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) } 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` 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) } LL | fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'a> { Box::new(x) }

View file

@ -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> { LL | fn foo<T: Any>(value: &T) -> Box<dyn Any> {
| -- this data with an anonymous lifetime `'_`... | -- this data with an anonymous lifetime `'_`...
LL | Box::new(value) as Box<dyn Any> 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 help: to declare that the trait object captures data from argument `value`, you can add an explicit `'_` lifetime bound
| |

View file

@ -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 { LL | fn foo(x: &u32) -> &'static u32 {
| ---- this data with an anonymous lifetime `'_`... | ---- this data with an anonymous lifetime `'_`...
LL | &*x 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 error: aborting due to previous error

View file

@ -4,7 +4,7 @@ error[E0759]: `foo` has an anonymous lifetime `'_` but it needs to satisfy a `'s
LL | fn inner(mut foo: &[u8]) { LL | fn inner(mut foo: &[u8]) {
| ----- this data with an anonymous lifetime `'_`... | ----- this data with an anonymous lifetime `'_`...
LL | let refcell = RefCell::new(&mut foo); LL | let refcell = RefCell::new(&mut foo);
| ^^^^^^^^ ...is captured here... | ^^^^^^^^ ...is used here...
... ...
LL | read_thing(read); LL | read_thing(read);
| ---- ...and is required to live as long as `'static` here | ---- ...and is required to live as long as `'static` here

View file

@ -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 { LL | fn foo<'a>(_: &'a u32) -> &'static u32 {
| ------- this data with lifetime `'a`... | ------- this data with lifetime `'a`...
LL | <Foo<'a>>::C 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 error: aborting due to previous error

View file

@ -5,8 +5,16 @@ LL | fn load(ss: &mut SomeStruct) -> Box<dyn SomeTrait> {
| --------------- this data with an anonymous lifetime `'_`... | --------------- this data with an anonymous lifetime `'_`...
... ...
LL | ss.r 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 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 + '_> { LL | fn load(ss: &mut SomeStruct) -> Box<dyn SomeTrait + '_> {

View file

@ -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> { LL | fn a(v: &[u8]) -> Box<dyn Foo + 'static> {
| ----- this data with an anonymous lifetime `'_`... | ----- this data with an anonymous lifetime `'_`...
LL | let x: Box<dyn Foo + 'static> = Box::new(v); 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` 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> { LL | fn b(v: &[u8]) -> Box<dyn Foo + 'static> {
| ----- this data with an anonymous lifetime `'_`... | ----- this data with an anonymous lifetime `'_`...
LL | Box::new(v) 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` help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v`
| |
LL | fn b(v: &[u8]) -> Box<dyn Foo + '_> { 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 `'_`... | ----- this data with an anonymous lifetime `'_`...
... ...
LL | Box::new(v) 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 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 + '_> { LL | fn c(v: &[u8]) -> Box<dyn Foo + '_> {

View file

@ -4,7 +4,7 @@ error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'
LL | pub fn chase_cat(&mut self) { LL | pub fn chase_cat(&mut self) {
| --------- this data with an anonymous lifetime `'_`... | --------- this data with an anonymous lifetime `'_`...
LL | let p: &'static mut usize = &mut self.cats_chased; 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 error: aborting due to previous error

View file

@ -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> { LL | fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> {
| ------------------ this data with lifetime `'a`... | ------------------ this data with lifetime `'a`...
LL | Box::new(B(&*v)) as Box<dyn X> 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` 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> { LL | fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'a> {

View file

@ -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> { LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
| ---------------- this data with lifetime `'a`... | ---------------- this data with lifetime `'a`...
LL | Box::new(B(&*v)) as Box<dyn X> 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` 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> { LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'a> {

View file

@ -5,8 +5,16 @@ LL | fn static_proc(x: &isize) -> Box<dyn FnMut() -> (isize) + 'static> {
| ------ this data with an anonymous lifetime `'_`... | ------ this data with an anonymous lifetime `'_`...
LL | // This is illegal, because the region bound on `proc` is 'static. LL | // This is illegal, because the region bound on `proc` is 'static.
LL | Box::new(move || { *x }) 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` 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) + '_> { LL | fn static_proc(x: &isize) -> Box<dyn FnMut() -> (isize) + '_> {

View file

@ -17,7 +17,7 @@ error[E0759]: `u` has an anonymous lifetime `'_` but it needs to satisfy a `'sta
LL | fn error(u: &(), v: &()) { LL | fn error(u: &(), v: &()) {
| --- this data with an anonymous lifetime `'_`... | --- this data with an anonymous lifetime `'_`...
LL | static_id(&u); LL | static_id(&u);
| ^^^^^^^^^ -- ...is captured here... | ^^^^^^^^^ -- ...is used here...
| |
note: ...and is required to live as long as `'static` here note: ...and is required to live as long as `'static` here
--> $DIR/regions-static-bound.rs:10:5 --> $DIR/regions-static-bound.rs:10:5
@ -32,7 +32,7 @@ LL | fn error(u: &(), v: &()) {
| --- this data with an anonymous lifetime `'_`... | --- this data with an anonymous lifetime `'_`...
LL | static_id(&u); LL | static_id(&u);
LL | static_id_indirect(&v); LL | static_id_indirect(&v);
| ^^^^^^^^^^^^^^^^^^ -- ...is captured here... | ^^^^^^^^^^^^^^^^^^ -- ...is used here...
| |
note: ...and is required to live as long as `'static` here note: ...and is required to live as long as `'static` here
--> $DIR/regions-static-bound.rs:11:5 --> $DIR/regions-static-bound.rs:11:5

View file

@ -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 () { LL | fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32> + 'a>) -> &'a () {
| -------------------------------------- this data with lifetime `'a`... | -------------------------------------- this data with lifetime `'a`...
LL | val.use_self() 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 note: the used `impl` has a `'static` requirement
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:60:30 --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:60:30

View file

@ -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 { LL | fn use_it<'a, T>(val: &'a dyn ObjectTrait<T>) -> impl OtherTrait<'a> + 'a {
| ---------------------- this data with lifetime `'a`... | ---------------------- this data with lifetime `'a`...
LL | val.use_self::<T>() 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 note: the used `impl` has a `'static` requirement
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:14:32 --> $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 { LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
| ------------------- this data with lifetime `'a`... | ------------------- this data with lifetime `'a`...
LL | val.use_self() 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 note: the used `impl` has a `'static` requirement
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:64:14 --> $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> { LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> {
| ------------------- this data with lifetime `'a`... | ------------------- this data with lifetime `'a`...
LL | val.use_self() 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 note: the used `impl` has a `'static` requirement
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:85:26 --> $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 { LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a {
| ------------------- this data with lifetime `'a`... | ------------------- this data with lifetime `'a`...
LL | MyTrait::use_self(val) LL | MyTrait::use_self(val)
| ^^^ ...is captured here... | ^^^ ...is used here...
| |
note: ...and is required to live as long as `'static` here note: ...and is required to live as long as `'static` here
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:108:9 --> $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 () { LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () {
| ------------------- this data with lifetime `'a`... | ------------------- this data with lifetime `'a`...
LL | val.use_self() 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 note: the used `impl` has a `'static` requirement
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:31:26 --> $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 () { LL | fn use_it<'a>(val: &'a Box<dyn ObjectTrait + 'a>) -> &'a () {
| ----------------------------- this data with lifetime `'a`... | ----------------------------- this data with lifetime `'a`...
LL | val.use_self() 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 note: the used `impl` has a `'static` requirement
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:48:30 --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:48:30

View file

@ -7,7 +7,7 @@ LL | fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> {
LL | remaining: self.0.iter(), LL | remaining: self.0.iter(),
| ------ ^^^^ | ------ ^^^^
| | | |
| ...is captured here... | ...is used here...
| |
note: ...and is required to live as long as `'static` here note: ...and is required to live as long as `'static` here
--> $DIR/trait-object-nested-in-impl-trait.rs:27:23 --> $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(), LL | remaining: self.0.iter(),
| ------ ^^^^ | ------ ^^^^
| | | |
| ...is captured here... | ...is used here...
| |
note: ...and is required to live as long as `'static` here note: ...and is required to live as long as `'static` here
--> $DIR/trait-object-nested-in-impl-trait.rs:38:23 --> $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(), LL | remaining: self.0.iter(),
| ------ ^^^^ | ------ ^^^^
| | | |
| ...is captured here... | ...is used here...
| |
note: ...and is required to live as long as `'static` here note: ...and is required to live as long as `'static` here
--> $DIR/trait-object-nested-in-impl-trait.rs:49:30 --> $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(), LL | remaining: self.0.iter(),
| ------ ^^^^ | ------ ^^^^
| | | |
| ...is captured here... | ...is used here...
| |
note: ...and is required to live as long as `'static` here note: ...and is required to live as long as `'static` here
--> $DIR/trait-object-nested-in-impl-trait.rs:60:30 --> $DIR/trait-object-nested-in-impl-trait.rs:60:30

View file

@ -29,4 +29,22 @@ fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
y.get_b() // ERROR 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() {} fn main() {}

View file

@ -36,12 +36,88 @@ LL | fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
LL | let y = x as &dyn Bar<'_, '_>; LL | let y = x as &dyn Bar<'_, '_>;
| - ^^ | - ^^
| | | |
| ...is captured here... | ...is used here...
LL | LL |
LL | y.get_b() // ERROR 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. Some errors have detailed explanations: E0308, E0759.
For more information about an error, try `rustc --explain E0308`. For more information about an error, try `rustc --explain E0308`.

View file

@ -5,8 +5,18 @@ LL | fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
| ---- this data with an anonymous lifetime `'_`... | ---- this data with an anonymous lifetime `'_`...
LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
LL | Box::new(items.iter()) 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 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> + '_> { LL | fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T> + '_> {