diff options
Diffstat (limited to 'compiler/rustc_trait_selection/src')
| -rw-r--r-- | compiler/rustc_trait_selection/src/errors.rs | 36 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs | 50 |
2 files changed, 52 insertions, 34 deletions
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index dde9e9c9ac6..c1fb287d63e 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -4,7 +4,7 @@ use rustc_errors::{ SubdiagnosticMessage, }; use rustc_macros::Diagnostic; -use rustc_middle::ty::{self, PolyTraitRef, Ty}; +use rustc_middle::ty::{self, ClosureKind, PolyTraitRef, Ty}; use rustc_span::{Span, Symbol}; #[derive(Diagnostic)] @@ -131,3 +131,37 @@ impl AddToDiagnostic for AdjustSignatureBorrow { } } } + +#[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, + + #[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, +} diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 4d85e2b6089..071d545251d 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -7,6 +7,7 @@ use super::{ ObligationCauseCode, ObligationCtxt, OutputTypeParameterMismatch, Overflow, PredicateObligation, SelectionError, TraitNotObjectSafe, }; +use crate::errors::{ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch}; use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode}; use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::infer::{self, InferCtxt}; @@ -3142,24 +3143,15 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { kind: ty::ClosureKind, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let closure_span = self.tcx.def_span(closure_def_id); - let mut err = struct_span_err!( - self.tcx.sess, - closure_span, - E0525, - "expected a closure that implements the `{}` trait, \ - but this closure only implements `{}`", - kind, - found_kind - ); - err.span_label( + let mut err = ClosureKindMismatch { closure_span, - format!("this closure implements `{found_kind}`, not `{kind}`"), - ); - err.span_label( - obligation.cause.span, - format!("the requirement to implement `{kind}` derives from here"), - ); + expected: kind, + found: found_kind, + cause_span: obligation.cause.span, + fn_once_label: None, + fn_mut_label: None, + }; // Additional context information explaining why the closure only implements // a particular trait. @@ -3167,30 +3159,22 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let hir_id = self.tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local()); match (found_kind, typeck_results.closure_kind_origins().get(hir_id)) { (ty::ClosureKind::FnOnce, Some((span, place))) => { - err.span_label( - *span, - format!( - "closure is `FnOnce` because it moves the \ - variable `{}` out of its environment", - ty::place_to_string_for_capture(self.tcx, place) - ), - ); + err.fn_once_label = Some(ClosureFnOnceLabel { + span: *span, + place: ty::place_to_string_for_capture(self.tcx, &place), + }) } (ty::ClosureKind::FnMut, Some((span, place))) => { - err.span_label( - *span, - format!( - "closure is `FnMut` because it mutates the \ - variable `{}` here", - ty::place_to_string_for_capture(self.tcx, place) - ), - ); + err.fn_mut_label = Some(ClosureFnMutLabel { + span: *span, + place: ty::place_to_string_for_capture(self.tcx, &place), + }) } _ => {} } } - err + self.tcx.sess.create_err(err) } fn report_type_parameter_mismatch_cyclic_type_error( |
