mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-02 10:04:23 +00:00
Migrate a trait selection error to use diagnostic translation
This commit is contained in:
parent
bc720ad36b
commit
1ca4bc966e
@ -7,6 +7,7 @@ use std::fmt::Write;
|
|||||||
|
|
||||||
use crate::query::Providers;
|
use crate::query::Providers;
|
||||||
use rustc_data_structures::fx::FxIndexMap;
|
use rustc_data_structures::fx::FxIndexMap;
|
||||||
|
use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_hir::{self as hir, LangItem};
|
use rustc_hir::{self as hir, LangItem};
|
||||||
use rustc_span::def_id::LocalDefIdMap;
|
use rustc_span::def_id::LocalDefIdMap;
|
||||||
@ -89,10 +90,18 @@ pub enum ClosureKind {
|
|||||||
FnOnce,
|
FnOnce,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> ClosureKind {
|
impl ClosureKind {
|
||||||
/// This is the initial value used when doing upvar inference.
|
/// This is the initial value used when doing upvar inference.
|
||||||
pub const LATTICE_BOTTOM: ClosureKind = ClosureKind::Fn;
|
pub const LATTICE_BOTTOM: ClosureKind = ClosureKind::Fn;
|
||||||
|
|
||||||
|
pub const fn as_str(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
ClosureKind::Fn => "Fn",
|
||||||
|
ClosureKind::FnMut => "FnMut",
|
||||||
|
ClosureKind::FnOnce => "FnOnce",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns `true` if a type that impls this closure kind
|
/// Returns `true` if a type that impls this closure kind
|
||||||
/// must also implement `other`.
|
/// must also implement `other`.
|
||||||
pub fn extends(self, other: ty::ClosureKind) -> bool {
|
pub fn extends(self, other: ty::ClosureKind) -> bool {
|
||||||
@ -115,7 +124,7 @@ impl<'tcx> ClosureKind {
|
|||||||
|
|
||||||
/// Returns the representative scalar type for this closure kind.
|
/// Returns the representative scalar type for this closure kind.
|
||||||
/// See `Ty::to_opt_closure_kind` for more details.
|
/// See `Ty::to_opt_closure_kind` for more details.
|
||||||
pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
|
pub fn to_ty<'tcx>(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
|
||||||
match self {
|
match self {
|
||||||
ClosureKind::Fn => tcx.types.i8,
|
ClosureKind::Fn => tcx.types.i8,
|
||||||
ClosureKind::FnMut => tcx.types.i16,
|
ClosureKind::FnMut => tcx.types.i16,
|
||||||
@ -124,6 +133,12 @@ impl<'tcx> ClosureKind {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl IntoDiagnosticArg for ClosureKind {
|
||||||
|
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||||
|
DiagnosticArgValue::Str(self.as_str().into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A composite describing a `Place` that is captured by a closure.
|
/// A composite describing a `Place` that is captured by a closure.
|
||||||
#[derive(PartialEq, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
|
#[derive(PartialEq, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
|
||||||
#[derive(TypeFoldable, TypeVisitable)]
|
#[derive(TypeFoldable, TypeVisitable)]
|
||||||
|
@ -2870,11 +2870,7 @@ define_print_and_forward_display! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ty::ClosureKind {
|
ty::ClosureKind {
|
||||||
match *self {
|
p!(write("{}", self.as_str()))
|
||||||
ty::ClosureKind::Fn => p!("Fn"),
|
|
||||||
ty::ClosureKind::FnMut => p!("FnMut"),
|
|
||||||
ty::ClosureKind::FnOnce => p!("FnOnce"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Predicate<'tcx> {
|
ty::Predicate<'tcx> {
|
||||||
|
@ -8,6 +8,15 @@ trait_selection_adjust_signature_remove_borrow = consider adjusting the signatur
|
|||||||
*[other] arguments
|
*[other] arguments
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait_selection_closure_fn_mut_label = closure is `FnMut` because it mutates the variable `{$place}` here
|
||||||
|
|
||||||
|
trait_selection_closure_fn_once_label = closure is `FnOnce` because it moves the variable `{$place}` out of its environment
|
||||||
|
|
||||||
|
trait_selection_closure_kind_mismatch = expected a closure that implements the `{$expected}` trait, but this closure only implements `{$found}`
|
||||||
|
.label = this closure implements `{$found}`, not `{$expected}`
|
||||||
|
|
||||||
|
trait_selection_closure_kind_requirement = the requirement to implement `{$expected}` derives from here
|
||||||
|
|
||||||
trait_selection_dump_vtable_entries = vtable entries for `{$trait_ref}`: {$entries}
|
trait_selection_dump_vtable_entries = vtable entries for `{$trait_ref}`: {$entries}
|
||||||
|
|
||||||
trait_selection_empty_on_clause_in_rustc_on_unimplemented = empty `on`-clause in `#[rustc_on_unimplemented]`
|
trait_selection_empty_on_clause_in_rustc_on_unimplemented = empty `on`-clause in `#[rustc_on_unimplemented]`
|
||||||
|
@ -4,7 +4,7 @@ use rustc_errors::{
|
|||||||
SubdiagnosticMessage,
|
SubdiagnosticMessage,
|
||||||
};
|
};
|
||||||
use rustc_macros::Diagnostic;
|
use rustc_macros::Diagnostic;
|
||||||
use rustc_middle::ty::{self, PolyTraitRef, Ty};
|
use rustc_middle::ty::{self, ClosureKind, PolyTraitRef, Ty};
|
||||||
use rustc_span::{Span, Symbol};
|
use rustc_span::{Span, Symbol};
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[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,
|
||||||
|
}
|
||||||
|
@ -7,6 +7,7 @@ use super::{
|
|||||||
ObligationCauseCode, ObligationCtxt, OutputTypeParameterMismatch, Overflow,
|
ObligationCauseCode, ObligationCtxt, OutputTypeParameterMismatch, Overflow,
|
||||||
PredicateObligation, SelectionError, TraitNotObjectSafe,
|
PredicateObligation, SelectionError, TraitNotObjectSafe,
|
||||||
};
|
};
|
||||||
|
use crate::errors::{ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch};
|
||||||
use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
|
use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
|
||||||
use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||||
use crate::infer::{self, InferCtxt};
|
use crate::infer::{self, InferCtxt};
|
||||||
@ -3142,24 +3143,15 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||||||
kind: ty::ClosureKind,
|
kind: ty::ClosureKind,
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||||
let closure_span = self.tcx.def_span(closure_def_id);
|
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,
|
closure_span,
|
||||||
format!("this closure implements `{found_kind}`, not `{kind}`"),
|
expected: kind,
|
||||||
);
|
found: found_kind,
|
||||||
err.span_label(
|
cause_span: obligation.cause.span,
|
||||||
obligation.cause.span,
|
fn_once_label: None,
|
||||||
format!("the requirement to implement `{kind}` derives from here"),
|
fn_mut_label: None,
|
||||||
);
|
};
|
||||||
|
|
||||||
// Additional context information explaining why the closure only implements
|
// Additional context information explaining why the closure only implements
|
||||||
// a particular trait.
|
// 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());
|
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)) {
|
match (found_kind, typeck_results.closure_kind_origins().get(hir_id)) {
|
||||||
(ty::ClosureKind::FnOnce, Some((span, place))) => {
|
(ty::ClosureKind::FnOnce, Some((span, place))) => {
|
||||||
err.span_label(
|
err.fn_once_label = Some(ClosureFnOnceLabel {
|
||||||
*span,
|
span: *span,
|
||||||
format!(
|
place: ty::place_to_string_for_capture(self.tcx, &place),
|
||||||
"closure is `FnOnce` because it moves the \
|
})
|
||||||
variable `{}` out of its environment",
|
|
||||||
ty::place_to_string_for_capture(self.tcx, place)
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
(ty::ClosureKind::FnMut, Some((span, place))) => {
|
(ty::ClosureKind::FnMut, Some((span, place))) => {
|
||||||
err.span_label(
|
err.fn_mut_label = Some(ClosureFnMutLabel {
|
||||||
*span,
|
span: *span,
|
||||||
format!(
|
place: ty::place_to_string_for_capture(self.tcx, &place),
|
||||||
"closure is `FnMut` because it mutates the \
|
})
|
||||||
variable `{}` here",
|
|
||||||
ty::place_to_string_for_capture(self.tcx, place)
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err
|
self.tcx.sess.create_err(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn report_type_parameter_mismatch_cyclic_type_error(
|
fn report_type_parameter_mismatch_cyclic_type_error(
|
||||||
|
Loading…
Reference in New Issue
Block a user