| use rustc_data_structures::fx::FxHashSet; |
| use rustc_errors::{ |
| codes::*, Applicability, Diag, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic, |
| EmissionGuarantee, IntoDiagArg, Level, MultiSpan, SubdiagMessageOp, Subdiagnostic, |
| }; |
| use rustc_hir as hir; |
| use rustc_hir::def_id::LocalDefId; |
| use rustc_hir::intravisit::{walk_ty, Visitor}; |
| use rustc_hir::FnRetTy; |
| use rustc_hir::GenericParamKind; |
| use rustc_macros::{Diagnostic, Subdiagnostic}; |
| use rustc_middle::ty::print::TraitRefPrintOnlyTraitPath; |
| use rustc_middle::ty::{ |
| self, print::PrintTraitRefExt as _, Binder, ClosureKind, FnSig, PolyTraitRef, Region, Ty, |
| TyCtxt, |
| }; |
| use rustc_span::symbol::{kw, Ident, Symbol}; |
| use rustc_span::{BytePos, Span}; |
| |
| use crate::error_reporting::infer::need_type_info::UnderspecifiedArgKind; |
| use crate::error_reporting::infer::nice_region_error::placeholder_error::Highlighted; |
| use crate::error_reporting::infer::ObligationCauseAsDiagArg; |
| use crate::fluent_generated as fluent; |
| |
| use std::path::PathBuf; |
| |
| pub mod note_and_explain; |
| |
| #[derive(Diagnostic)] |
| #[diag(trait_selection_dump_vtable_entries)] |
| pub struct DumpVTableEntries<'a> { |
| #[primary_span] |
| pub span: Span, |
| pub trait_ref: PolyTraitRef<'a>, |
| pub entries: String, |
| } |
| |
| #[derive(Diagnostic)] |
| #[diag(trait_selection_unable_to_construct_constant_value)] |
| pub struct UnableToConstructConstantValue<'a> { |
| #[primary_span] |
| pub span: Span, |
| pub unevaluated: ty::UnevaluatedConst<'a>, |
| } |
| |
| #[derive(Diagnostic)] |
| #[diag(trait_selection_empty_on_clause_in_rustc_on_unimplemented, code = E0232)] |
| pub struct EmptyOnClauseInOnUnimplemented { |
| #[primary_span] |
| #[label] |
| pub span: Span, |
| } |
| |
| #[derive(Diagnostic)] |
| #[diag(trait_selection_invalid_on_clause_in_rustc_on_unimplemented, code = E0232)] |
| pub struct InvalidOnClauseInOnUnimplemented { |
| #[primary_span] |
| #[label] |
| pub span: Span, |
| } |
| |
| #[derive(Diagnostic)] |
| #[diag(trait_selection_no_value_in_rustc_on_unimplemented, code = E0232)] |
| #[note] |
| pub struct NoValueInOnUnimplemented { |
| #[primary_span] |
| #[label] |
| pub span: Span, |
| } |
| |
| pub struct NegativePositiveConflict<'tcx> { |
| pub impl_span: Span, |
| pub trait_desc: ty::TraitRef<'tcx>, |
| pub self_ty: Option<Ty<'tcx>>, |
| pub negative_impl_span: Result<Span, Symbol>, |
| pub positive_impl_span: Result<Span, Symbol>, |
| } |
| |
| impl<G: EmissionGuarantee> Diagnostic<'_, G> for NegativePositiveConflict<'_> { |
| #[track_caller] |
| fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { |
| let mut diag = Diag::new(dcx, level, fluent::trait_selection_negative_positive_conflict); |
| diag.arg("trait_desc", self.trait_desc.print_only_trait_path().to_string()); |
| diag.arg("self_desc", self.self_ty.map_or_else(|| "none".to_string(), |ty| ty.to_string())); |
| diag.span(self.impl_span); |
| diag.code(E0751); |
| match self.negative_impl_span { |
| Ok(span) => { |
| diag.span_label(span, fluent::trait_selection_negative_implementation_here); |
| } |
| Err(cname) => { |
| diag.note(fluent::trait_selection_negative_implementation_in_crate); |
| diag.arg("negative_impl_cname", cname.to_string()); |
| } |
| } |
| match self.positive_impl_span { |
| Ok(span) => { |
| diag.span_label(span, fluent::trait_selection_positive_implementation_here); |
| } |
| Err(cname) => { |
| diag.note(fluent::trait_selection_positive_implementation_in_crate); |
| diag.arg("positive_impl_cname", cname.to_string()); |
| } |
| } |
| diag |
| } |
| } |
| |
| #[derive(Diagnostic)] |
| #[diag(trait_selection_inherent_projection_normalization_overflow)] |
| pub struct InherentProjectionNormalizationOverflow { |
| #[primary_span] |
| pub span: Span, |
| pub ty: String, |
| } |
| |
| pub enum AdjustSignatureBorrow { |
| Borrow { to_borrow: Vec<(Span, String)> }, |
| RemoveBorrow { remove_borrow: Vec<(Span, String)> }, |
| } |
| |
| impl Subdiagnostic for AdjustSignatureBorrow { |
| fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( |
| self, |
| diag: &mut Diag<'_, G>, |
| _f: &F, |
| ) { |
| match self { |
| AdjustSignatureBorrow::Borrow { to_borrow } => { |
| diag.arg("len", to_borrow.len()); |
| diag.multipart_suggestion_verbose( |
| fluent::trait_selection_adjust_signature_borrow, |
| to_borrow, |
| Applicability::MaybeIncorrect, |
| ); |
| } |
| AdjustSignatureBorrow::RemoveBorrow { remove_borrow } => { |
| diag.arg("len", remove_borrow.len()); |
| diag.multipart_suggestion_verbose( |
| fluent::trait_selection_adjust_signature_remove_borrow, |
| remove_borrow, |
| Applicability::MaybeIncorrect, |
| ); |
| } |
| } |
| } |
| } |
| |
| #[derive(Diagnostic)] |
| #[diag(trait_selection_closure_kind_mismatch, code = E0525)] |
| pub struct ClosureKindMismatch { |
| #[primary_span] |
| #[label] |
| pub closure_span: Span, |
| pub expected: ClosureKind, |
| pub found: ClosureKind, |
| #[label(trait_selection_closure_kind_requirement)] |
| pub cause_span: Span, |
| |
| pub trait_prefix: &'static str, |
| |
| #[subdiagnostic] |
| pub fn_once_label: Option<ClosureFnOnceLabel>, |
| |
| #[subdiagnostic] |
| pub fn_mut_label: Option<ClosureFnMutLabel>, |
| } |
| |
| #[derive(Subdiagnostic)] |
| #[label(trait_selection_closure_fn_once_label)] |
| pub struct ClosureFnOnceLabel { |
| #[primary_span] |
| pub span: Span, |
| pub place: String, |
| } |
| |
| #[derive(Subdiagnostic)] |
| #[label(trait_selection_closure_fn_mut_label)] |
| pub struct ClosureFnMutLabel { |
| #[primary_span] |
| pub span: Span, |
| pub place: String, |
| } |
| |
| #[derive(Diagnostic)] |
| #[diag(trait_selection_async_closure_not_fn)] |
| pub(crate) struct AsyncClosureNotFn { |
| #[primary_span] |
| pub span: Span, |
| pub kind: &'static str, |
| } |
| |
| #[derive(Diagnostic)] |
| #[diag(trait_selection_type_annotations_needed, code = E0282)] |
| pub struct AnnotationRequired<'a> { |
| #[primary_span] |
| pub span: Span, |
| pub source_kind: &'static str, |
| pub source_name: &'a str, |
| #[label] |
| pub failure_span: Option<Span>, |
| #[subdiagnostic] |
| pub bad_label: Option<InferenceBadError<'a>>, |
| #[subdiagnostic] |
| pub infer_subdiags: Vec<SourceKindSubdiag<'a>>, |
| #[subdiagnostic] |
| pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>, |
| #[note(trait_selection_full_type_written)] |
| pub was_written: Option<()>, |
| pub path: PathBuf, |
| } |
| |
| // Copy of `AnnotationRequired` for E0283 |
| #[derive(Diagnostic)] |
| #[diag(trait_selection_type_annotations_needed, code = E0283)] |
| pub struct AmbiguousImpl<'a> { |
| #[primary_span] |
| pub span: Span, |
| pub source_kind: &'static str, |
| pub source_name: &'a str, |
| #[label] |
| pub failure_span: Option<Span>, |
| #[subdiagnostic] |
| pub bad_label: Option<InferenceBadError<'a>>, |
| #[subdiagnostic] |
| pub infer_subdiags: Vec<SourceKindSubdiag<'a>>, |
| #[subdiagnostic] |
| pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>, |
| #[note(trait_selection_full_type_written)] |
| pub was_written: Option<()>, |
| pub path: PathBuf, |
| } |
| |
| // Copy of `AnnotationRequired` for E0284 |
| #[derive(Diagnostic)] |
| #[diag(trait_selection_type_annotations_needed, code = E0284)] |
| pub struct AmbiguousReturn<'a> { |
| #[primary_span] |
| pub span: Span, |
| pub source_kind: &'static str, |
| pub source_name: &'a str, |
| #[label] |
| pub failure_span: Option<Span>, |
| #[subdiagnostic] |
| pub bad_label: Option<InferenceBadError<'a>>, |
| #[subdiagnostic] |
| pub infer_subdiags: Vec<SourceKindSubdiag<'a>>, |
| #[subdiagnostic] |
| pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>, |
| #[note(trait_selection_full_type_written)] |
| pub was_written: Option<()>, |
| pub path: PathBuf, |
| } |
| |
| // Used when a better one isn't available |
| #[derive(Subdiagnostic)] |
| #[label(trait_selection_label_bad)] |
| pub struct InferenceBadError<'a> { |
| #[primary_span] |
| pub span: Span, |
| pub bad_kind: &'static str, |
| pub prefix_kind: UnderspecifiedArgKind, |
| pub has_parent: bool, |
| pub prefix: &'a str, |
| pub parent_prefix: &'a str, |
| pub parent_name: String, |
| pub name: String, |
| } |
| |
| #[derive(Subdiagnostic)] |
| pub enum SourceKindSubdiag<'a> { |
| #[suggestion( |
| trait_selection_source_kind_subdiag_let, |
| style = "verbose", |
| code = ": {type_name}", |
| applicability = "has-placeholders" |
| )] |
| LetLike { |
| #[primary_span] |
| span: Span, |
| name: String, |
| type_name: String, |
| kind: &'static str, |
| x_kind: &'static str, |
| prefix_kind: UnderspecifiedArgKind, |
| prefix: &'a str, |
| arg_name: String, |
| }, |
| #[label(trait_selection_source_kind_subdiag_generic_label)] |
| GenericLabel { |
| #[primary_span] |
| span: Span, |
| is_type: bool, |
| param_name: String, |
| parent_exists: bool, |
| parent_prefix: String, |
| parent_name: String, |
| }, |
| #[suggestion( |
| trait_selection_source_kind_subdiag_generic_suggestion, |
| style = "verbose", |
| code = "::<{args}>", |
| applicability = "has-placeholders" |
| )] |
| GenericSuggestion { |
| #[primary_span] |
| span: Span, |
| arg_count: usize, |
| args: String, |
| }, |
| } |
| |
| #[derive(Subdiagnostic)] |
| pub enum SourceKindMultiSuggestion<'a> { |
| #[multipart_suggestion( |
| trait_selection_source_kind_fully_qualified, |
| style = "verbose", |
| applicability = "has-placeholders" |
| )] |
| FullyQualified { |
| #[suggestion_part(code = "{def_path}({adjustment}")] |
| span_lo: Span, |
| #[suggestion_part(code = "{successor_pos}")] |
| span_hi: Span, |
| def_path: String, |
| adjustment: &'a str, |
| successor_pos: &'a str, |
| }, |
| #[multipart_suggestion( |
| trait_selection_source_kind_closure_return, |
| style = "verbose", |
| applicability = "has-placeholders" |
| )] |
| ClosureReturn { |
| #[suggestion_part(code = "{start_span_code}")] |
| start_span: Span, |
| start_span_code: String, |
| #[suggestion_part(code = " }}")] |
| end_span: Option<Span>, |
| }, |
| } |
| |
| impl<'a> SourceKindMultiSuggestion<'a> { |
| pub fn new_fully_qualified( |
| span: Span, |
| def_path: String, |
| adjustment: &'a str, |
| successor: (&'a str, BytePos), |
| ) -> Self { |
| Self::FullyQualified { |
| span_lo: span.shrink_to_lo(), |
| span_hi: span.shrink_to_hi().with_hi(successor.1), |
| def_path, |
| adjustment, |
| successor_pos: successor.0, |
| } |
| } |
| |
| pub fn new_closure_return( |
| ty_info: String, |
| data: &'a FnRetTy<'a>, |
| should_wrap_expr: Option<Span>, |
| ) -> Self { |
| let arrow = match data { |
| FnRetTy::DefaultReturn(_) => " -> ", |
| _ => "", |
| }; |
| let (start_span, start_span_code, end_span) = match should_wrap_expr { |
| Some(end_span) => (data.span(), format!("{arrow}{ty_info} {{"), Some(end_span)), |
| None => (data.span(), format!("{arrow}{ty_info}"), None), |
| }; |
| Self::ClosureReturn { start_span, start_span_code, end_span } |
| } |
| } |
| |
| pub enum RegionOriginNote<'a> { |
| Plain { |
| span: Span, |
| msg: DiagMessage, |
| }, |
| WithName { |
| span: Span, |
| msg: DiagMessage, |
| name: &'a str, |
| continues: bool, |
| }, |
| WithRequirement { |
| span: Span, |
| requirement: ObligationCauseAsDiagArg<'a>, |
| expected_found: Option<(DiagStyledString, DiagStyledString)>, |
| }, |
| } |
| |
| impl Subdiagnostic for RegionOriginNote<'_> { |
| fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( |
| self, |
| diag: &mut Diag<'_, G>, |
| _f: &F, |
| ) { |
| let mut label_or_note = |span, msg: DiagMessage| { |
| let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count(); |
| let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count(); |
| let span_is_primary = diag.span.primary_spans().iter().all(|&sp| sp == span); |
| if span_is_primary && sub_count == 0 && expanded_sub_count == 0 { |
| diag.span_label(span, msg); |
| } else if span_is_primary && expanded_sub_count == 0 { |
| diag.note(msg); |
| } else { |
| diag.span_note(span, msg); |
| } |
| }; |
| match self { |
| RegionOriginNote::Plain { span, msg } => { |
| label_or_note(span, msg); |
| } |
| RegionOriginNote::WithName { span, msg, name, continues } => { |
| label_or_note(span, msg); |
| diag.arg("name", name); |
| diag.arg("continues", continues); |
| } |
| RegionOriginNote::WithRequirement { |
| span, |
| requirement, |
| expected_found: Some((expected, found)), |
| } => { |
| label_or_note(span, fluent::trait_selection_subtype); |
| diag.arg("requirement", requirement); |
| |
| diag.note_expected_found(&"", expected, &"", found); |
| } |
| RegionOriginNote::WithRequirement { span, requirement, expected_found: None } => { |
| // FIXME: this really should be handled at some earlier stage. Our |
| // handling of region checking when type errors are present is |
| // *terrible*. |
| label_or_note(span, fluent::trait_selection_subtype_2); |
| diag.arg("requirement", requirement); |
| } |
| }; |
| } |
| } |
| |
| pub enum LifetimeMismatchLabels { |
| InRet { |
| param_span: Span, |
| ret_span: Span, |
| span: Span, |
| label_var1: Option<Ident>, |
| }, |
| Normal { |
| hir_equal: bool, |
| ty_sup: Span, |
| ty_sub: Span, |
| span: Span, |
| sup: Option<Ident>, |
| sub: Option<Ident>, |
| }, |
| } |
| |
| impl Subdiagnostic for LifetimeMismatchLabels { |
| fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( |
| self, |
| diag: &mut Diag<'_, G>, |
| _f: &F, |
| ) { |
| match self { |
| LifetimeMismatchLabels::InRet { param_span, ret_span, span, label_var1 } => { |
| diag.span_label(param_span, fluent::trait_selection_declared_different); |
| diag.span_label(ret_span, fluent::trait_selection_nothing); |
| diag.span_label(span, fluent::trait_selection_data_returned); |
| diag.arg("label_var1_exists", label_var1.is_some()); |
| diag.arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default()); |
| } |
| LifetimeMismatchLabels::Normal { |
| hir_equal, |
| ty_sup, |
| ty_sub, |
| span, |
| sup: label_var1, |
| sub: label_var2, |
| } => { |
| if hir_equal { |
| diag.span_label(ty_sup, fluent::trait_selection_declared_multiple); |
| diag.span_label(ty_sub, fluent::trait_selection_nothing); |
| diag.span_label(span, fluent::trait_selection_data_lifetime_flow); |
| } else { |
| diag.span_label(ty_sup, fluent::trait_selection_types_declared_different); |
| diag.span_label(ty_sub, fluent::trait_selection_nothing); |
| diag.span_label(span, fluent::trait_selection_data_flows); |
| diag.arg("label_var1_exists", label_var1.is_some()); |
| diag.arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default()); |
| diag.arg("label_var2_exists", label_var2.is_some()); |
| diag.arg("label_var2", label_var2.map(|x| x.to_string()).unwrap_or_default()); |
| } |
| } |
| } |
| } |
| } |
| |
| pub struct AddLifetimeParamsSuggestion<'a> { |
| pub tcx: TyCtxt<'a>, |
| pub generic_param_scope: LocalDefId, |
| pub sub: Region<'a>, |
| pub ty_sup: &'a hir::Ty<'a>, |
| pub ty_sub: &'a hir::Ty<'a>, |
| pub add_note: bool, |
| } |
| |
| impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> { |
| fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( |
| self, |
| diag: &mut Diag<'_, G>, |
| _f: &F, |
| ) { |
| let mut mk_suggestion = || { |
| let Some(anon_reg) = self.tcx.is_suitable_region(self.generic_param_scope, self.sub) |
| else { |
| return false; |
| }; |
| |
| let node = self.tcx.hir_node_by_def_id(anon_reg.def_id); |
| let is_impl = matches!(&node, hir::Node::ImplItem(_)); |
| let (generics, parent_generics) = match node { |
| hir::Node::Item(&hir::Item { |
| kind: hir::ItemKind::Fn(_, ref generics, ..), |
| .. |
| }) |
| | hir::Node::TraitItem(&hir::TraitItem { ref generics, .. }) |
| | hir::Node::ImplItem(&hir::ImplItem { ref generics, .. }) => ( |
| generics, |
| match self.tcx.parent_hir_node(self.tcx.local_def_id_to_hir_id(anon_reg.def_id)) |
| { |
| hir::Node::Item(hir::Item { |
| kind: hir::ItemKind::Trait(_, _, ref generics, ..), |
| .. |
| }) |
| | hir::Node::Item(hir::Item { |
| kind: hir::ItemKind::Impl(hir::Impl { ref generics, .. }), |
| .. |
| }) => Some(generics), |
| _ => None, |
| }, |
| ), |
| _ => return false, |
| }; |
| |
| let suggestion_param_name = generics |
| .params |
| .iter() |
| .filter(|p| matches!(p.kind, GenericParamKind::Lifetime { .. })) |
| .map(|p| p.name.ident().name) |
| .find(|i| *i != kw::UnderscoreLifetime); |
| let introduce_new = suggestion_param_name.is_none(); |
| |
| let mut default = "'a".to_string(); |
| if let Some(parent_generics) = parent_generics { |
| let used: FxHashSet<_> = parent_generics |
| .params |
| .iter() |
| .filter(|p| matches!(p.kind, GenericParamKind::Lifetime { .. })) |
| .map(|p| p.name.ident().name) |
| .filter(|i| *i != kw::UnderscoreLifetime) |
| .map(|l| l.to_string()) |
| .collect(); |
| if let Some(lt) = |
| ('a'..='z').map(|it| format!("'{it}")).find(|it| !used.contains(it)) |
| { |
| // We want a lifetime that *isn't* present in the `trait` or `impl` that assoc |
| // `fn` belongs to. We could suggest reusing one of their lifetimes, but it is |
| // likely to be an over-constraining lifetime requirement, so we always add a |
| // lifetime to the `fn`. |
| default = lt; |
| } |
| } |
| let suggestion_param_name = |
| suggestion_param_name.map(|n| n.to_string()).unwrap_or_else(|| default); |
| |
| struct ImplicitLifetimeFinder { |
| suggestions: Vec<(Span, String)>, |
| suggestion_param_name: String, |
| } |
| |
| impl<'v> Visitor<'v> for ImplicitLifetimeFinder { |
| fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) { |
| let make_suggestion = |ident: Ident| { |
| if ident.name == kw::Empty && ident.span.is_empty() { |
| format!("{}, ", self.suggestion_param_name) |
| } else if ident.name == kw::UnderscoreLifetime && ident.span.is_empty() { |
| format!("{} ", self.suggestion_param_name) |
| } else { |
| self.suggestion_param_name.clone() |
| } |
| }; |
| match ty.kind { |
| hir::TyKind::Path(hir::QPath::Resolved(_, path)) => { |
| for segment in path.segments { |
| if let Some(args) = segment.args { |
| if args.args.iter().all(|arg| { |
| matches!( |
| arg, |
| hir::GenericArg::Lifetime(lifetime) |
| if lifetime.ident.name == kw::Empty |
| ) |
| }) { |
| self.suggestions.push(( |
| segment.ident.span.shrink_to_hi(), |
| format!( |
| "<{}>", |
| args.args |
| .iter() |
| .map(|_| self.suggestion_param_name.clone()) |
| .collect::<Vec<_>>() |
| .join(", ") |
| ), |
| )); |
| } else { |
| for arg in args.args { |
| if let hir::GenericArg::Lifetime(lifetime) = arg |
| && lifetime.is_anonymous() |
| { |
| self.suggestions.push(( |
| lifetime.ident.span, |
| make_suggestion(lifetime.ident), |
| )); |
| } |
| } |
| } |
| } |
| } |
| } |
| hir::TyKind::Ref(lifetime, ..) if lifetime.is_anonymous() => { |
| self.suggestions |
| .push((lifetime.ident.span, make_suggestion(lifetime.ident))); |
| } |
| _ => {} |
| } |
| walk_ty(self, ty); |
| } |
| } |
| let mut visitor = ImplicitLifetimeFinder { |
| suggestions: vec![], |
| suggestion_param_name: suggestion_param_name.clone(), |
| }; |
| if let Some(fn_decl) = node.fn_decl() |
| && let hir::FnRetTy::Return(ty) = fn_decl.output |
| { |
| visitor.visit_ty(ty); |
| } |
| if visitor.suggestions.is_empty() { |
| // Do not suggest constraining the `&self` param, but rather the return type. |
| // If that is wrong (because it is not sufficient), a follow up error will tell the |
| // user to fix it. This way we lower the chances of *over* constraining, but still |
| // get the cake of "correctly" contrained in two steps. |
| visitor.visit_ty(self.ty_sup); |
| } |
| visitor.visit_ty(self.ty_sub); |
| if visitor.suggestions.is_empty() { |
| return false; |
| } |
| if introduce_new { |
| let new_param_suggestion = if let Some(first) = |
| generics.params.iter().find(|p| !p.name.ident().span.is_empty()) |
| { |
| (first.span.shrink_to_lo(), format!("{suggestion_param_name}, ")) |
| } else { |
| (generics.span, format!("<{suggestion_param_name}>")) |
| }; |
| |
| visitor.suggestions.push(new_param_suggestion); |
| } |
| diag.multipart_suggestion_verbose( |
| fluent::trait_selection_lifetime_param_suggestion, |
| visitor.suggestions, |
| Applicability::MaybeIncorrect, |
| ); |
| diag.arg("is_impl", is_impl); |
| diag.arg("is_reuse", !introduce_new); |
| |
| true |
| }; |
| if mk_suggestion() && self.add_note { |
| diag.note(fluent::trait_selection_lifetime_param_suggestion_elided); |
| } |
| } |
| } |
| |
| #[derive(Diagnostic)] |
| #[diag(trait_selection_lifetime_mismatch, code = E0623)] |
| pub struct LifetimeMismatch<'a> { |
| #[primary_span] |
| pub span: Span, |
| #[subdiagnostic] |
| pub labels: LifetimeMismatchLabels, |
| #[subdiagnostic] |
| pub suggestion: AddLifetimeParamsSuggestion<'a>, |
| } |
| |
| pub struct IntroducesStaticBecauseUnmetLifetimeReq { |
| pub unmet_requirements: MultiSpan, |
| pub binding_span: Span, |
| } |
| |
| impl Subdiagnostic for IntroducesStaticBecauseUnmetLifetimeReq { |
| fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( |
| mut self, |
| diag: &mut Diag<'_, G>, |
| _f: &F, |
| ) { |
| self.unmet_requirements |
| .push_span_label(self.binding_span, fluent::trait_selection_msl_introduces_static); |
| diag.span_note(self.unmet_requirements, fluent::trait_selection_msl_unmet_req); |
| } |
| } |
| |
| // FIXME(#100717): replace with a `Option<Span>` when subdiagnostic supports that |
| #[derive(Subdiagnostic)] |
| pub enum DoesNotOutliveStaticFromImpl { |
| #[note(trait_selection_does_not_outlive_static_from_impl)] |
| Spanned { |
| #[primary_span] |
| span: Span, |
| }, |
| #[note(trait_selection_does_not_outlive_static_from_impl)] |
| Unspanned, |
| } |
| |
| #[derive(Subdiagnostic)] |
| pub enum ImplicitStaticLifetimeSubdiag { |
| #[note(trait_selection_implicit_static_lifetime_note)] |
| Note { |
| #[primary_span] |
| span: Span, |
| }, |
| #[suggestion( |
| trait_selection_implicit_static_lifetime_suggestion, |
| style = "verbose", |
| code = " + '_", |
| applicability = "maybe-incorrect" |
| )] |
| Sugg { |
| #[primary_span] |
| span: Span, |
| }, |
| } |
| |
| #[derive(Diagnostic)] |
| #[diag(trait_selection_mismatched_static_lifetime)] |
| pub struct MismatchedStaticLifetime<'a> { |
| #[primary_span] |
| pub cause_span: Span, |
| #[subdiagnostic] |
| pub unmet_lifetime_reqs: IntroducesStaticBecauseUnmetLifetimeReq, |
| #[subdiagnostic] |
| pub expl: Option<note_and_explain::RegionExplanation<'a>>, |
| #[subdiagnostic] |
| pub does_not_outlive_static_from_impl: DoesNotOutliveStaticFromImpl, |
| #[subdiagnostic] |
| pub implicit_static_lifetimes: Vec<ImplicitStaticLifetimeSubdiag>, |
| } |
| |
| #[derive(Diagnostic)] |
| pub enum ExplicitLifetimeRequired<'a> { |
| #[diag(trait_selection_explicit_lifetime_required_with_ident, code = E0621)] |
| WithIdent { |
| #[primary_span] |
| #[label] |
| span: Span, |
| simple_ident: Ident, |
| named: String, |
| #[suggestion( |
| trait_selection_explicit_lifetime_required_sugg_with_ident, |
| code = "{new_ty}", |
| applicability = "unspecified" |
| )] |
| new_ty_span: Span, |
| #[skip_arg] |
| new_ty: Ty<'a>, |
| }, |
| #[diag(trait_selection_explicit_lifetime_required_with_param_type, code = E0621)] |
| WithParamType { |
| #[primary_span] |
| #[label] |
| span: Span, |
| named: String, |
| #[suggestion( |
| trait_selection_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 IntoDiagArg for TyOrSig<'_> { |
| fn into_diag_arg(self) -> rustc_errors::DiagArgValue { |
| match self { |
| TyOrSig::Ty(ty) => ty.into_diag_arg(), |
| TyOrSig::ClosureSig(sig) => sig.into_diag_arg(), |
| } |
| } |
| } |
| |
| #[derive(Subdiagnostic)] |
| pub enum ActualImplExplNotes<'tcx> { |
| #[note(trait_selection_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(trait_selection_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(trait_selection_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(trait_selection_actual_impl_expl_expected_signature_nothing)] |
| ExpectedSignatureNothing { |
| leading_ellipsis: bool, |
| ty_or_sig: TyOrSig<'tcx>, |
| trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, |
| }, |
| #[note(trait_selection_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(trait_selection_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(trait_selection_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(trait_selection_actual_impl_expl_expected_passive_nothing)] |
| ExpectedPassiveNothing { |
| leading_ellipsis: bool, |
| ty_or_sig: TyOrSig<'tcx>, |
| trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, |
| }, |
| #[note(trait_selection_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(trait_selection_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(trait_selection_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(trait_selection_actual_impl_expl_expected_other_nothing)] |
| ExpectedOtherNothing { |
| leading_ellipsis: bool, |
| ty_or_sig: TyOrSig<'tcx>, |
| trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, |
| }, |
| #[note(trait_selection_actual_impl_expl_but_actually_implements_trait)] |
| ButActuallyImplementsTrait { |
| trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, |
| has_lifetime: bool, |
| lifetime: usize, |
| }, |
| #[note(trait_selection_actual_impl_expl_but_actually_implemented_for_ty)] |
| ButActuallyImplementedForTy { |
| trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, |
| has_lifetime: bool, |
| lifetime: usize, |
| ty: String, |
| }, |
| #[note(trait_selection_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(trait_selection_trait_placeholder_mismatch)] |
| pub struct TraitPlaceholderMismatch<'tcx> { |
| #[primary_span] |
| pub span: Span, |
| #[label(trait_selection_label_satisfy)] |
| pub satisfy_span: Option<Span>, |
| #[label(trait_selection_label_where)] |
| pub where_span: Option<Span>, |
| #[label(trait_selection_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 Subdiagnostic for ConsiderBorrowingParamHelp { |
| fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( |
| self, |
| diag: &mut Diag<'_, G>, |
| f: &F, |
| ) { |
| 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<DiagMessage> is required |
| type_param_span.push_span_label(span, fluent::trait_selection_tid_consider_borrowing); |
| } |
| let msg = f(diag, fluent::trait_selection_tid_param_help.into()); |
| diag.span_help(type_param_span, msg); |
| } |
| } |
| |
| #[derive(Subdiagnostic)] |
| #[help(trait_selection_tid_rel_help)] |
| pub struct RelationshipHelp; |
| |
| #[derive(Diagnostic)] |
| #[diag(trait_selection_trait_impl_diff)] |
| pub struct TraitImplDiff { |
| #[primary_span] |
| #[label(trait_selection_found)] |
| pub sp: Span, |
| #[label(trait_selection_expected)] |
| pub trait_sp: Span, |
| #[note(trait_selection_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 Subdiagnostic for DynTraitConstraintSuggestion { |
| fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( |
| self, |
| diag: &mut Diag<'_, G>, |
| f: &F, |
| ) { |
| let mut multi_span: MultiSpan = vec![self.span].into(); |
| multi_span.push_span_label(self.span, fluent::trait_selection_dtcs_has_lifetime_req_label); |
| multi_span |
| .push_span_label(self.ident.span, fluent::trait_selection_dtcs_introduces_requirement); |
| let msg = f(diag, fluent::trait_selection_dtcs_has_req_note.into()); |
| diag.span_note(multi_span, msg); |
| let msg = f(diag, fluent::trait_selection_dtcs_suggestion.into()); |
| diag.span_suggestion_verbose( |
| self.span.shrink_to_hi(), |
| msg, |
| " + '_", |
| Applicability::MaybeIncorrect, |
| ); |
| } |
| } |
| |
| #[derive(Diagnostic)] |
| #[diag(trait_selection_but_calling_introduces, code = E0772)] |
| pub struct ButCallingIntroduces { |
| #[label(trait_selection_label1)] |
| pub param_ty_span: Span, |
| #[primary_span] |
| #[label(trait_selection_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 Subdiagnostic for ReqIntroducedLocations { |
| fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( |
| mut self, |
| diag: &mut Diag<'_, G>, |
| f: &F, |
| ) { |
| for sp in self.spans { |
| self.span.push_span_label(sp, fluent::trait_selection_ril_introduced_here); |
| } |
| |
| if self.add_label { |
| self.span.push_span_label(self.fn_decl_span, fluent::trait_selection_ril_introduced_by); |
| } |
| self.span.push_span_label(self.cause_span, fluent::trait_selection_ril_because_of); |
| let msg = f(diag, fluent::trait_selection_ril_static_introduced_by.into()); |
| diag.span_note(self.span, msg); |
| } |
| } |
| |
| pub struct MoreTargeted { |
| pub ident: Symbol, |
| } |
| |
| impl Subdiagnostic for MoreTargeted { |
| fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( |
| self, |
| diag: &mut Diag<'_, G>, |
| _f: &F, |
| ) { |
| diag.code(E0772); |
| diag.primary_message(fluent::trait_selection_more_targeted); |
| diag.arg("ident", self.ident); |
| } |
| } |
| |
| #[derive(Diagnostic)] |
| #[diag(trait_selection_but_needs_to_satisfy, code = E0759)] |
| pub struct ButNeedsToSatisfy { |
| #[primary_span] |
| pub sp: Span, |
| #[label(trait_selection_influencer)] |
| pub influencer_point: Span, |
| #[label(trait_selection_used_here)] |
| pub spans: Vec<Span>, |
| #[label(trait_selection_require)] |
| pub require_span_as_label: Option<Span>, |
| #[note(trait_selection_require)] |
| pub require_span_as_note: Option<Span>, |
| #[note(trait_selection_introduced_by_bound)] |
| pub bound: Option<Span>, |
| |
| #[subdiagnostic] |
| pub req_introduces_loc: Option<ReqIntroducedLocations>, |
| |
| pub has_param_name: bool, |
| pub param_name: String, |
| pub spans_empty: bool, |
| pub has_lifetime: bool, |
| pub lifetime: String, |
| } |
| |
| #[derive(Diagnostic)] |
| #[diag(trait_selection_outlives_content, code = E0312)] |
| pub struct OutlivesContent<'a> { |
| #[primary_span] |
| pub span: Span, |
| #[subdiagnostic] |
| pub notes: Vec<note_and_explain::RegionExplanation<'a>>, |
| } |
| |
| #[derive(Diagnostic)] |
| #[diag(trait_selection_outlives_bound, code = E0476)] |
| pub struct OutlivesBound<'a> { |
| #[primary_span] |
| pub span: Span, |
| #[subdiagnostic] |
| pub notes: Vec<note_and_explain::RegionExplanation<'a>>, |
| } |
| |
| #[derive(Diagnostic)] |
| #[diag(trait_selection_fulfill_req_lifetime, code = E0477)] |
| pub struct FulfillReqLifetime<'a> { |
| #[primary_span] |
| pub span: Span, |
| pub ty: Ty<'a>, |
| #[subdiagnostic] |
| pub note: Option<note_and_explain::RegionExplanation<'a>>, |
| } |
| |
| #[derive(Diagnostic)] |
| #[diag(trait_selection_lf_bound_not_satisfied, code = E0478)] |
| pub struct LfBoundNotSatisfied<'a> { |
| #[primary_span] |
| pub span: Span, |
| #[subdiagnostic] |
| pub notes: Vec<note_and_explain::RegionExplanation<'a>>, |
| } |
| |
| #[derive(Diagnostic)] |
| #[diag(trait_selection_ref_longer_than_data, code = E0491)] |
| pub struct RefLongerThanData<'a> { |
| #[primary_span] |
| pub span: Span, |
| pub ty: Ty<'a>, |
| #[subdiagnostic] |
| pub notes: Vec<note_and_explain::RegionExplanation<'a>>, |
| } |
| |
| #[derive(Subdiagnostic)] |
| pub enum WhereClauseSuggestions { |
| #[suggestion( |
| trait_selection_where_remove, |
| code = "", |
| applicability = "machine-applicable", |
| style = "verbose" |
| )] |
| Remove { |
| #[primary_span] |
| span: Span, |
| }, |
| #[suggestion( |
| trait_selection_where_copy_predicates, |
| code = "{space}where {trait_predicates}", |
| applicability = "machine-applicable", |
| style = "verbose" |
| )] |
| CopyPredicates { |
| #[primary_span] |
| span: Span, |
| space: &'static str, |
| trait_predicates: String, |
| }, |
| } |
| |
| #[derive(Subdiagnostic)] |
| pub enum SuggestRemoveSemiOrReturnBinding { |
| #[multipart_suggestion( |
| trait_selection_srs_remove_and_box, |
| applicability = "machine-applicable" |
| )] |
| RemoveAndBox { |
| #[suggestion_part(code = "Box::new(")] |
| first_lo: Span, |
| #[suggestion_part(code = ")")] |
| first_hi: Span, |
| #[suggestion_part(code = "Box::new(")] |
| second_lo: Span, |
| #[suggestion_part(code = ")")] |
| second_hi: Span, |
| #[suggestion_part(code = "")] |
| sp: Span, |
| }, |
| #[suggestion( |
| trait_selection_srs_remove, |
| style = "short", |
| code = "", |
| applicability = "machine-applicable" |
| )] |
| Remove { |
| #[primary_span] |
| sp: Span, |
| }, |
| #[suggestion( |
| trait_selection_srs_add, |
| style = "verbose", |
| code = "{code}", |
| applicability = "maybe-incorrect" |
| )] |
| Add { |
| #[primary_span] |
| sp: Span, |
| code: String, |
| ident: Ident, |
| }, |
| #[note(trait_selection_srs_add_one)] |
| AddOne { |
| #[primary_span] |
| spans: MultiSpan, |
| }, |
| } |
| |
| #[derive(Subdiagnostic)] |
| pub enum ConsiderAddingAwait { |
| #[help(trait_selection_await_both_futures)] |
| BothFuturesHelp, |
| #[multipart_suggestion(trait_selection_await_both_futures, applicability = "maybe-incorrect")] |
| BothFuturesSugg { |
| #[suggestion_part(code = ".await")] |
| first: Span, |
| #[suggestion_part(code = ".await")] |
| second: Span, |
| }, |
| #[suggestion( |
| trait_selection_await_future, |
| code = ".await", |
| style = "verbose", |
| applicability = "maybe-incorrect" |
| )] |
| FutureSugg { |
| #[primary_span] |
| span: Span, |
| }, |
| #[note(trait_selection_await_note)] |
| FutureSuggNote { |
| #[primary_span] |
| span: Span, |
| }, |
| #[multipart_suggestion( |
| trait_selection_await_future, |
| style = "verbose", |
| applicability = "maybe-incorrect" |
| )] |
| FutureSuggMultiple { |
| #[suggestion_part(code = ".await")] |
| spans: Vec<Span>, |
| }, |
| } |
| |
| #[derive(Diagnostic)] |
| pub enum PlaceholderRelationLfNotSatisfied { |
| #[diag(trait_selection_lf_bound_not_satisfied)] |
| HasBoth { |
| #[primary_span] |
| span: Span, |
| #[note(trait_selection_prlf_defined_with_sub)] |
| sub_span: Span, |
| #[note(trait_selection_prlf_must_outlive_with_sup)] |
| sup_span: Span, |
| sub_symbol: Symbol, |
| sup_symbol: Symbol, |
| #[note(trait_selection_prlf_known_limitation)] |
| note: (), |
| }, |
| #[diag(trait_selection_lf_bound_not_satisfied)] |
| HasSub { |
| #[primary_span] |
| span: Span, |
| #[note(trait_selection_prlf_defined_with_sub)] |
| sub_span: Span, |
| #[note(trait_selection_prlf_must_outlive_without_sup)] |
| sup_span: Span, |
| sub_symbol: Symbol, |
| #[note(trait_selection_prlf_known_limitation)] |
| note: (), |
| }, |
| #[diag(trait_selection_lf_bound_not_satisfied)] |
| HasSup { |
| #[primary_span] |
| span: Span, |
| #[note(trait_selection_prlf_defined_without_sub)] |
| sub_span: Span, |
| #[note(trait_selection_prlf_must_outlive_with_sup)] |
| sup_span: Span, |
| sup_symbol: Symbol, |
| #[note(trait_selection_prlf_known_limitation)] |
| note: (), |
| }, |
| #[diag(trait_selection_lf_bound_not_satisfied)] |
| HasNone { |
| #[primary_span] |
| span: Span, |
| #[note(trait_selection_prlf_defined_without_sub)] |
| sub_span: Span, |
| #[note(trait_selection_prlf_must_outlive_without_sup)] |
| sup_span: Span, |
| #[note(trait_selection_prlf_known_limitation)] |
| note: (), |
| }, |
| #[diag(trait_selection_lf_bound_not_satisfied)] |
| OnlyPrimarySpan { |
| #[primary_span] |
| span: Span, |
| #[note(trait_selection_prlf_known_limitation)] |
| note: (), |
| }, |
| } |
| |
| #[derive(Diagnostic)] |
| #[diag(trait_selection_opaque_captures_lifetime, code = E0700)] |
| pub struct OpaqueCapturesLifetime<'tcx> { |
| #[primary_span] |
| pub span: Span, |
| #[label] |
| pub opaque_ty_span: Span, |
| pub opaque_ty: Ty<'tcx>, |
| } |
| |
| #[derive(Subdiagnostic)] |
| pub enum FunctionPointerSuggestion<'a> { |
| #[suggestion( |
| trait_selection_fps_use_ref, |
| code = "&{fn_name}", |
| style = "verbose", |
| applicability = "maybe-incorrect" |
| )] |
| UseRef { |
| #[primary_span] |
| span: Span, |
| #[skip_arg] |
| fn_name: String, |
| }, |
| #[suggestion( |
| trait_selection_fps_remove_ref, |
| code = "{fn_name}", |
| style = "verbose", |
| applicability = "maybe-incorrect" |
| )] |
| RemoveRef { |
| #[primary_span] |
| span: Span, |
| #[skip_arg] |
| fn_name: String, |
| }, |
| #[suggestion( |
| trait_selection_fps_cast, |
| code = "&({fn_name} as {sig})", |
| style = "verbose", |
| applicability = "maybe-incorrect" |
| )] |
| CastRef { |
| #[primary_span] |
| span: Span, |
| #[skip_arg] |
| fn_name: String, |
| #[skip_arg] |
| sig: Binder<'a, FnSig<'a>>, |
| }, |
| #[suggestion( |
| trait_selection_fps_cast, |
| code = "{fn_name} as {sig}", |
| style = "verbose", |
| applicability = "maybe-incorrect" |
| )] |
| Cast { |
| #[primary_span] |
| span: Span, |
| #[skip_arg] |
| fn_name: String, |
| #[skip_arg] |
| sig: Binder<'a, FnSig<'a>>, |
| }, |
| #[suggestion( |
| trait_selection_fps_cast_both, |
| code = "{fn_name} as {found_sig}", |
| style = "hidden", |
| applicability = "maybe-incorrect" |
| )] |
| CastBoth { |
| #[primary_span] |
| span: Span, |
| #[skip_arg] |
| fn_name: String, |
| #[skip_arg] |
| found_sig: Binder<'a, FnSig<'a>>, |
| expected_sig: Binder<'a, FnSig<'a>>, |
| }, |
| #[suggestion( |
| trait_selection_fps_cast_both, |
| code = "&({fn_name} as {found_sig})", |
| style = "hidden", |
| applicability = "maybe-incorrect" |
| )] |
| CastBothRef { |
| #[primary_span] |
| span: Span, |
| #[skip_arg] |
| fn_name: String, |
| #[skip_arg] |
| found_sig: Binder<'a, FnSig<'a>>, |
| expected_sig: Binder<'a, FnSig<'a>>, |
| }, |
| } |
| |
| #[derive(Subdiagnostic)] |
| #[note(trait_selection_fps_items_are_distinct)] |
| pub struct FnItemsAreDistinct; |
| |
| #[derive(Subdiagnostic)] |
| #[note(trait_selection_fn_uniq_types)] |
| pub struct FnUniqTypes; |
| |
| #[derive(Subdiagnostic)] |
| #[help(trait_selection_fn_consider_casting)] |
| pub struct FnConsiderCasting { |
| pub casting: String, |
| } |
| |
| #[derive(Subdiagnostic)] |
| pub enum SuggestAccessingField<'a> { |
| #[suggestion( |
| trait_selection_suggest_accessing_field, |
| code = "{snippet}.{name}", |
| applicability = "maybe-incorrect" |
| )] |
| Safe { |
| #[primary_span] |
| span: Span, |
| snippet: String, |
| name: Symbol, |
| ty: Ty<'a>, |
| }, |
| #[suggestion( |
| trait_selection_suggest_accessing_field, |
| code = "unsafe {{ {snippet}.{name} }}", |
| applicability = "maybe-incorrect" |
| )] |
| Unsafe { |
| #[primary_span] |
| span: Span, |
| snippet: String, |
| name: Symbol, |
| ty: Ty<'a>, |
| }, |
| } |
| |
| #[derive(Subdiagnostic)] |
| #[multipart_suggestion(trait_selection_stp_wrap_one, applicability = "maybe-incorrect")] |
| pub struct SuggestTuplePatternOne { |
| pub variant: String, |
| #[suggestion_part(code = "{variant}(")] |
| pub span_low: Span, |
| #[suggestion_part(code = ")")] |
| pub span_high: Span, |
| } |
| |
| pub struct SuggestTuplePatternMany { |
| pub path: String, |
| pub cause_span: Span, |
| pub compatible_variants: Vec<String>, |
| } |
| |
| impl Subdiagnostic for SuggestTuplePatternMany { |
| fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( |
| self, |
| diag: &mut Diag<'_, G>, |
| f: &F, |
| ) { |
| diag.arg("path", self.path); |
| let message = f(diag, crate::fluent_generated::trait_selection_stp_wrap_many.into()); |
| diag.multipart_suggestions( |
| message, |
| self.compatible_variants.into_iter().map(|variant| { |
| vec![ |
| (self.cause_span.shrink_to_lo(), format!("{variant}(")), |
| (self.cause_span.shrink_to_hi(), ")".to_string()), |
| ] |
| }), |
| rustc_errors::Applicability::MaybeIncorrect, |
| ); |
| } |
| } |
| |
| #[derive(Subdiagnostic)] |
| pub enum TypeErrorAdditionalDiags { |
| #[suggestion( |
| trait_selection_meant_byte_literal, |
| code = "b'{code}'", |
| applicability = "machine-applicable" |
| )] |
| MeantByteLiteral { |
| #[primary_span] |
| span: Span, |
| code: String, |
| }, |
| #[suggestion( |
| trait_selection_meant_char_literal, |
| code = "'{code}'", |
| applicability = "machine-applicable" |
| )] |
| MeantCharLiteral { |
| #[primary_span] |
| span: Span, |
| code: String, |
| }, |
| #[multipart_suggestion( |
| trait_selection_meant_str_literal, |
| applicability = "machine-applicable" |
| )] |
| MeantStrLiteral { |
| #[suggestion_part(code = "\"")] |
| start: Span, |
| #[suggestion_part(code = "\"")] |
| end: Span, |
| }, |
| #[suggestion( |
| trait_selection_consider_specifying_length, |
| code = "{length}", |
| applicability = "maybe-incorrect" |
| )] |
| ConsiderSpecifyingLength { |
| #[primary_span] |
| span: Span, |
| length: u64, |
| }, |
| #[note(trait_selection_try_cannot_convert)] |
| TryCannotConvert { found: String, expected: String }, |
| #[suggestion( |
| trait_selection_tuple_trailing_comma, |
| code = ",", |
| applicability = "machine-applicable" |
| )] |
| TupleOnlyComma { |
| #[primary_span] |
| span: Span, |
| }, |
| #[multipart_suggestion( |
| trait_selection_tuple_trailing_comma, |
| applicability = "machine-applicable" |
| )] |
| TupleAlsoParentheses { |
| #[suggestion_part(code = "(")] |
| span_low: Span, |
| #[suggestion_part(code = ",)")] |
| span_high: Span, |
| }, |
| #[suggestion( |
| trait_selection_suggest_add_let_for_letchains, |
| style = "verbose", |
| applicability = "machine-applicable", |
| code = "let " |
| )] |
| AddLetForLetChains { |
| #[primary_span] |
| span: Span, |
| }, |
| } |
| |
| #[derive(Diagnostic)] |
| pub enum ObligationCauseFailureCode { |
| #[diag(trait_selection_oc_method_compat, code = E0308)] |
| MethodCompat { |
| #[primary_span] |
| span: Span, |
| #[subdiagnostic] |
| subdiags: Vec<TypeErrorAdditionalDiags>, |
| }, |
| #[diag(trait_selection_oc_type_compat, code = E0308)] |
| TypeCompat { |
| #[primary_span] |
| span: Span, |
| #[subdiagnostic] |
| subdiags: Vec<TypeErrorAdditionalDiags>, |
| }, |
| #[diag(trait_selection_oc_const_compat, code = E0308)] |
| ConstCompat { |
| #[primary_span] |
| span: Span, |
| #[subdiagnostic] |
| subdiags: Vec<TypeErrorAdditionalDiags>, |
| }, |
| #[diag(trait_selection_oc_try_compat, code = E0308)] |
| TryCompat { |
| #[primary_span] |
| span: Span, |
| #[subdiagnostic] |
| subdiags: Vec<TypeErrorAdditionalDiags>, |
| }, |
| #[diag(trait_selection_oc_match_compat, code = E0308)] |
| MatchCompat { |
| #[primary_span] |
| span: Span, |
| #[subdiagnostic] |
| subdiags: Vec<TypeErrorAdditionalDiags>, |
| }, |
| #[diag(trait_selection_oc_if_else_different, code = E0308)] |
| IfElseDifferent { |
| #[primary_span] |
| span: Span, |
| #[subdiagnostic] |
| subdiags: Vec<TypeErrorAdditionalDiags>, |
| }, |
| #[diag(trait_selection_oc_no_else, code = E0317)] |
| NoElse { |
| #[primary_span] |
| span: Span, |
| }, |
| #[diag(trait_selection_oc_no_diverge, code = E0308)] |
| NoDiverge { |
| #[primary_span] |
| span: Span, |
| #[subdiagnostic] |
| subdiags: Vec<TypeErrorAdditionalDiags>, |
| }, |
| #[diag(trait_selection_oc_fn_main_correct_type, code = E0580)] |
| FnMainCorrectType { |
| #[primary_span] |
| span: Span, |
| }, |
| #[diag(trait_selection_oc_fn_start_correct_type, code = E0308)] |
| FnStartCorrectType { |
| #[primary_span] |
| span: Span, |
| #[subdiagnostic] |
| subdiags: Vec<TypeErrorAdditionalDiags>, |
| }, |
| #[diag(trait_selection_oc_fn_lang_correct_type, code = E0308)] |
| FnLangCorrectType { |
| #[primary_span] |
| span: Span, |
| #[subdiagnostic] |
| subdiags: Vec<TypeErrorAdditionalDiags>, |
| lang_item_name: Symbol, |
| }, |
| #[diag(trait_selection_oc_intrinsic_correct_type, code = E0308)] |
| IntrinsicCorrectType { |
| #[primary_span] |
| span: Span, |
| #[subdiagnostic] |
| subdiags: Vec<TypeErrorAdditionalDiags>, |
| }, |
| #[diag(trait_selection_oc_method_correct_type, code = E0308)] |
| MethodCorrectType { |
| #[primary_span] |
| span: Span, |
| #[subdiagnostic] |
| subdiags: Vec<TypeErrorAdditionalDiags>, |
| }, |
| #[diag(trait_selection_oc_closure_selfref, code = E0644)] |
| ClosureSelfref { |
| #[primary_span] |
| span: Span, |
| }, |
| #[diag(trait_selection_oc_cant_coerce, code = E0308)] |
| CantCoerce { |
| #[primary_span] |
| span: Span, |
| #[subdiagnostic] |
| subdiags: Vec<TypeErrorAdditionalDiags>, |
| }, |
| #[diag(trait_selection_oc_generic, code = E0308)] |
| Generic { |
| #[primary_span] |
| span: Span, |
| #[subdiagnostic] |
| subdiags: Vec<TypeErrorAdditionalDiags>, |
| }, |
| } |
| |
| #[derive(Subdiagnostic)] |
| pub enum AddPreciseCapturing { |
| #[suggestion( |
| trait_selection_precise_capturing_new, |
| style = "verbose", |
| code = " + use<{concatenated_bounds}>", |
| applicability = "machine-applicable" |
| )] |
| New { |
| #[primary_span] |
| span: Span, |
| new_lifetime: Symbol, |
| concatenated_bounds: String, |
| }, |
| #[suggestion( |
| trait_selection_precise_capturing_existing, |
| style = "verbose", |
| code = "{pre}{new_lifetime}{post}", |
| applicability = "machine-applicable" |
| )] |
| Existing { |
| #[primary_span] |
| span: Span, |
| new_lifetime: Symbol, |
| pre: &'static str, |
| post: &'static str, |
| }, |
| } |
| |
| pub struct AddPreciseCapturingAndParams { |
| pub suggs: Vec<(Span, String)>, |
| pub new_lifetime: Symbol, |
| pub apit_spans: Vec<Span>, |
| } |
| |
| impl Subdiagnostic for AddPreciseCapturingAndParams { |
| fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>( |
| self, |
| diag: &mut Diag<'_, G>, |
| _f: &F, |
| ) { |
| diag.arg("new_lifetime", self.new_lifetime); |
| diag.multipart_suggestion_verbose( |
| fluent::trait_selection_precise_capturing_new_but_apit, |
| self.suggs, |
| Applicability::MaybeIncorrect, |
| ); |
| diag.span_note(self.apit_spans, fluent::trait_selection_warn_removing_apit_params); |
| } |
| } |