mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
Use structured suggestions for unconstrained generic parameters on impl blocks
This commit is contained in:
parent
3d68afc9e8
commit
a0db06bdeb
@ -519,6 +519,11 @@ hir_analysis_typeof_reserved_keyword_used =
|
||||
.suggestion = consider replacing `typeof(...)` with an actual type
|
||||
.label = reserved keyword
|
||||
|
||||
hir_analysis_unconstrained_generic_parameter = the {$param_def_kind} `{$param_name}` is not constrained by the impl trait, self type, or predicates
|
||||
.label = unconstrained {$param_def_kind}
|
||||
.const_param_note = expressions using a const parameter must map each value to a distinct output value
|
||||
.const_param_note2 = proving the result of expressions other than the parameter are unique is not supported
|
||||
|
||||
hir_analysis_unconstrained_opaque_type = unconstrained opaque type
|
||||
.note = `{$name}` must be used in combination with a concrete type within the same {$what}
|
||||
|
||||
|
@ -1604,6 +1604,20 @@ pub(crate) enum UnusedGenericParameterHelp {
|
||||
TyAlias { param_name: Ident },
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_unconstrained_generic_parameter)]
|
||||
pub(crate) struct UnconstrainedGenericParameter {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
pub param_name: Symbol,
|
||||
pub param_def_kind: &'static str,
|
||||
#[note(hir_analysis_const_param_note)]
|
||||
pub const_param_note: Option<()>,
|
||||
#[note(hir_analysis_const_param_note2)]
|
||||
pub const_param_note2: Option<()>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
pub enum UnnamedFieldsRepr<'a> {
|
||||
#[diag(hir_analysis_unnamed_fields_repr_missing_repr_c)]
|
||||
|
@ -8,15 +8,15 @@
|
||||
//! specialization errors. These things can (and probably should) be
|
||||
//! fixed, but for the moment it's easier to do these checks early.
|
||||
|
||||
use crate::constrained_generic_params as cgp;
|
||||
use crate::{constrained_generic_params as cgp, errors::UnconstrainedGenericParameter};
|
||||
use min_specialization::check_min_specialization;
|
||||
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::{codes::*, struct_span_code_err};
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
|
||||
use rustc_span::{ErrorGuaranteed, Span, Symbol};
|
||||
use rustc_span::ErrorGuaranteed;
|
||||
|
||||
mod min_specialization;
|
||||
|
||||
@ -117,43 +117,34 @@ fn enforce_impl_params_are_constrained(
|
||||
|
||||
let mut res = Ok(());
|
||||
for param in &impl_generics.own_params {
|
||||
match param.kind {
|
||||
let err = match param.kind {
|
||||
// Disallow ANY unconstrained type parameters.
|
||||
ty::GenericParamDefKind::Type { .. } => {
|
||||
let param_ty = ty::ParamTy::for_def(param);
|
||||
if !input_parameters.contains(&cgp::Parameter::from(param_ty)) {
|
||||
res = Err(report_unused_parameter(
|
||||
tcx,
|
||||
tcx.def_span(param.def_id),
|
||||
"type",
|
||||
param_ty.name,
|
||||
));
|
||||
}
|
||||
!input_parameters.contains(&cgp::Parameter::from(param_ty))
|
||||
}
|
||||
ty::GenericParamDefKind::Lifetime => {
|
||||
let param_lt = cgp::Parameter::from(param.to_early_bound_region_data());
|
||||
if lifetimes_in_associated_types.contains(¶m_lt) && // (*)
|
||||
lifetimes_in_associated_types.contains(¶m_lt) && // (*)
|
||||
!input_parameters.contains(¶m_lt)
|
||||
{
|
||||
res = Err(report_unused_parameter(
|
||||
tcx,
|
||||
tcx.def_span(param.def_id),
|
||||
"lifetime",
|
||||
param.name,
|
||||
));
|
||||
}
|
||||
}
|
||||
ty::GenericParamDefKind::Const { .. } => {
|
||||
let param_ct = ty::ParamConst::for_def(param);
|
||||
if !input_parameters.contains(&cgp::Parameter::from(param_ct)) {
|
||||
res = Err(report_unused_parameter(
|
||||
tcx,
|
||||
tcx.def_span(param.def_id),
|
||||
"const",
|
||||
param_ct.name,
|
||||
));
|
||||
}
|
||||
!input_parameters.contains(&cgp::Parameter::from(param_ct))
|
||||
}
|
||||
};
|
||||
if err {
|
||||
let const_param_note =
|
||||
matches!(param.kind, ty::GenericParamDefKind::Const { .. }).then_some(());
|
||||
let mut diag = tcx.dcx().create_err(UnconstrainedGenericParameter {
|
||||
span: tcx.def_span(param.def_id),
|
||||
param_name: param.name,
|
||||
param_def_kind: tcx.def_descr(param.def_id),
|
||||
const_param_note,
|
||||
const_param_note2: const_param_note,
|
||||
});
|
||||
diag.code(E0207);
|
||||
res = Err(diag.emit());
|
||||
}
|
||||
}
|
||||
res
|
||||
@ -177,30 +168,3 @@ fn enforce_impl_params_are_constrained(
|
||||
// associated types. I believe this is sound, because lifetimes
|
||||
// used elsewhere are not projected back out.
|
||||
}
|
||||
|
||||
fn report_unused_parameter(
|
||||
tcx: TyCtxt<'_>,
|
||||
span: Span,
|
||||
kind: &str,
|
||||
name: Symbol,
|
||||
) -> ErrorGuaranteed {
|
||||
let mut err = struct_span_code_err!(
|
||||
tcx.dcx(),
|
||||
span,
|
||||
E0207,
|
||||
"the {} parameter `{}` is not constrained by the \
|
||||
impl trait, self type, or predicates",
|
||||
kind,
|
||||
name
|
||||
);
|
||||
err.span_label(span, format!("unconstrained {kind} parameter"));
|
||||
if kind == "const" {
|
||||
err.note(
|
||||
"expressions using a const parameter must map each value to a distinct output value",
|
||||
);
|
||||
err.note(
|
||||
"proving the result of expressions other than the parameter are unique is not supported",
|
||||
);
|
||||
}
|
||||
err.emit()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user