Skip to content

Commit 49a749a

Browse files
authored
Unrolled build for rust-lang#127966
Rollup merge of rust-lang#127966 - oli-obk:structured_diag, r=compiler-errors Use structured suggestions for unconstrained generic parameters on impl blocks I did not deduplicate with `UnusedGenericParameter`, because in contrast to type declarations, just using a generic parameter in an impl isn't enough, it must be used with the right variance and not just as part of a projection.
2 parents 0cd01aa + a0db06b commit 49a749a

File tree

3 files changed

+39
-56
lines changed

3 files changed

+39
-56
lines changed

compiler/rustc_hir_analysis/messages.ftl

+5
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,11 @@ hir_analysis_typeof_reserved_keyword_used =
519519
.suggestion = consider replacing `typeof(...)` with an actual type
520520
.label = reserved keyword
521521
522+
hir_analysis_unconstrained_generic_parameter = the {$param_def_kind} `{$param_name}` is not constrained by the impl trait, self type, or predicates
523+
.label = unconstrained {$param_def_kind}
524+
.const_param_note = expressions using a const parameter must map each value to a distinct output value
525+
.const_param_note2 = proving the result of expressions other than the parameter are unique is not supported
526+
522527
hir_analysis_unconstrained_opaque_type = unconstrained opaque type
523528
.note = `{$name}` must be used in combination with a concrete type within the same {$what}
524529

compiler/rustc_hir_analysis/src/errors.rs

+14
Original file line numberDiff line numberDiff line change
@@ -1604,6 +1604,20 @@ pub(crate) enum UnusedGenericParameterHelp {
16041604
TyAlias { param_name: Ident },
16051605
}
16061606

1607+
#[derive(Diagnostic)]
1608+
#[diag(hir_analysis_unconstrained_generic_parameter)]
1609+
pub(crate) struct UnconstrainedGenericParameter {
1610+
#[primary_span]
1611+
#[label]
1612+
pub span: Span,
1613+
pub param_name: Symbol,
1614+
pub param_def_kind: &'static str,
1615+
#[note(hir_analysis_const_param_note)]
1616+
pub const_param_note: Option<()>,
1617+
#[note(hir_analysis_const_param_note2)]
1618+
pub const_param_note2: Option<()>,
1619+
}
1620+
16071621
#[derive(Diagnostic)]
16081622
pub enum UnnamedFieldsRepr<'a> {
16091623
#[diag(hir_analysis_unnamed_fields_repr_missing_repr_c)]

compiler/rustc_hir_analysis/src/impl_wf_check.rs

+20-56
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@
88
//! specialization errors. These things can (and probably should) be
99
//! fixed, but for the moment it's easier to do these checks early.
1010
11-
use crate::constrained_generic_params as cgp;
11+
use crate::{constrained_generic_params as cgp, errors::UnconstrainedGenericParameter};
1212
use min_specialization::check_min_specialization;
1313

1414
use rustc_data_structures::fx::FxHashSet;
15-
use rustc_errors::{codes::*, struct_span_code_err};
15+
use rustc_errors::codes::*;
1616
use rustc_hir::def::DefKind;
1717
use rustc_hir::def_id::LocalDefId;
1818
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
19-
use rustc_span::{ErrorGuaranteed, Span, Symbol};
19+
use rustc_span::ErrorGuaranteed;
2020

2121
mod min_specialization;
2222

@@ -117,43 +117,34 @@ fn enforce_impl_params_are_constrained(
117117

118118
let mut res = Ok(());
119119
for param in &impl_generics.own_params {
120-
match param.kind {
120+
let err = match param.kind {
121121
// Disallow ANY unconstrained type parameters.
122122
ty::GenericParamDefKind::Type { .. } => {
123123
let param_ty = ty::ParamTy::for_def(param);
124-
if !input_parameters.contains(&cgp::Parameter::from(param_ty)) {
125-
res = Err(report_unused_parameter(
126-
tcx,
127-
tcx.def_span(param.def_id),
128-
"type",
129-
param_ty.name,
130-
));
131-
}
124+
!input_parameters.contains(&cgp::Parameter::from(param_ty))
132125
}
133126
ty::GenericParamDefKind::Lifetime => {
134127
let param_lt = cgp::Parameter::from(param.to_early_bound_region_data());
135-
if lifetimes_in_associated_types.contains(&param_lt) && // (*)
128+
lifetimes_in_associated_types.contains(&param_lt) && // (*)
136129
!input_parameters.contains(&param_lt)
137-
{
138-
res = Err(report_unused_parameter(
139-
tcx,
140-
tcx.def_span(param.def_id),
141-
"lifetime",
142-
param.name,
143-
));
144-
}
145130
}
146131
ty::GenericParamDefKind::Const { .. } => {
147132
let param_ct = ty::ParamConst::for_def(param);
148-
if !input_parameters.contains(&cgp::Parameter::from(param_ct)) {
149-
res = Err(report_unused_parameter(
150-
tcx,
151-
tcx.def_span(param.def_id),
152-
"const",
153-
param_ct.name,
154-
));
155-
}
133+
!input_parameters.contains(&cgp::Parameter::from(param_ct))
156134
}
135+
};
136+
if err {
137+
let const_param_note =
138+
matches!(param.kind, ty::GenericParamDefKind::Const { .. }).then_some(());
139+
let mut diag = tcx.dcx().create_err(UnconstrainedGenericParameter {
140+
span: tcx.def_span(param.def_id),
141+
param_name: param.name,
142+
param_def_kind: tcx.def_descr(param.def_id),
143+
const_param_note,
144+
const_param_note2: const_param_note,
145+
});
146+
diag.code(E0207);
147+
res = Err(diag.emit());
157148
}
158149
}
159150
res
@@ -177,30 +168,3 @@ fn enforce_impl_params_are_constrained(
177168
// associated types. I believe this is sound, because lifetimes
178169
// used elsewhere are not projected back out.
179170
}
180-
181-
fn report_unused_parameter(
182-
tcx: TyCtxt<'_>,
183-
span: Span,
184-
kind: &str,
185-
name: Symbol,
186-
) -> ErrorGuaranteed {
187-
let mut err = struct_span_code_err!(
188-
tcx.dcx(),
189-
span,
190-
E0207,
191-
"the {} parameter `{}` is not constrained by the \
192-
impl trait, self type, or predicates",
193-
kind,
194-
name
195-
);
196-
err.span_label(span, format!("unconstrained {kind} parameter"));
197-
if kind == "const" {
198-
err.note(
199-
"expressions using a const parameter must map each value to a distinct output value",
200-
);
201-
err.note(
202-
"proving the result of expressions other than the parameter are unique is not supported",
203-
);
204-
}
205-
err.emit()
206-
}

0 commit comments

Comments
 (0)