Auto merge of #97284 - b-naber:constraint-dyn-impl-suggestion, r=estebank
Add suggestion for relaxing static lifetime bounds on dyn trait impls in NLL This PR introduces suggestions for relaxing static lifetime bounds on impls of dyn trait items for NLL similar to what is already available in lexical region diagnostics. Fixes https://github.com/rust-lang/rust/issues/95701 r? `@estebank`
This commit is contained in:
commit
ed76b773b5
23 changed files with 368 additions and 104 deletions
|
@ -95,7 +95,7 @@ pub struct OutlivesConstraint<'tcx> {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
|
|
||||||
/// What caused this constraint?
|
/// What caused this constraint?
|
||||||
pub category: ConstraintCategory,
|
pub category: ConstraintCategory<'tcx>,
|
||||||
|
|
||||||
/// Variance diagnostic information
|
/// Variance diagnostic information
|
||||||
pub variance_info: VarianceDiagInfo<'tcx>,
|
pub variance_info: VarianceDiagInfo<'tcx>,
|
||||||
|
|
|
@ -788,7 +788,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
err: &mut Diagnostic,
|
err: &mut Diagnostic,
|
||||||
location: Location,
|
location: Location,
|
||||||
issued_borrow: &BorrowData<'tcx>,
|
issued_borrow: &BorrowData<'tcx>,
|
||||||
explanation: BorrowExplanation,
|
explanation: BorrowExplanation<'tcx>,
|
||||||
) {
|
) {
|
||||||
let used_in_call = matches!(
|
let used_in_call = matches!(
|
||||||
explanation,
|
explanation,
|
||||||
|
@ -1088,7 +1088,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
BorrowExplanation::MustBeValidFor {
|
BorrowExplanation::MustBeValidFor {
|
||||||
category:
|
category:
|
||||||
category @ (ConstraintCategory::Return(_)
|
category @ (ConstraintCategory::Return(_)
|
||||||
| ConstraintCategory::CallArgument
|
| ConstraintCategory::CallArgument(_)
|
||||||
| ConstraintCategory::OpaqueType),
|
| ConstraintCategory::OpaqueType),
|
||||||
from_closure: false,
|
from_closure: false,
|
||||||
ref region_name,
|
ref region_name,
|
||||||
|
@ -1147,7 +1147,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
borrow: &BorrowData<'tcx>,
|
borrow: &BorrowData<'tcx>,
|
||||||
drop_span: Span,
|
drop_span: Span,
|
||||||
borrow_spans: UseSpans<'tcx>,
|
borrow_spans: UseSpans<'tcx>,
|
||||||
explanation: BorrowExplanation,
|
explanation: BorrowExplanation<'tcx>,
|
||||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
||||||
debug!(
|
debug!(
|
||||||
"report_local_value_does_not_live_long_enough(\
|
"report_local_value_does_not_live_long_enough(\
|
||||||
|
@ -1352,7 +1352,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
drop_span: Span,
|
drop_span: Span,
|
||||||
borrow_spans: UseSpans<'tcx>,
|
borrow_spans: UseSpans<'tcx>,
|
||||||
proper_span: Span,
|
proper_span: Span,
|
||||||
explanation: BorrowExplanation,
|
explanation: BorrowExplanation<'tcx>,
|
||||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
||||||
debug!(
|
debug!(
|
||||||
"report_temporary_value_does_not_live_long_enough(\
|
"report_temporary_value_does_not_live_long_enough(\
|
||||||
|
@ -1410,7 +1410,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
borrow: &BorrowData<'tcx>,
|
borrow: &BorrowData<'tcx>,
|
||||||
borrow_span: Span,
|
borrow_span: Span,
|
||||||
return_span: Span,
|
return_span: Span,
|
||||||
category: ConstraintCategory,
|
category: ConstraintCategory<'tcx>,
|
||||||
opt_place_desc: Option<&String>,
|
opt_place_desc: Option<&String>,
|
||||||
) -> Option<DiagnosticBuilder<'cx, ErrorGuaranteed>> {
|
) -> Option<DiagnosticBuilder<'cx, ErrorGuaranteed>> {
|
||||||
let return_kind = match category {
|
let return_kind = match category {
|
||||||
|
@ -1508,7 +1508,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
use_span: UseSpans<'tcx>,
|
use_span: UseSpans<'tcx>,
|
||||||
var_span: Span,
|
var_span: Span,
|
||||||
fr_name: &RegionName,
|
fr_name: &RegionName,
|
||||||
category: ConstraintCategory,
|
category: ConstraintCategory<'tcx>,
|
||||||
constraint_span: Span,
|
constraint_span: Span,
|
||||||
captured_var: &str,
|
captured_var: &str,
|
||||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
||||||
|
@ -1559,7 +1559,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
let msg = format!("{} is returned here", kind);
|
let msg = format!("{} is returned here", kind);
|
||||||
err.span_note(constraint_span, &msg);
|
err.span_note(constraint_span, &msg);
|
||||||
}
|
}
|
||||||
ConstraintCategory::CallArgument => {
|
ConstraintCategory::CallArgument(_) => {
|
||||||
fr_name.highlight_region_name(&mut err);
|
fr_name.highlight_region_name(&mut err);
|
||||||
if matches!(use_span.generator_kind(), Some(GeneratorKind::Async(_))) {
|
if matches!(use_span.generator_kind(), Some(GeneratorKind::Async(_))) {
|
||||||
err.note(
|
err.note(
|
||||||
|
|
|
@ -24,7 +24,7 @@ use crate::{
|
||||||
use super::{find_use, RegionName, UseSpans};
|
use super::{find_use, RegionName, UseSpans};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) enum BorrowExplanation {
|
pub(crate) enum BorrowExplanation<'tcx> {
|
||||||
UsedLater(LaterUseKind, Span, Option<Span>),
|
UsedLater(LaterUseKind, Span, Option<Span>),
|
||||||
UsedLaterInLoop(LaterUseKind, Span, Option<Span>),
|
UsedLaterInLoop(LaterUseKind, Span, Option<Span>),
|
||||||
UsedLaterWhenDropped {
|
UsedLaterWhenDropped {
|
||||||
|
@ -33,7 +33,7 @@ pub(crate) enum BorrowExplanation {
|
||||||
should_note_order: bool,
|
should_note_order: bool,
|
||||||
},
|
},
|
||||||
MustBeValidFor {
|
MustBeValidFor {
|
||||||
category: ConstraintCategory,
|
category: ConstraintCategory<'tcx>,
|
||||||
from_closure: bool,
|
from_closure: bool,
|
||||||
span: Span,
|
span: Span,
|
||||||
region_name: RegionName,
|
region_name: RegionName,
|
||||||
|
@ -51,11 +51,11 @@ pub(crate) enum LaterUseKind {
|
||||||
Other,
|
Other,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BorrowExplanation {
|
impl<'tcx> BorrowExplanation<'tcx> {
|
||||||
pub(crate) fn is_explained(&self) -> bool {
|
pub(crate) fn is_explained(&self) -> bool {
|
||||||
!matches!(self, BorrowExplanation::Unexplained)
|
!matches!(self, BorrowExplanation::Unexplained)
|
||||||
}
|
}
|
||||||
pub(crate) fn add_explanation_to_diagnostic<'tcx>(
|
pub(crate) fn add_explanation_to_diagnostic(
|
||||||
&self,
|
&self,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
body: &Body<'tcx>,
|
body: &Body<'tcx>,
|
||||||
|
@ -276,7 +276,7 @@ impl BorrowExplanation {
|
||||||
pub(crate) fn add_lifetime_bound_suggestion_to_diagnostic(
|
pub(crate) fn add_lifetime_bound_suggestion_to_diagnostic(
|
||||||
&self,
|
&self,
|
||||||
err: &mut Diagnostic,
|
err: &mut Diagnostic,
|
||||||
category: &ConstraintCategory,
|
category: &ConstraintCategory<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
region_name: &RegionName,
|
region_name: &RegionName,
|
||||||
) {
|
) {
|
||||||
|
@ -305,7 +305,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
&self,
|
&self,
|
||||||
borrow_region: RegionVid,
|
borrow_region: RegionVid,
|
||||||
outlived_region: RegionVid,
|
outlived_region: RegionVid,
|
||||||
) -> (ConstraintCategory, bool, Span, Option<RegionName>) {
|
) -> (ConstraintCategory<'tcx>, bool, Span, Option<RegionName>) {
|
||||||
let BlameConstraint { category, from_closure, cause, variance_info: _ } =
|
let BlameConstraint { category, from_closure, cause, variance_info: _ } =
|
||||||
self.regioncx.best_blame_constraint(
|
self.regioncx.best_blame_constraint(
|
||||||
&self.body,
|
&self.body,
|
||||||
|
@ -337,7 +337,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
location: Location,
|
location: Location,
|
||||||
borrow: &BorrowData<'tcx>,
|
borrow: &BorrowData<'tcx>,
|
||||||
kind_place: Option<(WriteKind, Place<'tcx>)>,
|
kind_place: Option<(WriteKind, Place<'tcx>)>,
|
||||||
) -> BorrowExplanation {
|
) -> BorrowExplanation<'tcx> {
|
||||||
debug!(
|
debug!(
|
||||||
"explain_why_borrow_contains_point(location={:?}, borrow={:?}, kind_place={:?})",
|
"explain_why_borrow_contains_point(location={:?}, borrow={:?}, kind_place={:?})",
|
||||||
location, borrow, kind_place
|
location, borrow, kind_place
|
||||||
|
|
|
@ -161,7 +161,7 @@ impl OutlivesSuggestionBuilder {
|
||||||
pub(crate) fn intermediate_suggestion(
|
pub(crate) fn intermediate_suggestion(
|
||||||
&mut self,
|
&mut self,
|
||||||
mbcx: &MirBorrowckCtxt<'_, '_>,
|
mbcx: &MirBorrowckCtxt<'_, '_>,
|
||||||
errci: &ErrorConstraintInfo,
|
errci: &ErrorConstraintInfo<'_>,
|
||||||
diag: &mut Diagnostic,
|
diag: &mut Diagnostic,
|
||||||
) {
|
) {
|
||||||
// Emit an intermediate note.
|
// Emit an intermediate note.
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
//! Error reporting machinery for lifetime errors.
|
//! Error reporting machinery for lifetime errors.
|
||||||
|
|
||||||
use rustc_errors::{Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
|
use rustc_data_structures::stable_set::FxHashSet;
|
||||||
|
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan};
|
||||||
|
use rustc_hir::def_id::DefId;
|
||||||
|
use rustc_hir::intravisit::Visitor;
|
||||||
|
use rustc_hir::{self as hir, Item, ItemKind, Node};
|
||||||
use rustc_infer::infer::{
|
use rustc_infer::infer::{
|
||||||
error_reporting::nice_region_error::{
|
error_reporting::nice_region_error::{
|
||||||
self, find_anon_type, find_param_with_region, suggest_adding_lifetime_params,
|
self, find_anon_type, find_param_with_region, suggest_adding_lifetime_params,
|
||||||
NiceRegionError,
|
HirTraitObjectVisitor, NiceRegionError, TraitObjectVisitor,
|
||||||
},
|
},
|
||||||
error_reporting::unexpected_hidden_region_diagnostic,
|
error_reporting::unexpected_hidden_region_diagnostic,
|
||||||
NllRegionVariableOrigin, RelateParamBound,
|
NllRegionVariableOrigin, RelateParamBound,
|
||||||
|
@ -12,8 +16,11 @@ use rustc_infer::infer::{
|
||||||
use rustc_middle::hir::place::PlaceBase;
|
use rustc_middle::hir::place::PlaceBase;
|
||||||
use rustc_middle::mir::{ConstraintCategory, ReturnConstraint};
|
use rustc_middle::mir::{ConstraintCategory, ReturnConstraint};
|
||||||
use rustc_middle::ty::subst::InternalSubsts;
|
use rustc_middle::ty::subst::InternalSubsts;
|
||||||
|
use rustc_middle::ty::Region;
|
||||||
|
use rustc_middle::ty::TypeVisitor;
|
||||||
use rustc_middle::ty::{self, RegionVid, Ty};
|
use rustc_middle::ty::{self, RegionVid, Ty};
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
|
use rustc_span::symbol::Ident;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
use crate::borrowck_errors;
|
use crate::borrowck_errors;
|
||||||
|
@ -27,7 +34,7 @@ use crate::{
|
||||||
MirBorrowckCtxt,
|
MirBorrowckCtxt,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl ConstraintDescription for ConstraintCategory {
|
impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> {
|
||||||
fn description(&self) -> &'static str {
|
fn description(&self) -> &'static str {
|
||||||
// Must end with a space. Allows for empty names to be provided.
|
// Must end with a space. Allows for empty names to be provided.
|
||||||
match self {
|
match self {
|
||||||
|
@ -37,7 +44,7 @@ impl ConstraintDescription for ConstraintCategory {
|
||||||
ConstraintCategory::UseAsConst => "using this value as a constant ",
|
ConstraintCategory::UseAsConst => "using this value as a constant ",
|
||||||
ConstraintCategory::UseAsStatic => "using this value as a static ",
|
ConstraintCategory::UseAsStatic => "using this value as a static ",
|
||||||
ConstraintCategory::Cast => "cast ",
|
ConstraintCategory::Cast => "cast ",
|
||||||
ConstraintCategory::CallArgument => "argument ",
|
ConstraintCategory::CallArgument(_) => "argument ",
|
||||||
ConstraintCategory::TypeAnnotation => "type annotation ",
|
ConstraintCategory::TypeAnnotation => "type annotation ",
|
||||||
ConstraintCategory::ClosureBounds => "closure body ",
|
ConstraintCategory::ClosureBounds => "closure body ",
|
||||||
ConstraintCategory::SizedBound => "proving this value is `Sized` ",
|
ConstraintCategory::SizedBound => "proving this value is `Sized` ",
|
||||||
|
@ -101,7 +108,7 @@ pub(crate) enum RegionErrorKind<'tcx> {
|
||||||
|
|
||||||
/// Information about the various region constraints involved in a borrow checker error.
|
/// Information about the various region constraints involved in a borrow checker error.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct ErrorConstraintInfo {
|
pub struct ErrorConstraintInfo<'tcx> {
|
||||||
// fr: outlived_fr
|
// fr: outlived_fr
|
||||||
pub(super) fr: RegionVid,
|
pub(super) fr: RegionVid,
|
||||||
pub(super) fr_is_local: bool,
|
pub(super) fr_is_local: bool,
|
||||||
|
@ -109,7 +116,7 @@ pub struct ErrorConstraintInfo {
|
||||||
pub(super) outlived_fr_is_local: bool,
|
pub(super) outlived_fr_is_local: bool,
|
||||||
|
|
||||||
// Category and span for best blame constraint
|
// Category and span for best blame constraint
|
||||||
pub(super) category: ConstraintCategory,
|
pub(super) category: ConstraintCategory<'tcx>,
|
||||||
pub(super) span: Span,
|
pub(super) span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,6 +263,70 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||||
outlives_suggestion.add_suggestion(self);
|
outlives_suggestion.add_suggestion(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_impl_ident_and_self_ty_from_trait(
|
||||||
|
&self,
|
||||||
|
def_id: DefId,
|
||||||
|
trait_objects: &FxHashSet<DefId>,
|
||||||
|
) -> Option<(Ident, &'tcx hir::Ty<'tcx>)> {
|
||||||
|
let tcx = self.infcx.tcx;
|
||||||
|
match tcx.hir().get_if_local(def_id) {
|
||||||
|
Some(Node::ImplItem(impl_item)) => {
|
||||||
|
match tcx.hir().find_by_def_id(tcx.hir().get_parent_item(impl_item.hir_id())) {
|
||||||
|
Some(Node::Item(Item {
|
||||||
|
kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
|
||||||
|
..
|
||||||
|
})) => Some((impl_item.ident, self_ty)),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(Node::TraitItem(trait_item)) => {
|
||||||
|
let trait_did = tcx.hir().get_parent_item(trait_item.hir_id());
|
||||||
|
match tcx.hir().find_by_def_id(trait_did) {
|
||||||
|
Some(Node::Item(Item { kind: ItemKind::Trait(..), .. })) => {
|
||||||
|
// The method being called is defined in the `trait`, but the `'static`
|
||||||
|
// obligation comes from the `impl`. Find that `impl` so that we can point
|
||||||
|
// at it in the suggestion.
|
||||||
|
let trait_did = trait_did.to_def_id();
|
||||||
|
match tcx
|
||||||
|
.hir()
|
||||||
|
.trait_impls(trait_did)
|
||||||
|
.iter()
|
||||||
|
.filter_map(|&impl_did| {
|
||||||
|
match tcx.hir().get_if_local(impl_did.to_def_id()) {
|
||||||
|
Some(Node::Item(Item {
|
||||||
|
kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
|
||||||
|
..
|
||||||
|
})) if trait_objects.iter().all(|did| {
|
||||||
|
// FIXME: we should check `self_ty` against the receiver
|
||||||
|
// type in the `UnifyReceiver` context, but for now, use
|
||||||
|
// this imperfect proxy. This will fail if there are
|
||||||
|
// multiple `impl`s for the same trait like
|
||||||
|
// `impl Foo for Box<dyn Bar>` and `impl Foo for dyn Bar`.
|
||||||
|
// In that case, only the first one will get suggestions.
|
||||||
|
let mut traits = vec![];
|
||||||
|
let mut hir_v = HirTraitObjectVisitor(&mut traits, *did);
|
||||||
|
hir_v.visit_ty(self_ty);
|
||||||
|
!traits.is_empty()
|
||||||
|
}) =>
|
||||||
|
{
|
||||||
|
Some(self_ty)
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.next()
|
||||||
|
{
|
||||||
|
Some(self_ty) => Some((trait_item.ident, self_ty)),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Report an error because the universal region `fr` was required to outlive
|
/// Report an error because the universal region `fr` was required to outlive
|
||||||
/// `outlived_fr` but it is not known to do so. For example:
|
/// `outlived_fr` but it is not known to do so. For example:
|
||||||
///
|
///
|
||||||
|
@ -279,6 +350,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||||
});
|
});
|
||||||
|
|
||||||
debug!("report_region_error: category={:?} {:?} {:?}", category, cause, variance_info);
|
debug!("report_region_error: category={:?} {:?} {:?}", category, cause, variance_info);
|
||||||
|
|
||||||
// Check if we can use one of the "nice region errors".
|
// Check if we can use one of the "nice region errors".
|
||||||
if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) {
|
if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) {
|
||||||
let nice = NiceRegionError::new_from_span(self.infcx, cause.span, o, f);
|
let nice = NiceRegionError::new_from_span(self.infcx, cause.span, o, f);
|
||||||
|
@ -312,7 +384,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||||
self.report_fnmut_error(&errci, kind)
|
self.report_fnmut_error(&errci, kind)
|
||||||
}
|
}
|
||||||
(ConstraintCategory::Assignment, true, false)
|
(ConstraintCategory::Assignment, true, false)
|
||||||
| (ConstraintCategory::CallArgument, true, false) => {
|
| (ConstraintCategory::CallArgument(_), true, false) => {
|
||||||
let mut db = self.report_escaping_data_error(&errci);
|
let mut db = self.report_escaping_data_error(&errci);
|
||||||
|
|
||||||
outlives_suggestion.intermediate_suggestion(self, &errci, &mut db);
|
outlives_suggestion.intermediate_suggestion(self, &errci, &mut db);
|
||||||
|
@ -405,7 +477,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||||
/// ```
|
/// ```
|
||||||
fn report_fnmut_error(
|
fn report_fnmut_error(
|
||||||
&self,
|
&self,
|
||||||
errci: &ErrorConstraintInfo,
|
errci: &ErrorConstraintInfo<'tcx>,
|
||||||
kind: ReturnConstraint,
|
kind: ReturnConstraint,
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||||
let ErrorConstraintInfo { outlived_fr, span, .. } = errci;
|
let ErrorConstraintInfo { outlived_fr, span, .. } = errci;
|
||||||
|
@ -486,7 +558,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||||
/// ```
|
/// ```
|
||||||
fn report_escaping_data_error(
|
fn report_escaping_data_error(
|
||||||
&self,
|
&self,
|
||||||
errci: &ErrorConstraintInfo,
|
errci: &ErrorConstraintInfo<'tcx>,
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||||
let ErrorConstraintInfo { span, category, .. } = errci;
|
let ErrorConstraintInfo { span, category, .. } = errci;
|
||||||
|
|
||||||
|
@ -548,24 +620,28 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||||
// Only show an extra note if we can find an 'error region' for both of the region
|
// Only show an extra note if we can find an 'error region' for both of the region
|
||||||
// variables. This avoids showing a noisy note that just mentions 'synthetic' regions
|
// variables. This avoids showing a noisy note that just mentions 'synthetic' regions
|
||||||
// that don't help the user understand the error.
|
// that don't help the user understand the error.
|
||||||
if self.to_error_region(errci.fr).is_some()
|
match (self.to_error_region(errci.fr), self.to_error_region(errci.outlived_fr)) {
|
||||||
&& self.to_error_region(errci.outlived_fr).is_some()
|
(Some(f), Some(o)) => {
|
||||||
{
|
self.maybe_suggest_constrain_dyn_trait_impl(&mut diag, f, o, category);
|
||||||
let fr_region_name = self.give_region_a_name(errci.fr).unwrap();
|
|
||||||
fr_region_name.highlight_region_name(&mut diag);
|
|
||||||
let outlived_fr_region_name = self.give_region_a_name(errci.outlived_fr).unwrap();
|
|
||||||
outlived_fr_region_name.highlight_region_name(&mut diag);
|
|
||||||
|
|
||||||
diag.span_label(
|
let fr_region_name = self.give_region_a_name(errci.fr).unwrap();
|
||||||
*span,
|
fr_region_name.highlight_region_name(&mut diag);
|
||||||
format!(
|
let outlived_fr_region_name = self.give_region_a_name(errci.outlived_fr).unwrap();
|
||||||
"{}requires that `{}` must outlive `{}`",
|
outlived_fr_region_name.highlight_region_name(&mut diag);
|
||||||
category.description(),
|
|
||||||
fr_region_name,
|
diag.span_label(
|
||||||
outlived_fr_region_name,
|
*span,
|
||||||
),
|
format!(
|
||||||
);
|
"{}requires that `{}` must outlive `{}`",
|
||||||
|
category.description(),
|
||||||
|
fr_region_name,
|
||||||
|
outlived_fr_region_name,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
diag
|
diag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -586,7 +662,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||||
/// ```
|
/// ```
|
||||||
fn report_general_error(
|
fn report_general_error(
|
||||||
&self,
|
&self,
|
||||||
errci: &ErrorConstraintInfo,
|
errci: &ErrorConstraintInfo<'tcx>,
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||||
let ErrorConstraintInfo {
|
let ErrorConstraintInfo {
|
||||||
fr,
|
fr,
|
||||||
|
@ -699,6 +775,100 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn maybe_suggest_constrain_dyn_trait_impl(
|
||||||
|
&self,
|
||||||
|
diag: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
|
||||||
|
f: Region<'tcx>,
|
||||||
|
o: Region<'tcx>,
|
||||||
|
category: &ConstraintCategory<'tcx>,
|
||||||
|
) {
|
||||||
|
if !o.is_static() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let tcx = self.infcx.tcx;
|
||||||
|
|
||||||
|
let instance = if let ConstraintCategory::CallArgument(Some(func_ty)) = category {
|
||||||
|
let (fn_did, substs) = match func_ty.kind() {
|
||||||
|
ty::FnDef(fn_did, substs) => (fn_did, substs),
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
debug!(?fn_did, ?substs);
|
||||||
|
|
||||||
|
// Only suggest this on function calls, not closures
|
||||||
|
let ty = tcx.type_of(fn_did);
|
||||||
|
debug!("ty: {:?}, ty.kind: {:?}", ty, ty.kind());
|
||||||
|
if let ty::Closure(_, _) = ty.kind() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Ok(Some(instance)) = ty::Instance::resolve(
|
||||||
|
tcx,
|
||||||
|
self.param_env,
|
||||||
|
*fn_did,
|
||||||
|
self.infcx.resolve_vars_if_possible(substs),
|
||||||
|
) {
|
||||||
|
instance
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let param = match find_param_with_region(tcx, f, o) {
|
||||||
|
Some(param) => param,
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
debug!(?param);
|
||||||
|
|
||||||
|
let mut visitor = TraitObjectVisitor(FxHashSet::default());
|
||||||
|
visitor.visit_ty(param.param_ty);
|
||||||
|
|
||||||
|
let Some((ident, self_ty)) =
|
||||||
|
self.get_impl_ident_and_self_ty_from_trait(instance.def_id(), &visitor.0) else {return};
|
||||||
|
|
||||||
|
self.suggest_constrain_dyn_trait_in_impl(diag, &visitor.0, ident, self_ty);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(self, err), level = "debug")]
|
||||||
|
fn suggest_constrain_dyn_trait_in_impl(
|
||||||
|
&self,
|
||||||
|
err: &mut Diagnostic,
|
||||||
|
found_dids: &FxHashSet<DefId>,
|
||||||
|
ident: Ident,
|
||||||
|
self_ty: &hir::Ty<'_>,
|
||||||
|
) -> bool {
|
||||||
|
debug!("err: {:#?}", err);
|
||||||
|
let mut suggested = false;
|
||||||
|
for found_did in found_dids {
|
||||||
|
let mut traits = vec![];
|
||||||
|
let mut hir_v = HirTraitObjectVisitor(&mut traits, *found_did);
|
||||||
|
hir_v.visit_ty(&self_ty);
|
||||||
|
debug!("trait spans found: {:?}", traits);
|
||||||
|
for span in &traits {
|
||||||
|
let mut multi_span: MultiSpan = vec![*span].into();
|
||||||
|
multi_span.push_span_label(
|
||||||
|
*span,
|
||||||
|
"this has an implicit `'static` lifetime requirement".to_string(),
|
||||||
|
);
|
||||||
|
multi_span.push_span_label(
|
||||||
|
ident.span,
|
||||||
|
"calling this method introduces the `impl`'s 'static` requirement".to_string(),
|
||||||
|
);
|
||||||
|
err.span_note(multi_span, "the used `impl` has a `'static` requirement");
|
||||||
|
err.span_suggestion_verbose(
|
||||||
|
span.shrink_to_hi(),
|
||||||
|
"consider relaxing the implicit `'static` requirement",
|
||||||
|
" + '_".to_string(),
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
suggested = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
suggested
|
||||||
|
}
|
||||||
|
|
||||||
fn suggest_adding_lifetime_params(
|
fn suggest_adding_lifetime_params(
|
||||||
&self,
|
&self,
|
||||||
diag: &mut Diagnostic,
|
diag: &mut Diagnostic,
|
||||||
|
|
|
@ -87,7 +87,7 @@ pub struct RegionInferenceContext<'tcx> {
|
||||||
|
|
||||||
/// Map closure bounds to a `Span` that should be used for error reporting.
|
/// Map closure bounds to a `Span` that should be used for error reporting.
|
||||||
closure_bounds_mapping:
|
closure_bounds_mapping:
|
||||||
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>,
|
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>>,
|
||||||
|
|
||||||
/// Map universe indexes to information on why we created it.
|
/// Map universe indexes to information on why we created it.
|
||||||
universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
|
universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
|
||||||
|
@ -259,7 +259,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
member_constraints_in: MemberConstraintSet<'tcx, RegionVid>,
|
member_constraints_in: MemberConstraintSet<'tcx, RegionVid>,
|
||||||
closure_bounds_mapping: FxHashMap<
|
closure_bounds_mapping: FxHashMap<
|
||||||
Location,
|
Location,
|
||||||
FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>,
|
FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>,
|
||||||
>,
|
>,
|
||||||
universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
|
universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
|
||||||
type_tests: Vec<TypeTest<'tcx>>,
|
type_tests: Vec<TypeTest<'tcx>>,
|
||||||
|
@ -1772,7 +1772,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
fr1: RegionVid,
|
fr1: RegionVid,
|
||||||
fr1_origin: NllRegionVariableOrigin,
|
fr1_origin: NllRegionVariableOrigin,
|
||||||
fr2: RegionVid,
|
fr2: RegionVid,
|
||||||
) -> (ConstraintCategory, ObligationCause<'tcx>) {
|
) -> (ConstraintCategory<'tcx>, ObligationCause<'tcx>) {
|
||||||
let BlameConstraint { category, cause, .. } =
|
let BlameConstraint { category, cause, .. } =
|
||||||
self.best_blame_constraint(body, fr1, fr1_origin, |r| {
|
self.best_blame_constraint(body, fr1, fr1_origin, |r| {
|
||||||
self.provides_universal_region(r, fr1, fr2)
|
self.provides_universal_region(r, fr1, fr2)
|
||||||
|
@ -2270,7 +2270,7 @@ impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct BlameConstraint<'tcx> {
|
pub struct BlameConstraint<'tcx> {
|
||||||
pub category: ConstraintCategory,
|
pub category: ConstraintCategory<'tcx>,
|
||||||
pub from_closure: bool,
|
pub from_closure: bool,
|
||||||
pub cause: ObligationCause<'tcx>,
|
pub cause: ObligationCause<'tcx>,
|
||||||
pub variance_info: ty::VarianceDiagInfo<'tcx>,
|
pub variance_info: ty::VarianceDiagInfo<'tcx>,
|
||||||
|
|
|
@ -28,7 +28,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
pub(super) fn fully_perform_op<R, Op>(
|
pub(super) fn fully_perform_op<R, Op>(
|
||||||
&mut self,
|
&mut self,
|
||||||
locations: Locations,
|
locations: Locations,
|
||||||
category: ConstraintCategory,
|
category: ConstraintCategory<'tcx>,
|
||||||
op: Op,
|
op: Op,
|
||||||
) -> Fallible<R>
|
) -> Fallible<R>
|
||||||
where
|
where
|
||||||
|
@ -83,11 +83,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
instantiated
|
instantiated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(self), level = "debug")]
|
||||||
pub(super) fn prove_trait_ref(
|
pub(super) fn prove_trait_ref(
|
||||||
&mut self,
|
&mut self,
|
||||||
trait_ref: ty::TraitRef<'tcx>,
|
trait_ref: ty::TraitRef<'tcx>,
|
||||||
locations: Locations,
|
locations: Locations,
|
||||||
category: ConstraintCategory,
|
category: ConstraintCategory<'tcx>,
|
||||||
) {
|
) {
|
||||||
self.prove_predicates(
|
self.prove_predicates(
|
||||||
Some(ty::Binder::dummy(ty::PredicateKind::Trait(ty::TraitPredicate {
|
Some(ty::Binder::dummy(ty::PredicateKind::Trait(ty::TraitPredicate {
|
||||||
|
@ -113,6 +114,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.zip(instantiated_predicates.spans.into_iter())
|
.zip(instantiated_predicates.spans.into_iter())
|
||||||
{
|
{
|
||||||
|
debug!(?predicate);
|
||||||
let predicate = self.normalize(predicate, locations);
|
let predicate = self.normalize(predicate, locations);
|
||||||
self.prove_predicate(predicate, locations, ConstraintCategory::Predicate(span));
|
self.prove_predicate(predicate, locations, ConstraintCategory::Predicate(span));
|
||||||
}
|
}
|
||||||
|
@ -122,7 +124,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
&mut self,
|
&mut self,
|
||||||
predicates: impl IntoIterator<Item = impl ToPredicate<'tcx>>,
|
predicates: impl IntoIterator<Item = impl ToPredicate<'tcx>>,
|
||||||
locations: Locations,
|
locations: Locations,
|
||||||
category: ConstraintCategory,
|
category: ConstraintCategory<'tcx>,
|
||||||
) {
|
) {
|
||||||
for predicate in predicates {
|
for predicate in predicates {
|
||||||
let predicate = predicate.to_predicate(self.tcx());
|
let predicate = predicate.to_predicate(self.tcx());
|
||||||
|
@ -137,7 +139,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
&mut self,
|
&mut self,
|
||||||
predicate: ty::Predicate<'tcx>,
|
predicate: ty::Predicate<'tcx>,
|
||||||
locations: Locations,
|
locations: Locations,
|
||||||
category: ConstraintCategory,
|
category: ConstraintCategory<'tcx>,
|
||||||
) {
|
) {
|
||||||
let param_env = self.param_env;
|
let param_env = self.param_env;
|
||||||
self.fully_perform_op(
|
self.fully_perform_op(
|
||||||
|
|
|
@ -27,7 +27,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> {
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
locations: Locations,
|
locations: Locations,
|
||||||
span: Span,
|
span: Span,
|
||||||
category: ConstraintCategory,
|
category: ConstraintCategory<'tcx>,
|
||||||
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
|
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
locations: Locations,
|
locations: Locations,
|
||||||
span: Span,
|
span: Span,
|
||||||
category: ConstraintCategory,
|
category: ConstraintCategory<'tcx>,
|
||||||
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
|
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
|
@ -162,6 +162,8 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
||||||
&mut constraints,
|
&mut constraints,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
debug!(?normalized_inputs_and_output);
|
||||||
|
|
||||||
for u in ty::UniverseIndex::ROOT..infcx.universe() {
|
for u in ty::UniverseIndex::ROOT..infcx.universe() {
|
||||||
let info = UniverseInfo::other();
|
let info = UniverseInfo::other();
|
||||||
constraints.universe_causes.insert(u, info);
|
constraints.universe_causes.insert(u, info);
|
||||||
|
@ -185,6 +187,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
||||||
implicit_region_bound,
|
implicit_region_bound,
|
||||||
&mut borrowck_context,
|
&mut borrowck_context,
|
||||||
|mut cx| {
|
|mut cx| {
|
||||||
|
debug!("inside extra closure of type_check_internal");
|
||||||
cx.equate_inputs_and_outputs(&body, universal_regions, &normalized_inputs_and_output);
|
cx.equate_inputs_and_outputs(&body, universal_regions, &normalized_inputs_and_output);
|
||||||
liveness::generate(
|
liveness::generate(
|
||||||
&mut cx,
|
&mut cx,
|
||||||
|
@ -257,6 +260,7 @@ fn type_check_internal<'a, 'tcx, R>(
|
||||||
borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
|
borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
|
||||||
extra: impl FnOnce(TypeChecker<'a, 'tcx>) -> R,
|
extra: impl FnOnce(TypeChecker<'a, 'tcx>) -> R,
|
||||||
) -> R {
|
) -> R {
|
||||||
|
debug!("body: {:#?}", body);
|
||||||
let mut checker = TypeChecker::new(
|
let mut checker = TypeChecker::new(
|
||||||
infcx,
|
infcx,
|
||||||
body,
|
body,
|
||||||
|
@ -935,7 +939,7 @@ pub(crate) struct MirTypeckRegionConstraints<'tcx> {
|
||||||
pub(crate) member_constraints: MemberConstraintSet<'tcx, RegionVid>,
|
pub(crate) member_constraints: MemberConstraintSet<'tcx, RegionVid>,
|
||||||
|
|
||||||
pub(crate) closure_bounds_mapping:
|
pub(crate) closure_bounds_mapping:
|
||||||
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>,
|
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>>,
|
||||||
|
|
||||||
pub(crate) universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
|
pub(crate) universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
|
||||||
|
|
||||||
|
@ -1125,7 +1129,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
fn push_region_constraints(
|
fn push_region_constraints(
|
||||||
&mut self,
|
&mut self,
|
||||||
locations: Locations,
|
locations: Locations,
|
||||||
category: ConstraintCategory,
|
category: ConstraintCategory<'tcx>,
|
||||||
data: &QueryRegionConstraints<'tcx>,
|
data: &QueryRegionConstraints<'tcx>,
|
||||||
) {
|
) {
|
||||||
debug!("constraints generated: {:#?}", data);
|
debug!("constraints generated: {:#?}", data);
|
||||||
|
@ -1150,7 +1154,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
sub: Ty<'tcx>,
|
sub: Ty<'tcx>,
|
||||||
sup: Ty<'tcx>,
|
sup: Ty<'tcx>,
|
||||||
locations: Locations,
|
locations: Locations,
|
||||||
category: ConstraintCategory,
|
category: ConstraintCategory<'tcx>,
|
||||||
) -> Fallible<()> {
|
) -> Fallible<()> {
|
||||||
// Use this order of parameters because the sup type is usually the
|
// Use this order of parameters because the sup type is usually the
|
||||||
// "expected" type in diagnostics.
|
// "expected" type in diagnostics.
|
||||||
|
@ -1163,7 +1167,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
expected: Ty<'tcx>,
|
expected: Ty<'tcx>,
|
||||||
found: Ty<'tcx>,
|
found: Ty<'tcx>,
|
||||||
locations: Locations,
|
locations: Locations,
|
||||||
category: ConstraintCategory,
|
category: ConstraintCategory<'tcx>,
|
||||||
) -> Fallible<()> {
|
) -> Fallible<()> {
|
||||||
self.relate_types(expected, ty::Variance::Invariant, found, locations, category)
|
self.relate_types(expected, ty::Variance::Invariant, found, locations, category)
|
||||||
}
|
}
|
||||||
|
@ -1175,7 +1179,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
v: ty::Variance,
|
v: ty::Variance,
|
||||||
user_ty: &UserTypeProjection,
|
user_ty: &UserTypeProjection,
|
||||||
locations: Locations,
|
locations: Locations,
|
||||||
category: ConstraintCategory,
|
category: ConstraintCategory<'tcx>,
|
||||||
) -> Fallible<()> {
|
) -> Fallible<()> {
|
||||||
let annotated_type = self.user_type_annotations[user_ty.base].inferred_ty;
|
let annotated_type = self.user_type_annotations[user_ty.base].inferred_ty;
|
||||||
let mut curr_projected_ty = PlaceTy::from_ty(annotated_type);
|
let mut curr_projected_ty = PlaceTy::from_ty(annotated_type);
|
||||||
|
@ -1212,6 +1216,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
#[instrument(skip(self, body, location), level = "debug")]
|
#[instrument(skip(self, body, location), level = "debug")]
|
||||||
fn check_stmt(&mut self, body: &Body<'tcx>, stmt: &Statement<'tcx>, location: Location) {
|
fn check_stmt(&mut self, body: &Body<'tcx>, stmt: &Statement<'tcx>, location: Location) {
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
|
debug!("stmt kind: {:?}", stmt.kind);
|
||||||
match stmt.kind {
|
match stmt.kind {
|
||||||
StatementKind::Assign(box (ref place, ref rv)) => {
|
StatementKind::Assign(box (ref place, ref rv)) => {
|
||||||
// Assignments to temporaries are not "interesting";
|
// Assignments to temporaries are not "interesting";
|
||||||
|
@ -1251,9 +1256,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
|
|
||||||
let place_ty = place.ty(body, tcx).ty;
|
let place_ty = place.ty(body, tcx).ty;
|
||||||
|
debug!(?place_ty);
|
||||||
let place_ty = self.normalize(place_ty, location);
|
let place_ty = self.normalize(place_ty, location);
|
||||||
|
debug!("place_ty normalized: {:?}", place_ty);
|
||||||
let rv_ty = rv.ty(body, tcx);
|
let rv_ty = rv.ty(body, tcx);
|
||||||
|
debug!(?rv_ty);
|
||||||
let rv_ty = self.normalize(rv_ty, location);
|
let rv_ty = self.normalize(rv_ty, location);
|
||||||
|
debug!("normalized rv_ty: {:?}", rv_ty);
|
||||||
if let Err(terr) =
|
if let Err(terr) =
|
||||||
self.sub_types(rv_ty, place_ty, location.to_locations(), category)
|
self.sub_types(rv_ty, place_ty, location.to_locations(), category)
|
||||||
{
|
{
|
||||||
|
@ -1347,6 +1356,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
term_location: Location,
|
term_location: Location,
|
||||||
) {
|
) {
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
|
debug!("terminator kind: {:?}", term.kind);
|
||||||
match term.kind {
|
match term.kind {
|
||||||
TerminatorKind::Goto { .. }
|
TerminatorKind::Goto { .. }
|
||||||
| TerminatorKind::Resume
|
| TerminatorKind::Resume
|
||||||
|
@ -1404,7 +1414,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
// FIXME: check the values
|
// FIXME: check the values
|
||||||
}
|
}
|
||||||
TerminatorKind::Call {
|
TerminatorKind::Call {
|
||||||
ref func, ref args, destination, target, from_hir_call, ..
|
ref func,
|
||||||
|
ref args,
|
||||||
|
ref destination,
|
||||||
|
from_hir_call,
|
||||||
|
target,
|
||||||
|
..
|
||||||
} => {
|
} => {
|
||||||
self.check_operand(func, term_location);
|
self.check_operand(func, term_location);
|
||||||
for arg in args {
|
for arg in args {
|
||||||
|
@ -1412,7 +1427,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let func_ty = func.ty(body, tcx);
|
let func_ty = func.ty(body, tcx);
|
||||||
debug!("check_terminator: call, func_ty={:?}", func_ty);
|
debug!("func_ty.kind: {:?}", func_ty.kind());
|
||||||
|
|
||||||
let sig = match func_ty.kind() {
|
let sig = match func_ty.kind() {
|
||||||
ty::FnDef(..) | ty::FnPtr(_) => func_ty.fn_sig(tcx),
|
ty::FnDef(..) | ty::FnPtr(_) => func_ty.fn_sig(tcx),
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -1425,8 +1441,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
LateBoundRegionConversionTime::FnCall,
|
LateBoundRegionConversionTime::FnCall,
|
||||||
sig,
|
sig,
|
||||||
);
|
);
|
||||||
|
debug!(?sig);
|
||||||
let sig = self.normalize(sig, term_location);
|
let sig = self.normalize(sig, term_location);
|
||||||
self.check_call_dest(body, term, &sig, destination, target, term_location);
|
self.check_call_dest(body, term, &sig, *destination, target, term_location);
|
||||||
|
|
||||||
self.prove_predicates(
|
self.prove_predicates(
|
||||||
sig.inputs_and_output
|
sig.inputs_and_output
|
||||||
|
@ -1585,11 +1602,20 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
if args.len() < sig.inputs().len() || (args.len() > sig.inputs().len() && !sig.c_variadic) {
|
if args.len() < sig.inputs().len() || (args.len() > sig.inputs().len() && !sig.c_variadic) {
|
||||||
span_mirbug!(self, term, "call to {:?} with wrong # of args", sig);
|
span_mirbug!(self, term, "call to {:?} with wrong # of args", sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let func_ty = if let TerminatorKind::Call { func, .. } = &term.kind {
|
||||||
|
Some(func.ty(body, self.infcx.tcx))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
debug!(?func_ty);
|
||||||
|
|
||||||
for (n, (fn_arg, op_arg)) in iter::zip(sig.inputs(), args).enumerate() {
|
for (n, (fn_arg, op_arg)) in iter::zip(sig.inputs(), args).enumerate() {
|
||||||
let op_arg_ty = op_arg.ty(body, self.tcx());
|
let op_arg_ty = op_arg.ty(body, self.tcx());
|
||||||
|
|
||||||
let op_arg_ty = self.normalize(op_arg_ty, term_location);
|
let op_arg_ty = self.normalize(op_arg_ty, term_location);
|
||||||
let category = if from_hir_call {
|
let category = if from_hir_call {
|
||||||
ConstraintCategory::CallArgument
|
ConstraintCategory::CallArgument(func_ty)
|
||||||
} else {
|
} else {
|
||||||
ConstraintCategory::Boring
|
ConstraintCategory::Boring
|
||||||
};
|
};
|
||||||
|
@ -1841,6 +1867,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(self, body), level = "debug")]
|
||||||
fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) {
|
fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) {
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
v: ty::Variance,
|
v: ty::Variance,
|
||||||
b: Ty<'tcx>,
|
b: Ty<'tcx>,
|
||||||
locations: Locations,
|
locations: Locations,
|
||||||
category: ConstraintCategory,
|
category: ConstraintCategory<'tcx>,
|
||||||
) -> Fallible<()> {
|
) -> Fallible<()> {
|
||||||
TypeRelating::new(
|
TypeRelating::new(
|
||||||
self.infcx,
|
self.infcx,
|
||||||
|
@ -47,7 +47,7 @@ struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
|
||||||
locations: Locations,
|
locations: Locations,
|
||||||
|
|
||||||
/// What category do we assign the resulting `'a: 'b` relationships?
|
/// What category do we assign the resulting `'a: 'b` relationships?
|
||||||
category: ConstraintCategory,
|
category: ConstraintCategory<'tcx>,
|
||||||
|
|
||||||
/// Information so that error reporting knows what types we are relating
|
/// Information so that error reporting knows what types we are relating
|
||||||
/// when reporting a bound region error.
|
/// when reporting a bound region error.
|
||||||
|
@ -58,7 +58,7 @@ impl<'me, 'bccx, 'tcx> NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
|
||||||
fn new(
|
fn new(
|
||||||
type_checker: &'me mut TypeChecker<'bccx, 'tcx>,
|
type_checker: &'me mut TypeChecker<'bccx, 'tcx>,
|
||||||
locations: Locations,
|
locations: Locations,
|
||||||
category: ConstraintCategory,
|
category: ConstraintCategory<'tcx>,
|
||||||
universe_info: UniverseInfo<'tcx>,
|
universe_info: UniverseInfo<'tcx>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self { type_checker, locations, category, universe_info }
|
Self { type_checker, locations, category, universe_info }
|
||||||
|
|
|
@ -16,7 +16,7 @@ mod util;
|
||||||
|
|
||||||
pub use different_lifetimes::suggest_adding_lifetime_params;
|
pub use different_lifetimes::suggest_adding_lifetime_params;
|
||||||
pub use find_anon_type::find_anon_type;
|
pub use find_anon_type::find_anon_type;
|
||||||
pub use static_impl_trait::suggest_new_region_bound;
|
pub use static_impl_trait::{suggest_new_region_bound, HirTraitObjectVisitor, TraitObjectVisitor};
|
||||||
pub use util::find_param_with_region;
|
pub use util::find_param_with_region;
|
||||||
|
|
||||||
impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
|
impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
|
||||||
|
|
|
@ -546,7 +546,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Collect all the trait objects in a type that could have received an implicit `'static` lifetime.
|
/// Collect all the trait objects in a type that could have received an implicit `'static` lifetime.
|
||||||
pub(super) struct TraitObjectVisitor(pub(super) FxHashSet<DefId>);
|
pub struct TraitObjectVisitor(pub FxHashSet<DefId>);
|
||||||
|
|
||||||
impl<'tcx> TypeVisitor<'tcx> for TraitObjectVisitor {
|
impl<'tcx> TypeVisitor<'tcx> for TraitObjectVisitor {
|
||||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||||
|
@ -563,7 +563,7 @@ impl<'tcx> TypeVisitor<'tcx> for TraitObjectVisitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Collect all `hir::Ty<'_>` `Span`s for trait objects with an implicit lifetime.
|
/// Collect all `hir::Ty<'_>` `Span`s for trait objects with an implicit lifetime.
|
||||||
pub(super) struct HirTraitObjectVisitor<'a>(pub(super) &'a mut Vec<Span>, pub(super) DefId);
|
pub struct HirTraitObjectVisitor<'a>(pub &'a mut Vec<Span>, pub DefId);
|
||||||
|
|
||||||
impl<'a, 'tcx> Visitor<'tcx> for HirTraitObjectVisitor<'a> {
|
impl<'a, 'tcx> Visitor<'tcx> for HirTraitObjectVisitor<'a> {
|
||||||
fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) {
|
fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) {
|
||||||
|
|
|
@ -34,6 +34,7 @@ pub struct AnonymousParamInfo<'tcx> {
|
||||||
// i32, which is the type of y but with the anonymous region replaced
|
// i32, which is the type of y but with the anonymous region replaced
|
||||||
// with 'a, the corresponding bound region and is_first which is true if
|
// with 'a, the corresponding bound region and is_first which is true if
|
||||||
// the hir::Param is the first parameter in the function declaration.
|
// the hir::Param is the first parameter in the function declaration.
|
||||||
|
#[instrument(skip(tcx), level = "debug")]
|
||||||
pub fn find_param_with_region<'tcx>(
|
pub fn find_param_with_region<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
anon_region: Region<'tcx>,
|
anon_region: Region<'tcx>,
|
||||||
|
@ -51,9 +52,19 @@ pub fn find_param_with_region<'tcx>(
|
||||||
let hir_id = hir.local_def_id_to_hir_id(id.as_local()?);
|
let hir_id = hir.local_def_id_to_hir_id(id.as_local()?);
|
||||||
let body_id = hir.maybe_body_owned_by(hir_id)?;
|
let body_id = hir.maybe_body_owned_by(hir_id)?;
|
||||||
let body = hir.body(body_id);
|
let body = hir.body(body_id);
|
||||||
|
|
||||||
|
// Don't perform this on closures
|
||||||
|
match hir.get(hir_id) {
|
||||||
|
hir::Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
let owner_id = hir.body_owner(body_id);
|
let owner_id = hir.body_owner(body_id);
|
||||||
let fn_decl = hir.fn_decl_by_hir_id(owner_id).unwrap();
|
let fn_decl = hir.fn_decl_by_hir_id(owner_id).unwrap();
|
||||||
let poly_fn_sig = tcx.fn_sig(id);
|
let poly_fn_sig = tcx.fn_sig(id);
|
||||||
|
|
||||||
let fn_sig = tcx.liberate_late_bound_regions(id, poly_fn_sig);
|
let fn_sig = tcx.liberate_late_bound_regions(id, poly_fn_sig);
|
||||||
body.params
|
body.params
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
@ -338,11 +338,12 @@ pub struct ClosureOutlivesRequirement<'tcx> {
|
||||||
pub blame_span: Span,
|
pub blame_span: Span,
|
||||||
|
|
||||||
// ... due to this reason.
|
// ... due to this reason.
|
||||||
pub category: ConstraintCategory,
|
pub category: ConstraintCategory<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure this enum doesn't unintentionally grow
|
// Make sure this enum doesn't unintentionally grow
|
||||||
rustc_data_structures::static_assert_size!(ConstraintCategory, 12);
|
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
||||||
|
rustc_data_structures::static_assert_size!(ConstraintCategory<'_>, 16);
|
||||||
|
|
||||||
/// Outlives-constraints can be categorized to determine whether and why they
|
/// Outlives-constraints can be categorized to determine whether and why they
|
||||||
/// are interesting (for error reporting). Order of variants indicates sort
|
/// are interesting (for error reporting). Order of variants indicates sort
|
||||||
|
@ -351,7 +352,7 @@ rustc_data_structures::static_assert_size!(ConstraintCategory, 12);
|
||||||
/// See also `rustc_const_eval::borrow_check::constraints`.
|
/// See also `rustc_const_eval::borrow_check::constraints`.
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
|
||||||
#[derive(TyEncodable, TyDecodable, HashStable)]
|
#[derive(TyEncodable, TyDecodable, HashStable)]
|
||||||
pub enum ConstraintCategory {
|
pub enum ConstraintCategory<'tcx> {
|
||||||
Return(ReturnConstraint),
|
Return(ReturnConstraint),
|
||||||
Yield,
|
Yield,
|
||||||
UseAsConst,
|
UseAsConst,
|
||||||
|
@ -363,7 +364,9 @@ pub enum ConstraintCategory {
|
||||||
///
|
///
|
||||||
/// We try to get the category that the closure used when reporting this.
|
/// We try to get the category that the closure used when reporting this.
|
||||||
ClosureBounds,
|
ClosureBounds,
|
||||||
CallArgument,
|
|
||||||
|
/// Contains the function type if available.
|
||||||
|
CallArgument(Option<Ty<'tcx>>),
|
||||||
CopyBound,
|
CopyBound,
|
||||||
SizedBound,
|
SizedBound,
|
||||||
Assignment,
|
Assignment,
|
||||||
|
|
|
@ -135,8 +135,8 @@ impl<'a> HashStable<StableHashingContext<'a>> for ty::RegionKind {
|
||||||
ty::RePlaceholder(p) => {
|
ty::RePlaceholder(p) => {
|
||||||
p.hash_stable(hcx, hasher);
|
p.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
ty::ReVar(..) => {
|
ty::ReVar(reg) => {
|
||||||
bug!("StableHasher: unexpected region {:?}", *self)
|
reg.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: lifetime may not live long enough
|
error: lifetime may not live long enough
|
||||||
--> $DIR/project-fn-ret-invariant-nll.rs:63:5
|
--> $DIR/project-fn-ret-invariant-nll.rs:64:5
|
||||||
|
|
|
|
||||||
LL | fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
LL | fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
||||||
| -- -- lifetime `'b` defined here
|
| -- -- lifetime `'b` defined here
|
||||||
|
@ -15,7 +15,7 @@ LL | (a, b)
|
||||||
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
|
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
|
||||||
|
|
||||||
error: lifetime may not live long enough
|
error: lifetime may not live long enough
|
||||||
--> $DIR/project-fn-ret-invariant-nll.rs:63:5
|
--> $DIR/project-fn-ret-invariant-nll.rs:64:5
|
||||||
|
|
|
|
||||||
LL | fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
LL | fn transmute<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
||||||
| -- -- lifetime `'b` defined here
|
| -- -- lifetime `'b` defined here
|
||||||
|
|
|
@ -15,19 +15,19 @@ LL | let a = bar(f, x);
|
||||||
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
|
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
|
||||||
|
|
||||||
error: lifetime may not live long enough
|
error: lifetime may not live long enough
|
||||||
--> $DIR/project-fn-ret-invariant-nll.rs:47:13
|
--> $DIR/project-fn-ret-invariant-nll.rs:46:13
|
||||||
|
|
|
|
||||||
LL | fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
LL | fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
||||||
| -- -- lifetime `'b` defined here
|
| -- -- lifetime `'b` defined here
|
||||||
| |
|
| |
|
||||||
| lifetime `'a` defined here
|
| lifetime `'a` defined here
|
||||||
...
|
LL | let f = foo; // <-- No consistent type can be inferred for `f` here.
|
||||||
LL | let b = bar(f, y);
|
LL | let a = bar(f, x);
|
||||||
| ^^^^^^^^^ argument requires that `'b` must outlive `'a`
|
| ^^^^^^^^^ argument requires that `'b` must outlive `'a`
|
||||||
|
|
|
|
||||||
= help: consider adding the following bound: `'b: 'a`
|
= help: consider adding the following bound: `'b: 'a`
|
||||||
= note: requirement occurs because of the type `Type<'_>`, which makes the generic argument `'_` invariant
|
= note: requirement occurs because of a function pointer to `foo`
|
||||||
= note: the struct `Type<'a>` is invariant over the parameter `'a`
|
= note: the function `foo` is invariant over the parameter `'a`
|
||||||
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
|
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
|
||||||
|
|
||||||
help: `'a` and `'b` must be the same: replace one with the other
|
help: `'a` and `'b` must be the same: replace one with the other
|
||||||
|
|
|
@ -44,7 +44,8 @@ fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
||||||
fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
|
||||||
let f = foo; // <-- No consistent type can be inferred for `f` here.
|
let f = foo; // <-- No consistent type can be inferred for `f` here.
|
||||||
let a = bar(f, x); //[oneuse]~ ERROR lifetime may not live long enough
|
let a = bar(f, x); //[oneuse]~ ERROR lifetime may not live long enough
|
||||||
let b = bar(f, y); //[oneuse]~ ERROR lifetime may not live long enough
|
//[oneuse]~^ ERROR lifetime may not live long enough
|
||||||
|
let b = bar(f, y);
|
||||||
(a, b)
|
(a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: lifetime may not live long enough
|
error: lifetime may not live long enough
|
||||||
--> $DIR/project-fn-ret-invariant-nll.rs:56:5
|
--> $DIR/project-fn-ret-invariant-nll.rs:57:5
|
||||||
|
|
|
|
||||||
LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> {
|
LL | fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> {
|
||||||
| -- lifetime `'a` defined here
|
| -- lifetime `'a` defined here
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0521]: borrowed data escapes outside of associated function
|
error[E0521]: borrowed data escapes outside of associated function
|
||||||
--> $DIR/issue-72312.rs:20:24
|
--> $DIR/issue-72312.rs:20:9
|
||||||
|
|
|
|
||||||
LL | pub async fn start(&self) {
|
LL | pub async fn start(&self) {
|
||||||
| -----
|
| -----
|
||||||
|
@ -7,18 +7,17 @@ LL | pub async fn start(&self) {
|
||||||
| `self` is a reference that is only valid in the associated function body
|
| `self` is a reference that is only valid in the associated function body
|
||||||
| let's call the lifetime of this reference `'1`
|
| let's call the lifetime of this reference `'1`
|
||||||
...
|
...
|
||||||
LL | require_static(async move {
|
LL | / require_static(async move {
|
||||||
| ________________________^
|
|
||||||
LL | |
|
LL | |
|
||||||
LL | |
|
LL | |
|
||||||
LL | |
|
LL | |
|
||||||
LL | |
|
LL | |
|
||||||
LL | | &self;
|
LL | | &self;
|
||||||
LL | | });
|
LL | | });
|
||||||
| | ^
|
| | ^
|
||||||
| | |
|
| | |
|
||||||
| |_________`self` escapes the associated function body here
|
| |__________`self` escapes the associated function body here
|
||||||
| argument requires that `'1` must outlive `'static`
|
| argument requires that `'1` must outlive `'static`
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -72,14 +72,15 @@ LL | | }
|
||||||
error[E0597]: `a` does not live long enough
|
error[E0597]: `a` does not live long enough
|
||||||
--> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:30:26
|
--> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:30:26
|
||||||
|
|
|
|
||||||
LL | let cell = Cell::new(&a);
|
LL | let cell = Cell::new(&a);
|
||||||
| ----------^^-
|
| ^^ borrowed value does not live long enough
|
||||||
| | |
|
|
||||||
| | borrowed value does not live long enough
|
|
||||||
| argument requires that `a` is borrowed for `'static`
|
|
||||||
...
|
...
|
||||||
LL | }
|
LL | / foo(cell, |cell_a, cell_x| {
|
||||||
| - `a` dropped here while still borrowed
|
LL | | cell_x.set(cell_a.get()); // forces 'a: 'x, implies 'a = 'static -> borrow error
|
||||||
|
LL | | })
|
||||||
|
| |______- argument requires that `a` is borrowed for `'static`
|
||||||
|
LL | }
|
||||||
|
| - `a` dropped here while still borrowed
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
error[E0597]: `c` does not live long enough
|
error[E0597]: `c` does not live long enough
|
||||||
--> $DIR/adt-nullary-enums.rs:33:41
|
--> $DIR/adt-nullary-enums.rs:33:41
|
||||||
|
|
|
|
||||||
LL | SomeEnum::SomeVariant(Cell::new(&c)),
|
LL | / combine(
|
||||||
| ----------^^-
|
LL | | SomeEnum::SomeVariant(Cell::new(&c)),
|
||||||
| | |
|
| | ^^ borrowed value does not live long enough
|
||||||
| | borrowed value does not live long enough
|
LL | | SomeEnum::SomeOtherVariant::<Cell<&'static u32>>,
|
||||||
| argument requires that `c` is borrowed for `'static`
|
LL | | );
|
||||||
...
|
| |_____- argument requires that `c` is borrowed for `'static`
|
||||||
LL | }
|
LL | }
|
||||||
| - `c` dropped here while still borrowed
|
| - `c` dropped here while still borrowed
|
||||||
|
|
||||||
error[E0597]: `c` does not live long enough
|
error[E0597]: `c` does not live long enough
|
||||||
--> $DIR/adt-nullary-enums.rs:41:41
|
--> $DIR/adt-nullary-enums.rs:41:41
|
||||||
|
|
|
@ -10,6 +10,18 @@ LL | val.use_self::<T>()
|
||||||
| |
|
| |
|
||||||
| `val` escapes the function body here
|
| `val` escapes the function body here
|
||||||
| argument requires that `'a` must outlive `'static`
|
| argument requires that `'a` must outlive `'static`
|
||||||
|
|
|
||||||
|
note: the used `impl` has a `'static` requirement
|
||||||
|
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound-nll.rs:19:32
|
||||||
|
|
|
||||||
|
LL | impl<T> MyTrait<T> for dyn ObjectTrait<T> {
|
||||||
|
| ^^^^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
|
||||||
|
LL | fn use_self<K>(&self) -> &() { panic!() }
|
||||||
|
| -------- calling this method introduces the `impl`'s 'static` requirement
|
||||||
|
help: consider relaxing the implicit `'static` requirement
|
||||||
|
|
|
||||||
|
LL | impl<T> MyTrait<T> for dyn ObjectTrait<T> + '_ {
|
||||||
|
| ++++
|
||||||
|
|
||||||
error[E0521]: borrowed data escapes outside of function
|
error[E0521]: borrowed data escapes outside of function
|
||||||
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound-nll.rs:74:9
|
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound-nll.rs:74:9
|
||||||
|
@ -23,6 +35,18 @@ LL | val.use_self()
|
||||||
| |
|
| |
|
||||||
| `val` escapes the function body here
|
| `val` escapes the function body here
|
||||||
| argument requires that `'a` must outlive `'static`
|
| argument requires that `'a` must outlive `'static`
|
||||||
|
|
|
||||||
|
note: the used `impl` has a `'static` requirement
|
||||||
|
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound-nll.rs:69:14
|
||||||
|
|
|
||||||
|
LL | impl dyn ObjectTrait {
|
||||||
|
| ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
|
||||||
|
LL | fn use_self(&self) -> &() { panic!() }
|
||||||
|
| -------- calling this method introduces the `impl`'s 'static` requirement
|
||||||
|
help: consider relaxing the implicit `'static` requirement
|
||||||
|
|
|
||||||
|
LL | impl dyn ObjectTrait + '_ {
|
||||||
|
| ++++
|
||||||
|
|
||||||
error[E0521]: borrowed data escapes outside of function
|
error[E0521]: borrowed data escapes outside of function
|
||||||
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound-nll.rs:94:9
|
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound-nll.rs:94:9
|
||||||
|
@ -36,6 +60,19 @@ LL | val.use_self()
|
||||||
| |
|
| |
|
||||||
| `val` escapes the function body here
|
| `val` escapes the function body here
|
||||||
| argument requires that `'a` must outlive `'static`
|
| argument requires that `'a` must outlive `'static`
|
||||||
|
|
|
||||||
|
note: the used `impl` has a `'static` requirement
|
||||||
|
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound-nll.rs:91:26
|
||||||
|
|
|
||||||
|
LL | fn use_self(&self) -> &() { panic!() }
|
||||||
|
| -------- calling this method introduces the `impl`'s 'static` requirement
|
||||||
|
...
|
||||||
|
LL | impl MyTrait for dyn ObjectTrait {}
|
||||||
|
| ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
|
||||||
|
help: consider relaxing the implicit `'static` requirement
|
||||||
|
|
|
||||||
|
LL | impl MyTrait for dyn ObjectTrait + '_ {}
|
||||||
|
| ++++
|
||||||
|
|
||||||
error[E0521]: borrowed data escapes outside of function
|
error[E0521]: borrowed data escapes outside of function
|
||||||
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound-nll.rs:114:9
|
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound-nll.rs:114:9
|
||||||
|
@ -49,6 +86,19 @@ LL | MyTrait::use_self(val)
|
||||||
| |
|
| |
|
||||||
| `val` escapes the function body here
|
| `val` escapes the function body here
|
||||||
| argument requires that `'a` must outlive `'static`
|
| argument requires that `'a` must outlive `'static`
|
||||||
|
|
|
||||||
|
note: the used `impl` has a `'static` requirement
|
||||||
|
--> $DIR/impl-on-dyn-trait-with-implicit-static-bound-nll.rs:110:26
|
||||||
|
|
|
||||||
|
LL | fn use_self(&self) -> &() { panic!() }
|
||||||
|
| -------- calling this method introduces the `impl`'s 'static` requirement
|
||||||
|
...
|
||||||
|
LL | impl MyTrait for dyn ObjectTrait {}
|
||||||
|
| ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
|
||||||
|
help: consider relaxing the implicit `'static` requirement
|
||||||
|
|
|
||||||
|
LL | impl MyTrait for dyn ObjectTrait + '_ {}
|
||||||
|
| ++++
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue