Rollup merge of #101936 - IntQuant:issue-100717-infer-4, r=compiler-errors
Migrating rustc_infer to session diagnostics (part 3) ``@rustbot`` label +A-translation r? rust-lang/diagnostics cc https://github.com/rust-lang/rust/issues/100717 Seems like a part of static_impl_trait.rs emits suggestions in a loop, and note.rs needs to have two instances of the same subdiagnostic, so these will need to wait until we have eager translation/list support. Other than that, there is only error_reporting/mod.rs left to migrate.
This commit is contained in:
commit
405e48f1ac
7 changed files with 815 additions and 331 deletions
|
@ -172,3 +172,142 @@ infer_msl_unmet_req = because this has an unmet lifetime requirement
|
||||||
infer_msl_trait_note = this has an implicit `'static` lifetime requirement
|
infer_msl_trait_note = this has an implicit `'static` lifetime requirement
|
||||||
infer_msl_trait_sugg = consider relaxing the implicit `'static` requirement
|
infer_msl_trait_sugg = consider relaxing the implicit `'static` requirement
|
||||||
infer_suggest_add_let_for_letchains = consider adding `let`
|
infer_suggest_add_let_for_letchains = consider adding `let`
|
||||||
|
|
||||||
|
infer_explicit_lifetime_required_with_ident = explicit lifetime required in the type of `{$simple_ident}`
|
||||||
|
.label = lifetime `{$named}` required
|
||||||
|
|
||||||
|
infer_explicit_lifetime_required_with_param_type = explicit lifetime required in parameter type
|
||||||
|
.label = lifetime `{$named}` required
|
||||||
|
|
||||||
|
infer_explicit_lifetime_required_sugg_with_ident = add explicit lifetime `{$named}` to the type of `{$simple_ident}`
|
||||||
|
|
||||||
|
infer_explicit_lifetime_required_sugg_with_param_type = add explicit lifetime `{$named}` to type
|
||||||
|
|
||||||
|
infer_actual_impl_expl_expected_signature_two = {$leading_ellipsis ->
|
||||||
|
[true] ...
|
||||||
|
*[false] {""}
|
||||||
|
}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
|
||||||
|
infer_actual_impl_expl_expected_signature_any = {$leading_ellipsis ->
|
||||||
|
[true] ...
|
||||||
|
*[false] {""}
|
||||||
|
}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...
|
||||||
|
infer_actual_impl_expl_expected_signature_some = {$leading_ellipsis ->
|
||||||
|
[true] ...
|
||||||
|
*[false] {""}
|
||||||
|
}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{lifetime_1}`...
|
||||||
|
infer_actual_impl_expl_expected_signature_nothing = {$leading_ellipsis ->
|
||||||
|
[true] ...
|
||||||
|
*[false] {""}
|
||||||
|
}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`
|
||||||
|
infer_actual_impl_expl_expected_passive_two = {$leading_ellipsis ->
|
||||||
|
[true] ...
|
||||||
|
*[false] {""}
|
||||||
|
}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
|
||||||
|
infer_actual_impl_expl_expected_passive_any = {$leading_ellipsis ->
|
||||||
|
[true] ...
|
||||||
|
*[false] {""}
|
||||||
|
}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any lifetime `'{$lifetime_1}`...
|
||||||
|
infer_actual_impl_expl_expected_passive_some = {$leading_ellipsis ->
|
||||||
|
[true] ...
|
||||||
|
*[false] {""}
|
||||||
|
}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for some specific lifetime `'{lifetime_1}`...
|
||||||
|
infer_actual_impl_expl_expected_passive_nothing = {$leading_ellipsis ->
|
||||||
|
[true] ...
|
||||||
|
*[false] {""}
|
||||||
|
}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`
|
||||||
|
infer_actual_impl_expl_expected_other_two = {$leading_ellipsis ->
|
||||||
|
[true] ...
|
||||||
|
*[false] {""}
|
||||||
|
}`{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...
|
||||||
|
infer_actual_impl_expl_expected_other_any = {$leading_ellipsis ->
|
||||||
|
[true] ...
|
||||||
|
*[false] {""}
|
||||||
|
}`{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...
|
||||||
|
infer_actual_impl_expl_expected_other_some = {$leading_ellipsis ->
|
||||||
|
[true] ...
|
||||||
|
*[false] {""}
|
||||||
|
}`{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{lifetime_1}`...
|
||||||
|
infer_actual_impl_expl_expected_other_nothing = {$leading_ellipsis ->
|
||||||
|
[true] ...
|
||||||
|
*[false] {""}
|
||||||
|
}`{$ty_or_sig}` must implement `{$trait_path}`
|
||||||
|
|
||||||
|
infer_actual_impl_expl_but_actually_implements_trait = ...but it actually implements `{$trait_path}`{$has_lifetime ->
|
||||||
|
[true] , for some specific lifetime `'{$lifetime}`
|
||||||
|
*[false] {""}
|
||||||
|
}
|
||||||
|
infer_actual_impl_expl_but_actually_implemented_for_ty = ...but `{$trait_path}` is actually implemented for the type `{$ty}`{$has_lifetime ->
|
||||||
|
[true] , for some specific lifetime `'{$lifetime}`
|
||||||
|
*[false] {""}
|
||||||
|
}
|
||||||
|
infer_actual_impl_expl_but_actually_ty_implements = ...but `{$ty}` actually implements `{$trait_path}`{$has_lifetime ->
|
||||||
|
[true] , for some specific lifetime `'{$lifetime}`
|
||||||
|
*[false] {""}
|
||||||
|
}
|
||||||
|
|
||||||
|
infer_trait_placeholder_mismatch = implementation of `{$trait_def_id}` is not general enough
|
||||||
|
.label_satisfy = doesn't satisfy where-clause
|
||||||
|
.label_where = due to a where-clause on `{$def_id}`...
|
||||||
|
.label_dup = implementation of `{$trait_def_id}` is not general enough
|
||||||
|
|
||||||
|
infer_trait_impl_diff = `impl` item signature doesn't match `trait` item signature
|
||||||
|
.found = found `{$found}`
|
||||||
|
.expected = expected `{$expected}`
|
||||||
|
.expected_found = expected `{$expected}`
|
||||||
|
{" "}found `{$found}`
|
||||||
|
|
||||||
|
infer_tid_rel_help = verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output
|
||||||
|
infer_tid_consider_borrowing = consider borrowing this type parameter in the trait
|
||||||
|
infer_tid_param_help = the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
|
||||||
|
|
||||||
|
infer_dtcs_has_lifetime_req_label = this has an implicit `'static` lifetime requirement
|
||||||
|
infer_dtcs_introduces_requirement = calling this method introduces the `impl`'s 'static` requirement
|
||||||
|
infer_dtcs_has_req_note = the used `impl` has a `'static` requirement
|
||||||
|
infer_dtcs_suggestion = consider relaxing the implicit `'static` requirement
|
||||||
|
|
||||||
|
infer_but_calling_introduces = {$has_param_name ->
|
||||||
|
[true] `{$param_name}`
|
||||||
|
*[false] `fn` parameter
|
||||||
|
} has {$lifetime_kind ->
|
||||||
|
[named] lifetime `{lifetime}`
|
||||||
|
*[anon] an anonymous lifetime `'_`
|
||||||
|
} but calling `{assoc_item}` introduces an implicit `'static` lifetime requirement
|
||||||
|
.label1 = {$has_lifetime ->
|
||||||
|
[named] lifetime `{lifetime}`
|
||||||
|
*[anon] an anonymous lifetime `'_`
|
||||||
|
}
|
||||||
|
.label2 = ...is used and required to live as long as `'static` here because of an implicit lifetime bound on the {$has_impl_path ->
|
||||||
|
[named] `impl` of `{$impl_path}`
|
||||||
|
*[anon] inherent `impl`
|
||||||
|
}
|
||||||
|
|
||||||
|
infer_but_needs_to_satisfy = {$has_param_name ->
|
||||||
|
[true] `{$param_name}`
|
||||||
|
*[false] `fn` parameter
|
||||||
|
} has {$has_lifetime ->
|
||||||
|
[named] lifetime `{lifetime}`
|
||||||
|
*[anon] an anonymous lifetime `'_`
|
||||||
|
} but it needs to satisfy a `'static` lifetime requirement
|
||||||
|
.influencer = this data with {$has_lifetime ->
|
||||||
|
[named] lifetime `{lifetime}`
|
||||||
|
*[anon] an anonymous lifetime `'_`
|
||||||
|
}...
|
||||||
|
.require = {$spans_empty ->
|
||||||
|
*[true] ...is used and required to live as long as `'static` here
|
||||||
|
[false] ...and is required to live as long as `'static` here
|
||||||
|
}
|
||||||
|
.used_here = ...is used here...
|
||||||
|
.introduced_by_bound = 'static` lifetime requirement introduced by this bound
|
||||||
|
|
||||||
|
infer_more_targeted = {$has_param_name ->
|
||||||
|
[true] `{$param_name}`
|
||||||
|
*[false] `fn` parameter
|
||||||
|
} has {$has_lifetime ->
|
||||||
|
[named] lifetime `{lifetime}`
|
||||||
|
*[anon] an anonymous lifetime `'_`
|
||||||
|
} but calling `{$ident}` introduces an implicit `'static` lifetime requirement
|
||||||
|
|
||||||
|
infer_ril_introduced_here = `'static` requirement introduced here
|
||||||
|
infer_ril_introduced_by = requirement introduced by this return type
|
||||||
|
infer_ril_because_of = because of this returned expression
|
||||||
|
infer_ril_static_introduced_by = "`'static` lifetime requirement introduced by the return type
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
use hir::GenericParamKind;
|
use hir::GenericParamKind;
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
fluent, AddToDiagnostic, Applicability, Diagnostic, DiagnosticMessage, DiagnosticStyledString,
|
fluent, AddToDiagnostic, Applicability, Diagnostic, DiagnosticMessage, DiagnosticStyledString,
|
||||||
MultiSpan, SubdiagnosticMessage,
|
IntoDiagnosticArg, MultiSpan, SubdiagnosticMessage,
|
||||||
};
|
};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::{FnRetTy, Ty};
|
use rustc_hir::FnRetTy;
|
||||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||||
use rustc_middle::ty::{Region, TyCtxt};
|
use rustc_middle::ty::print::TraitRefPrintOnlyTraitPath;
|
||||||
|
use rustc_middle::ty::{Binder, FnSig, Region, Ty, TyCtxt};
|
||||||
use rustc_span::symbol::kw;
|
use rustc_span::symbol::kw;
|
||||||
|
use rustc_span::Symbol;
|
||||||
use rustc_span::{symbol::Ident, BytePos, Span};
|
use rustc_span::{symbol::Ident, BytePos, Span};
|
||||||
|
|
||||||
|
use crate::infer::error_reporting::nice_region_error::placeholder_error::Highlighted;
|
||||||
use crate::infer::error_reporting::{
|
use crate::infer::error_reporting::{
|
||||||
need_type_info::{GeneratorKindAsDiagArg, UnderspecifiedArgKind},
|
need_type_info::{GeneratorKindAsDiagArg, UnderspecifiedArgKind},
|
||||||
ObligationCauseAsDiagArg,
|
ObligationCauseAsDiagArg,
|
||||||
|
@ -357,8 +360,8 @@ impl AddToDiagnostic for LifetimeMismatchLabels {
|
||||||
pub struct AddLifetimeParamsSuggestion<'a> {
|
pub struct AddLifetimeParamsSuggestion<'a> {
|
||||||
pub tcx: TyCtxt<'a>,
|
pub tcx: TyCtxt<'a>,
|
||||||
pub sub: Region<'a>,
|
pub sub: Region<'a>,
|
||||||
pub ty_sup: &'a Ty<'a>,
|
pub ty_sup: &'a hir::Ty<'a>,
|
||||||
pub ty_sub: &'a Ty<'a>,
|
pub ty_sub: &'a hir::Ty<'a>,
|
||||||
pub add_note: bool,
|
pub add_note: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -520,3 +523,411 @@ pub struct MismatchedStaticLifetime<'a> {
|
||||||
#[subdiagnostic]
|
#[subdiagnostic]
|
||||||
pub implicit_static_lifetimes: Vec<ImplicitStaticLifetimeSubdiag>,
|
pub implicit_static_lifetimes: Vec<ImplicitStaticLifetimeSubdiag>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
pub enum ExplicitLifetimeRequired<'a> {
|
||||||
|
#[diag(infer_explicit_lifetime_required_with_ident, code = "E0621")]
|
||||||
|
WithIdent {
|
||||||
|
#[primary_span]
|
||||||
|
#[label]
|
||||||
|
span: Span,
|
||||||
|
simple_ident: Ident,
|
||||||
|
named: String,
|
||||||
|
#[suggestion(
|
||||||
|
infer_explicit_lifetime_required_sugg_with_ident,
|
||||||
|
code = "{new_ty}",
|
||||||
|
applicability = "unspecified"
|
||||||
|
)]
|
||||||
|
new_ty_span: Span,
|
||||||
|
#[skip_arg]
|
||||||
|
new_ty: Ty<'a>,
|
||||||
|
},
|
||||||
|
#[diag(infer_explicit_lifetime_required_with_param_type, code = "E0621")]
|
||||||
|
WithParamType {
|
||||||
|
#[primary_span]
|
||||||
|
#[label]
|
||||||
|
span: Span,
|
||||||
|
named: String,
|
||||||
|
#[suggestion(
|
||||||
|
infer_explicit_lifetime_required_sugg_with_param_type,
|
||||||
|
code = "{new_ty}",
|
||||||
|
applicability = "unspecified"
|
||||||
|
)]
|
||||||
|
new_ty_span: Span,
|
||||||
|
#[skip_arg]
|
||||||
|
new_ty: Ty<'a>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum TyOrSig<'tcx> {
|
||||||
|
Ty(Highlighted<'tcx, Ty<'tcx>>),
|
||||||
|
ClosureSig(Highlighted<'tcx, Binder<'tcx, FnSig<'tcx>>>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoDiagnosticArg for TyOrSig<'_> {
|
||||||
|
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
|
||||||
|
match self {
|
||||||
|
TyOrSig::Ty(ty) => ty.into_diagnostic_arg(),
|
||||||
|
TyOrSig::ClosureSig(sig) => sig.into_diagnostic_arg(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
pub enum ActualImplExplNotes<'tcx> {
|
||||||
|
#[note(infer_actual_impl_expl_expected_signature_two)]
|
||||||
|
ExpectedSignatureTwo {
|
||||||
|
leading_ellipsis: bool,
|
||||||
|
ty_or_sig: TyOrSig<'tcx>,
|
||||||
|
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||||
|
lifetime_1: usize,
|
||||||
|
lifetime_2: usize,
|
||||||
|
},
|
||||||
|
#[note(infer_actual_impl_expl_expected_signature_any)]
|
||||||
|
ExpectedSignatureAny {
|
||||||
|
leading_ellipsis: bool,
|
||||||
|
ty_or_sig: TyOrSig<'tcx>,
|
||||||
|
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||||
|
lifetime_1: usize,
|
||||||
|
},
|
||||||
|
#[note(infer_actual_impl_expl_expected_signature_some)]
|
||||||
|
ExpectedSignatureSome {
|
||||||
|
leading_ellipsis: bool,
|
||||||
|
ty_or_sig: TyOrSig<'tcx>,
|
||||||
|
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||||
|
lifetime_1: usize,
|
||||||
|
},
|
||||||
|
#[note(infer_actual_impl_expl_expected_signature_nothing)]
|
||||||
|
ExpectedSignatureNothing {
|
||||||
|
leading_ellipsis: bool,
|
||||||
|
ty_or_sig: TyOrSig<'tcx>,
|
||||||
|
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||||
|
},
|
||||||
|
#[note(infer_actual_impl_expl_expected_passive_two)]
|
||||||
|
ExpectedPassiveTwo {
|
||||||
|
leading_ellipsis: bool,
|
||||||
|
ty_or_sig: TyOrSig<'tcx>,
|
||||||
|
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||||
|
lifetime_1: usize,
|
||||||
|
lifetime_2: usize,
|
||||||
|
},
|
||||||
|
#[note(infer_actual_impl_expl_expected_passive_any)]
|
||||||
|
ExpectedPassiveAny {
|
||||||
|
leading_ellipsis: bool,
|
||||||
|
ty_or_sig: TyOrSig<'tcx>,
|
||||||
|
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||||
|
lifetime_1: usize,
|
||||||
|
},
|
||||||
|
#[note(infer_actual_impl_expl_expected_passive_some)]
|
||||||
|
ExpectedPassiveSome {
|
||||||
|
leading_ellipsis: bool,
|
||||||
|
ty_or_sig: TyOrSig<'tcx>,
|
||||||
|
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||||
|
lifetime_1: usize,
|
||||||
|
},
|
||||||
|
#[note(infer_actual_impl_expl_expected_passive_nothing)]
|
||||||
|
ExpectedPassiveNothing {
|
||||||
|
leading_ellipsis: bool,
|
||||||
|
ty_or_sig: TyOrSig<'tcx>,
|
||||||
|
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||||
|
},
|
||||||
|
#[note(infer_actual_impl_expl_expected_other_two)]
|
||||||
|
ExpectedOtherTwo {
|
||||||
|
leading_ellipsis: bool,
|
||||||
|
ty_or_sig: TyOrSig<'tcx>,
|
||||||
|
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||||
|
lifetime_1: usize,
|
||||||
|
lifetime_2: usize,
|
||||||
|
},
|
||||||
|
#[note(infer_actual_impl_expl_expected_other_any)]
|
||||||
|
ExpectedOtherAny {
|
||||||
|
leading_ellipsis: bool,
|
||||||
|
ty_or_sig: TyOrSig<'tcx>,
|
||||||
|
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||||
|
lifetime_1: usize,
|
||||||
|
},
|
||||||
|
#[note(infer_actual_impl_expl_expected_other_some)]
|
||||||
|
ExpectedOtherSome {
|
||||||
|
leading_ellipsis: bool,
|
||||||
|
ty_or_sig: TyOrSig<'tcx>,
|
||||||
|
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||||
|
lifetime_1: usize,
|
||||||
|
},
|
||||||
|
#[note(infer_actual_impl_expl_expected_other_nothing)]
|
||||||
|
ExpectedOtherNothing {
|
||||||
|
leading_ellipsis: bool,
|
||||||
|
ty_or_sig: TyOrSig<'tcx>,
|
||||||
|
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||||
|
},
|
||||||
|
#[note(infer_actual_impl_expl_but_actually_implements_trait)]
|
||||||
|
ButActuallyImplementsTrait {
|
||||||
|
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||||
|
has_lifetime: bool,
|
||||||
|
lifetime: usize,
|
||||||
|
},
|
||||||
|
#[note(infer_actual_impl_expl_but_actually_implemented_for_ty)]
|
||||||
|
ButActuallyImplementedForTy {
|
||||||
|
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||||
|
has_lifetime: bool,
|
||||||
|
lifetime: usize,
|
||||||
|
ty: String,
|
||||||
|
},
|
||||||
|
#[note(infer_actual_impl_expl_but_actually_ty_implements)]
|
||||||
|
ButActuallyTyImplements {
|
||||||
|
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||||
|
has_lifetime: bool,
|
||||||
|
lifetime: usize,
|
||||||
|
ty: String,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum ActualImplExpectedKind {
|
||||||
|
Signature,
|
||||||
|
Passive,
|
||||||
|
Other,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum ActualImplExpectedLifetimeKind {
|
||||||
|
Two,
|
||||||
|
Any,
|
||||||
|
Some,
|
||||||
|
Nothing,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> ActualImplExplNotes<'tcx> {
|
||||||
|
pub fn new_expected(
|
||||||
|
kind: ActualImplExpectedKind,
|
||||||
|
lt_kind: ActualImplExpectedLifetimeKind,
|
||||||
|
leading_ellipsis: bool,
|
||||||
|
ty_or_sig: TyOrSig<'tcx>,
|
||||||
|
trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||||
|
lifetime_1: usize,
|
||||||
|
lifetime_2: usize,
|
||||||
|
) -> Self {
|
||||||
|
match (kind, lt_kind) {
|
||||||
|
(ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Two) => {
|
||||||
|
Self::ExpectedSignatureTwo {
|
||||||
|
leading_ellipsis,
|
||||||
|
ty_or_sig,
|
||||||
|
trait_path,
|
||||||
|
lifetime_1,
|
||||||
|
lifetime_2,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Any) => {
|
||||||
|
Self::ExpectedSignatureAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
|
||||||
|
}
|
||||||
|
(ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Some) => {
|
||||||
|
Self::ExpectedSignatureSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
|
||||||
|
}
|
||||||
|
(ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Nothing) => {
|
||||||
|
Self::ExpectedSignatureNothing { leading_ellipsis, ty_or_sig, trait_path }
|
||||||
|
}
|
||||||
|
(ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Two) => {
|
||||||
|
Self::ExpectedPassiveTwo {
|
||||||
|
leading_ellipsis,
|
||||||
|
ty_or_sig,
|
||||||
|
trait_path,
|
||||||
|
lifetime_1,
|
||||||
|
lifetime_2,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Any) => {
|
||||||
|
Self::ExpectedPassiveAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
|
||||||
|
}
|
||||||
|
(ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Some) => {
|
||||||
|
Self::ExpectedPassiveSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
|
||||||
|
}
|
||||||
|
(ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Nothing) => {
|
||||||
|
Self::ExpectedPassiveNothing { leading_ellipsis, ty_or_sig, trait_path }
|
||||||
|
}
|
||||||
|
(ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Two) => {
|
||||||
|
Self::ExpectedOtherTwo {
|
||||||
|
leading_ellipsis,
|
||||||
|
ty_or_sig,
|
||||||
|
trait_path,
|
||||||
|
lifetime_1,
|
||||||
|
lifetime_2,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Any) => {
|
||||||
|
Self::ExpectedOtherAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
|
||||||
|
}
|
||||||
|
(ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Some) => {
|
||||||
|
Self::ExpectedOtherSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 }
|
||||||
|
}
|
||||||
|
(ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Nothing) => {
|
||||||
|
Self::ExpectedOtherNothing { leading_ellipsis, ty_or_sig, trait_path }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(infer_trait_placeholder_mismatch)]
|
||||||
|
pub struct TraitPlaceholderMismatch<'tcx> {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
#[label(label_satisfy)]
|
||||||
|
pub satisfy_span: Option<Span>,
|
||||||
|
#[label(label_where)]
|
||||||
|
pub where_span: Option<Span>,
|
||||||
|
#[label(label_dup)]
|
||||||
|
pub dup_span: Option<Span>,
|
||||||
|
pub def_id: String,
|
||||||
|
pub trait_def_id: String,
|
||||||
|
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub actual_impl_expl_notes: Vec<ActualImplExplNotes<'tcx>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ConsiderBorrowingParamHelp {
|
||||||
|
pub spans: Vec<Span>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AddToDiagnostic for ConsiderBorrowingParamHelp {
|
||||||
|
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, f: F)
|
||||||
|
where
|
||||||
|
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||||
|
{
|
||||||
|
let mut type_param_span: MultiSpan = self.spans.clone().into();
|
||||||
|
for &span in &self.spans {
|
||||||
|
// Seems like we can't call f() here as Into<DiagnosticMessage> is required
|
||||||
|
type_param_span.push_span_label(span, fluent::infer_tid_consider_borrowing);
|
||||||
|
}
|
||||||
|
let msg = f(diag, fluent::infer_tid_param_help.into());
|
||||||
|
diag.span_help(type_param_span, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[help(infer_tid_rel_help)]
|
||||||
|
pub struct RelationshipHelp;
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(infer_trait_impl_diff)]
|
||||||
|
pub struct TraitImplDiff {
|
||||||
|
#[primary_span]
|
||||||
|
#[label(found)]
|
||||||
|
pub sp: Span,
|
||||||
|
#[label(expected)]
|
||||||
|
pub trait_sp: Span,
|
||||||
|
#[note(expected_found)]
|
||||||
|
pub note: (),
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub param_help: ConsiderBorrowingParamHelp,
|
||||||
|
#[subdiagnostic]
|
||||||
|
// Seems like subdiagnostics are always pushed to the end, so this one
|
||||||
|
// also has to be a subdiagnostic to maintain order.
|
||||||
|
pub rel_help: Option<RelationshipHelp>,
|
||||||
|
pub expected: String,
|
||||||
|
pub found: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DynTraitConstraintSuggestion {
|
||||||
|
pub span: Span,
|
||||||
|
pub ident: Ident,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AddToDiagnostic for DynTraitConstraintSuggestion {
|
||||||
|
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, f: F)
|
||||||
|
where
|
||||||
|
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||||
|
{
|
||||||
|
let mut multi_span: MultiSpan = vec![self.span].into();
|
||||||
|
multi_span.push_span_label(self.span, fluent::infer_dtcs_has_lifetime_req_label);
|
||||||
|
multi_span.push_span_label(self.ident.span, fluent::infer_dtcs_introduces_requirement);
|
||||||
|
let msg = f(diag, fluent::infer_dtcs_has_req_note.into());
|
||||||
|
diag.span_note(multi_span, msg);
|
||||||
|
let msg = f(diag, fluent::infer_dtcs_suggestion.into());
|
||||||
|
diag.span_suggestion_verbose(
|
||||||
|
self.span.shrink_to_hi(),
|
||||||
|
msg,
|
||||||
|
" + '_",
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(infer_but_calling_introduces, code = "E0772")]
|
||||||
|
pub struct ButCallingIntroduces {
|
||||||
|
#[label(label1)]
|
||||||
|
pub param_ty_span: Span,
|
||||||
|
#[primary_span]
|
||||||
|
#[label(label2)]
|
||||||
|
pub cause_span: Span,
|
||||||
|
|
||||||
|
pub has_param_name: bool,
|
||||||
|
pub param_name: String,
|
||||||
|
pub has_lifetime: bool,
|
||||||
|
pub lifetime: String,
|
||||||
|
pub assoc_item: Symbol,
|
||||||
|
pub has_impl_path: bool,
|
||||||
|
pub impl_path: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ReqIntroducedLocations {
|
||||||
|
pub span: MultiSpan,
|
||||||
|
pub spans: Vec<Span>,
|
||||||
|
pub fn_decl_span: Span,
|
||||||
|
pub cause_span: Span,
|
||||||
|
pub add_label: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AddToDiagnostic for ReqIntroducedLocations {
|
||||||
|
fn add_to_diagnostic_with<F>(mut self, diag: &mut Diagnostic, f: F)
|
||||||
|
where
|
||||||
|
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||||
|
{
|
||||||
|
for sp in self.spans {
|
||||||
|
self.span.push_span_label(sp, fluent::infer_ril_introduced_here);
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.add_label {
|
||||||
|
self.span.push_span_label(self.fn_decl_span, fluent::infer_ril_introduced_by);
|
||||||
|
}
|
||||||
|
self.span.push_span_label(self.cause_span, fluent::infer_ril_because_of);
|
||||||
|
let msg = f(diag, fluent::infer_ril_static_introduced_by.into());
|
||||||
|
diag.span_note(self.span, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MoreTargeted {
|
||||||
|
pub ident: Symbol,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AddToDiagnostic for MoreTargeted {
|
||||||
|
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _f: F)
|
||||||
|
where
|
||||||
|
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||||
|
{
|
||||||
|
diag.code(rustc_errors::error_code!(E0772));
|
||||||
|
diag.set_primary_message(fluent::infer_more_targeted);
|
||||||
|
diag.set_arg("ident", self.ident);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(infer_but_needs_to_satisfy, code = "E0759")]
|
||||||
|
pub struct ButNeedsToSatisfy {
|
||||||
|
#[primary_span]
|
||||||
|
pub sp: Span,
|
||||||
|
#[label(influencer)]
|
||||||
|
pub influencer_point: Span,
|
||||||
|
#[label(used_here)]
|
||||||
|
pub spans: Vec<Span>,
|
||||||
|
#[label(require)]
|
||||||
|
pub require_span_as_label: Option<Span>,
|
||||||
|
#[note(require)]
|
||||||
|
pub require_span_as_note: Option<Span>,
|
||||||
|
#[note(introduced_by_bound)]
|
||||||
|
pub bound: Option<Span>,
|
||||||
|
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub req_introduces_loc: Option<ReqIntroducedLocations>,
|
||||||
|
|
||||||
|
pub spans_empty: bool,
|
||||||
|
pub has_lifetime: bool,
|
||||||
|
pub lifetime: String,
|
||||||
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ mod different_lifetimes;
|
||||||
pub mod find_anon_type;
|
pub mod find_anon_type;
|
||||||
mod mismatched_static_lifetime;
|
mod mismatched_static_lifetime;
|
||||||
mod named_anon_conflict;
|
mod named_anon_conflict;
|
||||||
mod placeholder_error;
|
pub(crate) mod placeholder_error;
|
||||||
mod placeholder_relation;
|
mod placeholder_relation;
|
||||||
mod static_impl_trait;
|
mod static_impl_trait;
|
||||||
mod trait_impl_difference;
|
mod trait_impl_difference;
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
//! Error Reporting for Anonymous Region Lifetime Errors
|
//! Error Reporting for Anonymous Region Lifetime Errors
|
||||||
//! where one region is named and the other is anonymous.
|
//! where one region is named and the other is anonymous.
|
||||||
use crate::infer::error_reporting::nice_region_error::find_anon_type::find_anon_type;
|
|
||||||
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
|
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
|
||||||
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
|
use crate::{
|
||||||
|
errors::ExplicitLifetimeRequired,
|
||||||
|
infer::error_reporting::nice_region_error::find_anon_type::find_anon_type,
|
||||||
|
};
|
||||||
|
use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty;
|
||||||
use rustc_span::symbol::kw;
|
use rustc_span::symbol::kw;
|
||||||
|
|
||||||
|
@ -86,31 +89,17 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
{
|
{
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
let named = named.to_string();
|
||||||
let (error_var, span_label_var) = match param.pat.simple_ident() {
|
let err = match param.pat.simple_ident() {
|
||||||
Some(simple_ident) => (
|
Some(simple_ident) => ExplicitLifetimeRequired::WithIdent {
|
||||||
format!("the type of `{}`", simple_ident),
|
span,
|
||||||
format!("the type of `{}`", simple_ident),
|
simple_ident,
|
||||||
),
|
named,
|
||||||
None => ("parameter type".to_owned(), "type".to_owned()),
|
new_ty_span,
|
||||||
|
new_ty,
|
||||||
|
},
|
||||||
|
None => ExplicitLifetimeRequired::WithParamType { span, named, new_ty_span, new_ty },
|
||||||
};
|
};
|
||||||
|
Some(self.tcx().sess.parse_sess.create_err(err))
|
||||||
let mut diag = struct_span_err!(
|
|
||||||
self.tcx().sess,
|
|
||||||
span,
|
|
||||||
E0621,
|
|
||||||
"explicit lifetime required in {}",
|
|
||||||
error_var
|
|
||||||
);
|
|
||||||
|
|
||||||
diag.span_label(span, format!("lifetime `{}` required", named));
|
|
||||||
diag.span_suggestion(
|
|
||||||
new_ty_span,
|
|
||||||
&format!("add explicit lifetime `{}` to {}", named, span_label_var),
|
|
||||||
new_ty,
|
|
||||||
Applicability::Unspecified,
|
|
||||||
);
|
|
||||||
|
|
||||||
Some(diag)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
|
use crate::errors::{
|
||||||
|
ActualImplExpectedKind, ActualImplExpectedLifetimeKind, ActualImplExplNotes,
|
||||||
|
TraitPlaceholderMismatch, TyOrSig,
|
||||||
|
};
|
||||||
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
|
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
|
||||||
use crate::infer::lexical_region_resolve::RegionResolutionError;
|
use crate::infer::lexical_region_resolve::RegionResolutionError;
|
||||||
use crate::infer::ValuePairs;
|
use crate::infer::ValuePairs;
|
||||||
use crate::infer::{SubregionOrigin, TypeTrace};
|
use crate::infer::{SubregionOrigin, TypeTrace};
|
||||||
use crate::traits::{ObligationCause, ObligationCauseCode};
|
use crate::traits::{ObligationCause, ObligationCauseCode};
|
||||||
use rustc_data_structures::intern::Interned;
|
use rustc_data_structures::intern::Interned;
|
||||||
use rustc_errors::{Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
|
use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, IntoDiagnosticArg};
|
||||||
use rustc_hir::def::Namespace;
|
use rustc_hir::def::Namespace;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_middle::ty::error::ExpectedFound;
|
use rustc_middle::ty::error::ExpectedFound;
|
||||||
|
@ -12,7 +16,43 @@ use rustc_middle::ty::print::{FmtPrinter, Print, RegionHighlightMode};
|
||||||
use rustc_middle::ty::subst::SubstsRef;
|
use rustc_middle::ty::subst::SubstsRef;
|
||||||
use rustc_middle::ty::{self, RePlaceholder, ReVar, Region, TyCtxt};
|
use rustc_middle::ty::{self, RePlaceholder, ReVar, Region, TyCtxt};
|
||||||
|
|
||||||
use std::fmt::{self, Write};
|
use std::fmt;
|
||||||
|
|
||||||
|
// HACK(eddyb) maybe move this in a more central location.
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct Highlighted<'tcx, T> {
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
highlight: RegionHighlightMode<'tcx>,
|
||||||
|
value: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx, T> IntoDiagnosticArg for Highlighted<'tcx, T>
|
||||||
|
where
|
||||||
|
T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>, Error = fmt::Error, Output = FmtPrinter<'a, 'tcx>>,
|
||||||
|
{
|
||||||
|
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
|
||||||
|
rustc_errors::DiagnosticArgValue::Str(self.to_string().into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx, T> Highlighted<'tcx, T> {
|
||||||
|
fn map<U>(self, f: impl FnOnce(T) -> U) -> Highlighted<'tcx, U> {
|
||||||
|
Highlighted { tcx: self.tcx, highlight: self.highlight, value: f(self.value) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx, T> fmt::Display for Highlighted<'tcx, T>
|
||||||
|
where
|
||||||
|
T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>, Error = fmt::Error, Output = FmtPrinter<'a, 'tcx>>,
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
let mut printer = ty::print::FmtPrinter::new(self.tcx, Namespace::TypeNS);
|
||||||
|
printer.region_highlight_mode = self.highlight;
|
||||||
|
|
||||||
|
let s = self.value.print(printer)?.into_buffer();
|
||||||
|
f.write_str(&s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> NiceRegionError<'_, 'tcx> {
|
impl<'tcx> NiceRegionError<'_, 'tcx> {
|
||||||
/// When given a `ConcreteFailure` for a function with arguments containing a named region and
|
/// When given a `ConcreteFailure` for a function with arguments containing a named region and
|
||||||
|
@ -205,26 +245,21 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
|
||||||
actual_substs: SubstsRef<'tcx>,
|
actual_substs: SubstsRef<'tcx>,
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||||
let span = cause.span();
|
let span = cause.span();
|
||||||
let msg = format!(
|
|
||||||
"implementation of `{}` is not general enough",
|
|
||||||
self.tcx().def_path_str(trait_def_id),
|
|
||||||
);
|
|
||||||
let mut err = self.tcx().sess.struct_span_err(span, &msg);
|
|
||||||
|
|
||||||
let leading_ellipsis = if let ObligationCauseCode::ItemObligation(def_id)
|
let (leading_ellipsis, satisfy_span, where_span, dup_span, def_id) =
|
||||||
| ObligationCauseCode::ExprItemObligation(def_id, ..) =
|
if let ObligationCauseCode::ItemObligation(def_id)
|
||||||
*cause.code()
|
| ObligationCauseCode::ExprItemObligation(def_id, ..) = *cause.code()
|
||||||
{
|
{
|
||||||
err.span_label(span, "doesn't satisfy where-clause");
|
(
|
||||||
err.span_label(
|
true,
|
||||||
self.tcx().def_span(def_id),
|
Some(span),
|
||||||
&format!("due to a where-clause on `{}`...", self.tcx().def_path_str(def_id)),
|
Some(self.tcx().def_span(def_id)),
|
||||||
);
|
None,
|
||||||
true
|
self.tcx().def_path_str(def_id),
|
||||||
} else {
|
)
|
||||||
err.span_label(span, &msg);
|
} else {
|
||||||
false
|
(false, None, None, Some(span), String::new())
|
||||||
};
|
};
|
||||||
|
|
||||||
let expected_trait_ref = self
|
let expected_trait_ref = self
|
||||||
.cx
|
.cx
|
||||||
|
@ -284,8 +319,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
|
||||||
?expected_self_ty_has_vid,
|
?expected_self_ty_has_vid,
|
||||||
);
|
);
|
||||||
|
|
||||||
self.explain_actual_impl_that_was_found(
|
let actual_impl_expl_notes = self.explain_actual_impl_that_was_found(
|
||||||
&mut err,
|
|
||||||
sub_placeholder,
|
sub_placeholder,
|
||||||
sup_placeholder,
|
sup_placeholder,
|
||||||
has_sub,
|
has_sub,
|
||||||
|
@ -299,7 +333,15 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
|
||||||
leading_ellipsis,
|
leading_ellipsis,
|
||||||
);
|
);
|
||||||
|
|
||||||
err
|
self.tcx().sess.create_err(TraitPlaceholderMismatch {
|
||||||
|
span,
|
||||||
|
satisfy_span,
|
||||||
|
where_span,
|
||||||
|
dup_span,
|
||||||
|
def_id,
|
||||||
|
trait_def_id: self.tcx().def_path_str(trait_def_id),
|
||||||
|
actual_impl_expl_notes,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add notes with details about the expected and actual trait refs, with attention to cases
|
/// Add notes with details about the expected and actual trait refs, with attention to cases
|
||||||
|
@ -309,7 +351,6 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
|
||||||
/// due to the number of combinations we have to deal with.
|
/// due to the number of combinations we have to deal with.
|
||||||
fn explain_actual_impl_that_was_found(
|
fn explain_actual_impl_that_was_found(
|
||||||
&self,
|
&self,
|
||||||
err: &mut Diagnostic,
|
|
||||||
sub_placeholder: Option<Region<'tcx>>,
|
sub_placeholder: Option<Region<'tcx>>,
|
||||||
sup_placeholder: Option<Region<'tcx>>,
|
sup_placeholder: Option<Region<'tcx>>,
|
||||||
has_sub: Option<usize>,
|
has_sub: Option<usize>,
|
||||||
|
@ -321,39 +362,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
|
||||||
actual_has_vid: Option<usize>,
|
actual_has_vid: Option<usize>,
|
||||||
any_self_ty_has_vid: bool,
|
any_self_ty_has_vid: bool,
|
||||||
leading_ellipsis: bool,
|
leading_ellipsis: bool,
|
||||||
) {
|
) -> Vec<ActualImplExplNotes<'tcx>> {
|
||||||
// HACK(eddyb) maybe move this in a more central location.
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
struct Highlighted<'tcx, T> {
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
highlight: RegionHighlightMode<'tcx>,
|
|
||||||
value: T,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx, T> Highlighted<'tcx, T> {
|
|
||||||
fn map<U>(self, f: impl FnOnce(T) -> U) -> Highlighted<'tcx, U> {
|
|
||||||
Highlighted { tcx: self.tcx, highlight: self.highlight, value: f(self.value) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx, T> fmt::Display for Highlighted<'tcx, T>
|
|
||||||
where
|
|
||||||
T: for<'a> Print<
|
|
||||||
'tcx,
|
|
||||||
FmtPrinter<'a, 'tcx>,
|
|
||||||
Error = fmt::Error,
|
|
||||||
Output = FmtPrinter<'a, 'tcx>,
|
|
||||||
>,
|
|
||||||
{
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
let mut printer = ty::print::FmtPrinter::new(self.tcx, Namespace::TypeNS);
|
|
||||||
printer.region_highlight_mode = self.highlight;
|
|
||||||
|
|
||||||
let s = self.value.print(printer)?.into_buffer();
|
|
||||||
f.write_str(&s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The weird thing here with the `maybe_highlighting_region` calls and the
|
// The weird thing here with the `maybe_highlighting_region` calls and the
|
||||||
// the match inside is meant to be like this:
|
// the match inside is meant to be like this:
|
||||||
//
|
//
|
||||||
|
@ -380,120 +389,110 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
|
||||||
let mut expected_trait_ref = highlight_trait_ref(expected_trait_ref);
|
let mut expected_trait_ref = highlight_trait_ref(expected_trait_ref);
|
||||||
expected_trait_ref.highlight.maybe_highlighting_region(sub_placeholder, has_sub);
|
expected_trait_ref.highlight.maybe_highlighting_region(sub_placeholder, has_sub);
|
||||||
expected_trait_ref.highlight.maybe_highlighting_region(sup_placeholder, has_sup);
|
expected_trait_ref.highlight.maybe_highlighting_region(sup_placeholder, has_sup);
|
||||||
err.note(&{
|
|
||||||
let passive_voice = match (has_sub, has_sup) {
|
|
||||||
(Some(_), _) | (_, Some(_)) => any_self_ty_has_vid,
|
|
||||||
(None, None) => {
|
|
||||||
expected_trait_ref.highlight.maybe_highlighting_region(vid, expected_has_vid);
|
|
||||||
match expected_has_vid {
|
|
||||||
Some(_) => true,
|
|
||||||
None => any_self_ty_has_vid,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut note = if same_self_type {
|
let passive_voice = match (has_sub, has_sup) {
|
||||||
let mut self_ty = expected_trait_ref.map(|tr| tr.self_ty());
|
(Some(_), _) | (_, Some(_)) => any_self_ty_has_vid,
|
||||||
self_ty.highlight.maybe_highlighting_region(vid, actual_has_vid);
|
(None, None) => {
|
||||||
|
expected_trait_ref.highlight.maybe_highlighting_region(vid, expected_has_vid);
|
||||||
if self_ty.value.is_closure()
|
match expected_has_vid {
|
||||||
&& self.tcx().is_fn_trait(expected_trait_ref.value.def_id)
|
Some(_) => true,
|
||||||
{
|
None => any_self_ty_has_vid,
|
||||||
let closure_sig = self_ty.map(|closure| {
|
|
||||||
if let ty::Closure(_, substs) = closure.kind() {
|
|
||||||
self.tcx().signature_unclosure(
|
|
||||||
substs.as_closure().sig(),
|
|
||||||
rustc_hir::Unsafety::Normal,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
bug!("type is not longer closure");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
format!(
|
|
||||||
"{}closure with signature `{}` must implement `{}`",
|
|
||||||
if leading_ellipsis { "..." } else { "" },
|
|
||||||
closure_sig,
|
|
||||||
expected_trait_ref.map(|tr| tr.print_only_trait_path()),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
format!(
|
|
||||||
"{}`{}` must implement `{}`",
|
|
||||||
if leading_ellipsis { "..." } else { "" },
|
|
||||||
self_ty,
|
|
||||||
expected_trait_ref.map(|tr| tr.print_only_trait_path()),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else if passive_voice {
|
|
||||||
format!(
|
|
||||||
"{}`{}` would have to be implemented for the type `{}`",
|
|
||||||
if leading_ellipsis { "..." } else { "" },
|
|
||||||
expected_trait_ref.map(|tr| tr.print_only_trait_path()),
|
|
||||||
expected_trait_ref.map(|tr| tr.self_ty()),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
format!(
|
|
||||||
"{}`{}` must implement `{}`",
|
|
||||||
if leading_ellipsis { "..." } else { "" },
|
|
||||||
expected_trait_ref.map(|tr| tr.self_ty()),
|
|
||||||
expected_trait_ref.map(|tr| tr.print_only_trait_path()),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
match (has_sub, has_sup) {
|
|
||||||
(Some(n1), Some(n2)) => {
|
|
||||||
let _ = write!(
|
|
||||||
note,
|
|
||||||
", for any two lifetimes `'{}` and `'{}`...",
|
|
||||||
std::cmp::min(n1, n2),
|
|
||||||
std::cmp::max(n1, n2),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
(Some(n), _) | (_, Some(n)) => {
|
|
||||||
let _ = write!(note, ", for any lifetime `'{}`...", n,);
|
|
||||||
}
|
|
||||||
(None, None) => {
|
|
||||||
if let Some(n) = expected_has_vid {
|
|
||||||
let _ = write!(note, ", for some specific lifetime `'{}`...", n,);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
note
|
let (kind, ty_or_sig, trait_path) = if same_self_type {
|
||||||
});
|
let mut self_ty = expected_trait_ref.map(|tr| tr.self_ty());
|
||||||
|
self_ty.highlight.maybe_highlighting_region(vid, actual_has_vid);
|
||||||
|
|
||||||
|
if self_ty.value.is_closure() && self.tcx().is_fn_trait(expected_trait_ref.value.def_id)
|
||||||
|
{
|
||||||
|
let closure_sig = self_ty.map(|closure| {
|
||||||
|
if let ty::Closure(_, substs) = closure.kind() {
|
||||||
|
self.tcx().signature_unclosure(
|
||||||
|
substs.as_closure().sig(),
|
||||||
|
rustc_hir::Unsafety::Normal,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
bug!("type is not longer closure");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
(
|
||||||
|
ActualImplExpectedKind::Signature,
|
||||||
|
TyOrSig::ClosureSig(closure_sig),
|
||||||
|
expected_trait_ref.map(|tr| tr.print_only_trait_path()),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
ActualImplExpectedKind::Other,
|
||||||
|
TyOrSig::Ty(self_ty),
|
||||||
|
expected_trait_ref.map(|tr| tr.print_only_trait_path()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else if passive_voice {
|
||||||
|
(
|
||||||
|
ActualImplExpectedKind::Passive,
|
||||||
|
TyOrSig::Ty(expected_trait_ref.map(|tr| tr.self_ty())),
|
||||||
|
expected_trait_ref.map(|tr| tr.print_only_trait_path()),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
ActualImplExpectedKind::Other,
|
||||||
|
TyOrSig::Ty(expected_trait_ref.map(|tr| tr.self_ty())),
|
||||||
|
expected_trait_ref.map(|tr| tr.print_only_trait_path()),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
let (lt_kind, lifetime_1, lifetime_2) = match (has_sub, has_sup) {
|
||||||
|
(Some(n1), Some(n2)) => {
|
||||||
|
(ActualImplExpectedLifetimeKind::Two, std::cmp::min(n1, n2), std::cmp::max(n1, n2))
|
||||||
|
}
|
||||||
|
(Some(n), _) | (_, Some(n)) => (ActualImplExpectedLifetimeKind::Any, n, 0),
|
||||||
|
(None, None) => {
|
||||||
|
if let Some(n) = expected_has_vid {
|
||||||
|
(ActualImplExpectedLifetimeKind::Some, n, 0)
|
||||||
|
} else {
|
||||||
|
(ActualImplExpectedLifetimeKind::Nothing, 0, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let note_1 = ActualImplExplNotes::new_expected(
|
||||||
|
kind,
|
||||||
|
lt_kind,
|
||||||
|
leading_ellipsis,
|
||||||
|
ty_or_sig,
|
||||||
|
trait_path,
|
||||||
|
lifetime_1,
|
||||||
|
lifetime_2,
|
||||||
|
);
|
||||||
|
|
||||||
let mut actual_trait_ref = highlight_trait_ref(actual_trait_ref);
|
let mut actual_trait_ref = highlight_trait_ref(actual_trait_ref);
|
||||||
actual_trait_ref.highlight.maybe_highlighting_region(vid, actual_has_vid);
|
actual_trait_ref.highlight.maybe_highlighting_region(vid, actual_has_vid);
|
||||||
err.note(&{
|
|
||||||
let passive_voice = match actual_has_vid {
|
|
||||||
Some(_) => any_self_ty_has_vid,
|
|
||||||
None => true,
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut note = if same_self_type {
|
let passive_voice = match actual_has_vid {
|
||||||
format!(
|
Some(_) => any_self_ty_has_vid,
|
||||||
"...but it actually implements `{}`",
|
None => true,
|
||||||
actual_trait_ref.map(|tr| tr.print_only_trait_path()),
|
};
|
||||||
)
|
|
||||||
} else if passive_voice {
|
|
||||||
format!(
|
|
||||||
"...but `{}` is actually implemented for the type `{}`",
|
|
||||||
actual_trait_ref.map(|tr| tr.print_only_trait_path()),
|
|
||||||
actual_trait_ref.map(|tr| tr.self_ty()),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
format!(
|
|
||||||
"...but `{}` actually implements `{}`",
|
|
||||||
actual_trait_ref.map(|tr| tr.self_ty()),
|
|
||||||
actual_trait_ref.map(|tr| tr.print_only_trait_path()),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(n) = actual_has_vid {
|
let trait_path = actual_trait_ref.map(|tr| tr.print_only_trait_path());
|
||||||
let _ = write!(note, ", for some specific lifetime `'{}`", n);
|
let ty = actual_trait_ref.map(|tr| tr.self_ty()).to_string();
|
||||||
|
let has_lifetime = actual_has_vid.is_some();
|
||||||
|
let lifetime = actual_has_vid.unwrap_or_default();
|
||||||
|
|
||||||
|
let note_2 = if same_self_type {
|
||||||
|
ActualImplExplNotes::ButActuallyImplementsTrait { trait_path, has_lifetime, lifetime }
|
||||||
|
} else if passive_voice {
|
||||||
|
ActualImplExplNotes::ButActuallyImplementedForTy {
|
||||||
|
trait_path,
|
||||||
|
ty,
|
||||||
|
has_lifetime,
|
||||||
|
lifetime,
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
ActualImplExplNotes::ButActuallyTyImplements { trait_path, ty, has_lifetime, lifetime }
|
||||||
|
};
|
||||||
|
|
||||||
note
|
vec![note_1, note_2]
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
//! Error Reporting for static impl Traits.
|
//! Error Reporting for static impl Traits.
|
||||||
|
|
||||||
|
use crate::errors::{
|
||||||
|
ButCallingIntroduces, ButNeedsToSatisfy, DynTraitConstraintSuggestion, MoreTargeted,
|
||||||
|
ReqIntroducedLocations,
|
||||||
|
};
|
||||||
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
|
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
|
||||||
use crate::infer::lexical_region_resolve::RegionResolutionError;
|
use crate::infer::lexical_region_resolve::RegionResolutionError;
|
||||||
use crate::infer::{SubregionOrigin, TypeTrace};
|
use crate::infer::{SubregionOrigin, TypeTrace};
|
||||||
use crate::traits::{ObligationCauseCode, UnifyReceiverContext};
|
use crate::traits::{ObligationCauseCode, UnifyReceiverContext};
|
||||||
use rustc_data_structures::fx::FxIndexSet;
|
use rustc_data_structures::fx::FxIndexSet;
|
||||||
use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan};
|
use rustc_errors::{AddToDiagnostic, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan};
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::intravisit::{walk_ty, Visitor};
|
use rustc_hir::intravisit::{walk_ty, Visitor};
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
|
@ -53,46 +57,32 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let param = self.find_param_with_region(*sup_r, *sub_r)?;
|
let param = self.find_param_with_region(*sup_r, *sub_r)?;
|
||||||
let lifetime = if sup_r.has_name() {
|
let simple_ident = param.param.pat.simple_ident();
|
||||||
format!("lifetime `{}`", sup_r)
|
|
||||||
} else {
|
let (has_impl_path, impl_path) = match ctxt.assoc_item.container {
|
||||||
"an anonymous lifetime `'_`".to_string()
|
AssocItemContainer::TraitContainer => {
|
||||||
|
let id = ctxt.assoc_item.container_id(tcx);
|
||||||
|
(true, tcx.def_path_str(id))
|
||||||
|
}
|
||||||
|
AssocItemContainer::ImplContainer => (false, String::new()),
|
||||||
};
|
};
|
||||||
let mut err = struct_span_err!(
|
|
||||||
tcx.sess,
|
let mut err = self.tcx().sess.create_err(ButCallingIntroduces {
|
||||||
cause.span,
|
param_ty_span: param.param_ty_span,
|
||||||
E0772,
|
cause_span: cause.span,
|
||||||
"{} has {} but calling `{}` introduces an implicit `'static` lifetime \
|
has_param_name: simple_ident.is_some(),
|
||||||
requirement",
|
param_name: simple_ident.map(|x| x.to_string()).unwrap_or_default(),
|
||||||
param
|
has_lifetime: sup_r.has_name(),
|
||||||
.param
|
lifetime: sup_r.to_string(),
|
||||||
.pat
|
assoc_item: ctxt.assoc_item.name,
|
||||||
.simple_ident()
|
has_impl_path,
|
||||||
.map(|s| format!("`{}`", s))
|
impl_path,
|
||||||
.unwrap_or_else(|| "`fn` parameter".to_string()),
|
});
|
||||||
lifetime,
|
|
||||||
ctxt.assoc_item.name,
|
|
||||||
);
|
|
||||||
err.span_label(param.param_ty_span, &format!("this data with {}...", lifetime));
|
|
||||||
err.span_label(
|
|
||||||
cause.span,
|
|
||||||
&format!(
|
|
||||||
"...is used and required to live as long as `'static` here \
|
|
||||||
because of an implicit lifetime bound on the {}",
|
|
||||||
match ctxt.assoc_item.container {
|
|
||||||
AssocItemContainer::TraitContainer => {
|
|
||||||
let id = ctxt.assoc_item.container_id(tcx);
|
|
||||||
format!("`impl` of `{}`", tcx.def_path_str(id))
|
|
||||||
}
|
|
||||||
AssocItemContainer::ImplContainer => "inherent `impl`".to_string(),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) {
|
if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) {
|
||||||
let reported = err.emit();
|
let reported = err.emit();
|
||||||
return Some(reported);
|
return Some(reported);
|
||||||
} else {
|
} else {
|
||||||
err.cancel();
|
err.cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return None;
|
return None;
|
||||||
|
@ -108,25 +98,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
let sp = var_origin.span();
|
let sp = var_origin.span();
|
||||||
let return_sp = sub_origin.span();
|
let return_sp = sub_origin.span();
|
||||||
let param = self.find_param_with_region(*sup_r, *sub_r)?;
|
let param = self.find_param_with_region(*sup_r, *sub_r)?;
|
||||||
let (lifetime_name, lifetime) = if sup_r.has_name() {
|
let lifetime_name = if sup_r.has_name() { sup_r.to_string() } else { "'_".to_owned() };
|
||||||
(sup_r.to_string(), format!("lifetime `{}`", sup_r))
|
|
||||||
} else {
|
|
||||||
("'_".to_owned(), "an anonymous lifetime `'_`".to_string())
|
|
||||||
};
|
|
||||||
let param_name = param
|
|
||||||
.param
|
|
||||||
.pat
|
|
||||||
.simple_ident()
|
|
||||||
.map(|s| format!("`{}`", s))
|
|
||||||
.unwrap_or_else(|| "`fn` parameter".to_string());
|
|
||||||
let mut err = struct_span_err!(
|
|
||||||
tcx.sess,
|
|
||||||
sp,
|
|
||||||
E0759,
|
|
||||||
"{} has {} but it needs to satisfy a `'static` lifetime requirement",
|
|
||||||
param_name,
|
|
||||||
lifetime,
|
|
||||||
);
|
|
||||||
|
|
||||||
let (mention_influencer, influencer_point) =
|
let (mention_influencer, influencer_point) =
|
||||||
if sup_origin.span().overlaps(param.param_ty_span) {
|
if sup_origin.span().overlaps(param.param_ty_span) {
|
||||||
|
@ -145,7 +117,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
} else {
|
} else {
|
||||||
(!sup_origin.span().overlaps(return_sp), param.param_ty_span)
|
(!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);
|
||||||
|
|
||||||
|
@ -159,31 +130,19 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
spans.dedup_by_key(|span| (span.lo(), span.hi()));
|
spans.dedup_by_key(|span| (span.lo(), span.hi()));
|
||||||
|
|
||||||
// We try to make the output have fewer overlapping spans if possible.
|
// We try to make the output have fewer overlapping spans if possible.
|
||||||
let require_msg = if spans.is_empty() {
|
|
||||||
"...is used and required to live as long as `'static` here"
|
|
||||||
} else {
|
|
||||||
"...and is required to live as long as `'static` here"
|
|
||||||
};
|
|
||||||
let require_span =
|
let require_span =
|
||||||
if sup_origin.span().overlaps(return_sp) { sup_origin.span() } else { return_sp };
|
if sup_origin.span().overlaps(return_sp) { sup_origin.span() } else { return_sp };
|
||||||
|
|
||||||
for span in &spans {
|
let spans_empty = spans.is_empty();
|
||||||
err.span_label(*span, "...is used here...");
|
let require_as_note = spans.iter().any(|sp| sp.overlaps(return_sp) || *sp > return_sp);
|
||||||
}
|
let bound = if let SubregionOrigin::RelateParamBound(_, _, Some(bound)) = sub_origin {
|
||||||
|
Some(*bound)
|
||||||
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 {
|
} else {
|
||||||
// We don't need a note, it's already at the end, it can be shown as a `span_label`.
|
None
|
||||||
err.span_label(require_span, require_msg);
|
};
|
||||||
}
|
|
||||||
|
let mut subdiag = None;
|
||||||
|
|
||||||
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 SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = sub_origin {
|
||||||
if let ObligationCauseCode::ReturnValue(hir_id)
|
if let ObligationCauseCode::ReturnValue(hir_id)
|
||||||
| ObligationCauseCode::BlockTailExpression(hir_id) = cause.code()
|
| ObligationCauseCode::BlockTailExpression(hir_id) = cause.code()
|
||||||
|
@ -191,33 +150,50 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
let parent_id = tcx.hir().get_parent_item(*hir_id);
|
let parent_id = tcx.hir().get_parent_item(*hir_id);
|
||||||
if let Some(fn_decl) = tcx.hir().fn_decl_by_hir_id(parent_id.into()) {
|
if let Some(fn_decl) = tcx.hir().fn_decl_by_hir_id(parent_id.into()) {
|
||||||
let mut span: MultiSpan = fn_decl.output.span().into();
|
let mut span: MultiSpan = fn_decl.output.span().into();
|
||||||
|
let mut spans = Vec::new();
|
||||||
let mut add_label = true;
|
let mut add_label = true;
|
||||||
if let hir::FnRetTy::Return(ty) = fn_decl.output {
|
if let hir::FnRetTy::Return(ty) = fn_decl.output {
|
||||||
let mut v = StaticLifetimeVisitor(vec![], tcx.hir());
|
let mut v = StaticLifetimeVisitor(vec![], tcx.hir());
|
||||||
v.visit_ty(ty);
|
v.visit_ty(ty);
|
||||||
if !v.0.is_empty() {
|
if !v.0.is_empty() {
|
||||||
span = v.0.clone().into();
|
span = v.0.clone().into();
|
||||||
for sp in v.0 {
|
spans = v.0;
|
||||||
span.push_span_label(sp, "`'static` requirement introduced here");
|
|
||||||
}
|
|
||||||
add_label = false;
|
add_label = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if add_label {
|
let fn_decl_span = fn_decl.output.span();
|
||||||
span.push_span_label(
|
|
||||||
fn_decl.output.span(),
|
subdiag = Some(ReqIntroducedLocations {
|
||||||
"requirement introduced by this return type",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
span.push_span_label(cause.span, "because of this returned expression");
|
|
||||||
err.span_note(
|
|
||||||
span,
|
span,
|
||||||
"`'static` lifetime requirement introduced by the return type",
|
spans,
|
||||||
);
|
fn_decl_span,
|
||||||
|
cause_span: cause.span,
|
||||||
|
add_label,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let diag = ButNeedsToSatisfy {
|
||||||
|
sp,
|
||||||
|
influencer_point,
|
||||||
|
spans: spans.clone(),
|
||||||
|
// 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.
|
||||||
|
require_span_as_note: require_as_note.then_some(require_span),
|
||||||
|
// We don't need a note, it's already at the end, it can be shown as a `span_label`.
|
||||||
|
require_span_as_label: (!require_as_note).then_some(require_span),
|
||||||
|
req_introduces_loc: subdiag,
|
||||||
|
|
||||||
|
has_lifetime: sup_r.has_name(),
|
||||||
|
lifetime: sup_r.to_string(),
|
||||||
|
spans_empty,
|
||||||
|
bound,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut err = self.tcx().sess.create_err(diag);
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
let mut override_error_code = None;
|
let mut override_error_code = None;
|
||||||
|
@ -251,12 +227,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
if let (Some(ident), true) = (override_error_code, fn_returns.is_empty()) {
|
if let (Some(ident), true) = (override_error_code, fn_returns.is_empty()) {
|
||||||
// Provide a more targeted error code and description.
|
// Provide a more targeted error code and description.
|
||||||
err.code(rustc_errors::error_code!(E0772));
|
let retarget_subdiag = MoreTargeted { ident };
|
||||||
err.set_primary_message(&format!(
|
retarget_subdiag.add_to_diagnostic(&mut err);
|
||||||
"{} has {} but calling `{}` introduces an implicit `'static` lifetime \
|
|
||||||
requirement",
|
|
||||||
param_name, lifetime, ident,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let arg = match param.param.pat.simple_ident() {
|
let arg = match param.param.pat.simple_ident() {
|
||||||
|
@ -551,21 +523,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
let mut traits = vec![];
|
let mut traits = vec![];
|
||||||
let mut hir_v = HirTraitObjectVisitor(&mut traits, *found_did);
|
let mut hir_v = HirTraitObjectVisitor(&mut traits, *found_did);
|
||||||
hir_v.visit_ty(&self_ty);
|
hir_v.visit_ty(&self_ty);
|
||||||
for span in &traits {
|
for &span in &traits {
|
||||||
let mut multi_span: MultiSpan = vec![*span].into();
|
let subdiag = DynTraitConstraintSuggestion { span, ident };
|
||||||
multi_span
|
subdiag.add_to_diagnostic(err);
|
||||||
.push_span_label(*span, "this has an implicit `'static` lifetime requirement");
|
|
||||||
multi_span.push_span_label(
|
|
||||||
ident.span,
|
|
||||||
"calling this method introduces the `impl`'s 'static` requirement",
|
|
||||||
);
|
|
||||||
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",
|
|
||||||
" + '_",
|
|
||||||
Applicability::MaybeIncorrect,
|
|
||||||
);
|
|
||||||
suggested = true;
|
suggested = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
//! Error Reporting for `impl` items that do not match the obligations from their `trait`.
|
//! Error Reporting for `impl` items that do not match the obligations from their `trait`.
|
||||||
|
|
||||||
|
use crate::errors::{ConsiderBorrowingParamHelp, RelationshipHelp, TraitImplDiff};
|
||||||
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
|
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
|
||||||
use crate::infer::lexical_region_resolve::RegionResolutionError;
|
use crate::infer::lexical_region_resolve::RegionResolutionError;
|
||||||
use crate::infer::Subtype;
|
use crate::infer::Subtype;
|
||||||
use crate::traits::ObligationCauseCode::CompareImplItemObligation;
|
use crate::traits::ObligationCauseCode::CompareImplItemObligation;
|
||||||
use rustc_errors::{ErrorGuaranteed, MultiSpan};
|
use rustc_errors::ErrorGuaranteed;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::Res;
|
use rustc_hir::def::Res;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
|
@ -51,10 +52,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
trait_def_id: DefId,
|
trait_def_id: DefId,
|
||||||
) -> ErrorGuaranteed {
|
) -> ErrorGuaranteed {
|
||||||
let trait_sp = self.tcx().def_span(trait_def_id);
|
let trait_sp = self.tcx().def_span(trait_def_id);
|
||||||
let mut err = self
|
|
||||||
.tcx()
|
|
||||||
.sess
|
|
||||||
.struct_span_err(sp, "`impl` item signature doesn't match `trait` item signature");
|
|
||||||
|
|
||||||
// Mark all unnamed regions in the type with a number.
|
// Mark all unnamed regions in the type with a number.
|
||||||
// This diagnostic is called in response to lifetime errors, so be informative.
|
// This diagnostic is called in response to lifetime errors, so be informative.
|
||||||
|
@ -91,9 +88,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
let found =
|
let found =
|
||||||
self.cx.extract_inference_diagnostics_data(found.into(), Some(found_highlight)).name;
|
self.cx.extract_inference_diagnostics_data(found.into(), Some(found_highlight)).name;
|
||||||
|
|
||||||
err.span_label(sp, &format!("found `{}`", found));
|
|
||||||
err.span_label(trait_sp, &format!("expected `{}`", expected));
|
|
||||||
|
|
||||||
// Get the span of all the used type parameters in the method.
|
// Get the span of all the used type parameters in the method.
|
||||||
let assoc_item = self.tcx().associated_item(trait_def_id);
|
let assoc_item = self.tcx().associated_item(trait_def_id);
|
||||||
let mut visitor = TypeParamSpanVisitor { tcx: self.tcx(), types: vec![] };
|
let mut visitor = TypeParamSpanVisitor { tcx: self.tcx(), types: vec![] };
|
||||||
|
@ -110,26 +104,18 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
let mut type_param_span: MultiSpan = visitor.types.to_vec().into();
|
|
||||||
for &span in &visitor.types {
|
|
||||||
type_param_span
|
|
||||||
.push_span_label(span, "consider borrowing this type parameter in the trait");
|
|
||||||
}
|
|
||||||
|
|
||||||
err.note(&format!("expected `{}`\n found `{}`", expected, found));
|
let diag = TraitImplDiff {
|
||||||
|
sp,
|
||||||
|
trait_sp,
|
||||||
|
note: (),
|
||||||
|
param_help: ConsiderBorrowingParamHelp { spans: visitor.types.to_vec() },
|
||||||
|
rel_help: visitor.types.is_empty().then_some(RelationshipHelp),
|
||||||
|
expected,
|
||||||
|
found,
|
||||||
|
};
|
||||||
|
|
||||||
err.span_help(
|
self.tcx().sess.emit_err(diag)
|
||||||
type_param_span,
|
|
||||||
"the lifetime requirements from the `impl` do not correspond to the requirements in \
|
|
||||||
the `trait`",
|
|
||||||
);
|
|
||||||
if visitor.types.is_empty() {
|
|
||||||
err.help(
|
|
||||||
"verify the lifetime relationships in the `trait` and `impl` between the `self` \
|
|
||||||
argument, the other inputs and its output",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
err.emit()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue