8
8
//! specialization errors. These things can (and probably should) be
9
9
//! fixed, but for the moment it's easier to do these checks early.
10
10
11
- use crate :: constrained_generic_params as cgp;
11
+ use crate :: { constrained_generic_params as cgp, errors :: UnconstrainedGenericParameter } ;
12
12
use min_specialization:: check_min_specialization;
13
13
14
14
use rustc_data_structures:: fx:: FxHashSet ;
15
- use rustc_errors:: { codes:: * , struct_span_code_err } ;
15
+ use rustc_errors:: codes:: * ;
16
16
use rustc_hir:: def:: DefKind ;
17
17
use rustc_hir:: def_id:: LocalDefId ;
18
18
use rustc_middle:: ty:: { self , TyCtxt , TypeVisitableExt } ;
19
- use rustc_span:: { ErrorGuaranteed , Span , Symbol } ;
19
+ use rustc_span:: ErrorGuaranteed ;
20
20
21
21
mod min_specialization;
22
22
@@ -117,43 +117,34 @@ fn enforce_impl_params_are_constrained(
117
117
118
118
let mut res = Ok ( ( ) ) ;
119
119
for param in & impl_generics. own_params {
120
- match param. kind {
120
+ let err = match param. kind {
121
121
// Disallow ANY unconstrained type parameters.
122
122
ty:: GenericParamDefKind :: Type { .. } => {
123
123
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) )
132
125
}
133
126
ty:: GenericParamDefKind :: Lifetime => {
134
127
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) && // (*)
136
129
!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
- }
145
130
}
146
131
ty:: GenericParamDefKind :: Const { .. } => {
147
132
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) )
156
134
}
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 ( ) ) ;
157
148
}
158
149
}
159
150
res
@@ -177,30 +168,3 @@ fn enforce_impl_params_are_constrained(
177
168
// associated types. I believe this is sound, because lifetimes
178
169
// used elsewhere are not projected back out.
179
170
}
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