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 } ;
1212use min_specialization:: check_min_specialization;
1313
1414use rustc_data_structures:: fx:: FxHashSet ;
15- use rustc_errors:: { codes:: * , struct_span_code_err } ;
15+ use rustc_errors:: codes:: * ;
1616use rustc_hir:: def:: DefKind ;
1717use rustc_hir:: def_id:: LocalDefId ;
1818use rustc_middle:: ty:: { self , TyCtxt , TypeVisitableExt } ;
19- use rustc_span:: { ErrorGuaranteed , Span , Symbol } ;
19+ use rustc_span:: ErrorGuaranteed ;
2020
2121mod 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