@@ -194,6 +194,39 @@ enum ResolutionError<'a> {
194
194
ConstParamDependentOnTypeParam ,
195
195
}
196
196
197
+ #[ derive( Clone , Copy ) ]
198
+ enum CurrentScope {
199
+ Const ,
200
+ Static ,
201
+ Type ,
202
+ Other ,
203
+ }
204
+
205
+ impl CurrentScope {
206
+ fn is_other ( & self ) -> bool {
207
+ match self {
208
+ CurrentScope :: Other => true ,
209
+ _ => false ,
210
+ }
211
+ }
212
+
213
+ fn description ( & self ) -> & ' static str {
214
+ match self {
215
+ Self :: Const => "`const` associated item" ,
216
+ Self :: Static => "`static` associated item" ,
217
+ Self :: Type => "associated type" ,
218
+ Self :: Other => "outer function" ,
219
+ }
220
+ }
221
+
222
+ fn generic_param_resolution_error_message ( & self ) -> String {
223
+ match self {
224
+ Self :: Other => format ! ( "from {}" , self . description( ) ) ,
225
+ _ => format ! ( "in {}" , self . description( ) ) ,
226
+ }
227
+ }
228
+ }
229
+
197
230
/// Combines an error with provided span and emits it.
198
231
///
199
232
/// This takes the error provided, combines it with the span and any additional spans inside the
@@ -210,14 +243,21 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>,
210
243
-> DiagnosticBuilder < ' sess > {
211
244
match resolution_error {
212
245
ResolutionError :: GenericParamsFromOuterFunction ( outer_res) => {
246
+ let msg = resolver. scope . generic_param_resolution_error_message ( ) ;
213
247
let mut err = struct_span_err ! ( resolver. session,
214
248
span,
215
249
E0401 ,
216
- "can't use generic parameters from outer function" ,
250
+ "can't use generic parameters {}" ,
251
+ msg,
217
252
) ;
218
- err. span_label ( span, format ! ( "use of generic parameter from outer function" ) ) ;
253
+ err. span_label ( span, & format ! ( "use of generic parameter {}" , msg ) ) ;
219
254
220
255
let cm = resolver. session . source_map ( ) ;
256
+ let type_param_extra_msg = if resolver. scope . is_other ( ) {
257
+ "from outer function "
258
+ } else {
259
+ ""
260
+ } ;
221
261
match outer_res {
222
262
Res :: SelfTy ( maybe_trait_defid, maybe_impl_defid) => {
223
263
if let Some ( impl_span) = maybe_impl_defid. and_then ( |def_id| {
@@ -241,12 +281,18 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>,
241
281
} ,
242
282
Res :: Def ( DefKind :: TyParam , def_id) => {
243
283
if let Some ( span) = resolver. definitions . opt_span ( def_id) {
244
- err. span_label ( span, "type parameter from outer function" ) ;
284
+ err. span_label ( span, format ! (
285
+ "type parameter {}being used" ,
286
+ type_param_extra_msg,
287
+ ) ) ;
245
288
}
246
289
}
247
290
Res :: Def ( DefKind :: ConstParam , def_id) => {
248
291
if let Some ( span) = resolver. definitions . opt_span ( def_id) {
249
- err. span_label ( span, "const parameter from outer function" ) ;
292
+ err. span_label ( span, format ! (
293
+ "const parameter {}being used" ,
294
+ type_param_extra_msg,
295
+ ) ) ;
250
296
}
251
297
}
252
298
_ => {
@@ -258,7 +304,14 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>,
258
304
// Try to retrieve the span of the function signature and generate a new message with
259
305
// a local type or const parameter.
260
306
let sugg_msg = & format ! ( "try using a local generic parameter instead" ) ;
261
- if let Some ( ( sugg_span, new_snippet) ) = cm. generate_local_type_param_snippet ( span) {
307
+ if !resolver. scope . is_other ( ) {
308
+ err. help ( & format ! (
309
+ "{} need a type instead of a generic parameter" ,
310
+ resolver. scope. description( ) ,
311
+ ) ) ;
312
+ } else if let Some (
313
+ ( sugg_span, new_snippet) ,
314
+ ) = cm. generate_local_type_param_snippet ( span) {
262
315
// Suggest the modification to the user
263
316
err. span_suggestion (
264
317
sugg_span,
@@ -267,6 +320,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>,
267
320
Applicability :: MachineApplicable ,
268
321
) ;
269
322
} else if let Some ( sp) = cm. generate_fn_name_span ( span) {
323
+ // FIXME: needs to use proper scope navigation to avoid errors like #45447
270
324
err. span_label ( sp,
271
325
format ! ( "try adding a local generic parameter in this method instead" ) ) ;
272
326
} else {
@@ -1688,6 +1742,9 @@ pub struct Resolver<'a> {
1688
1742
current_type_ascription : Vec < Span > ,
1689
1743
1690
1744
injected_crate : Option < Module < ' a > > ,
1745
+
1746
+ /// Used for more accurate error when using type parameters in a associated items.
1747
+ scope : CurrentScope ,
1691
1748
}
1692
1749
1693
1750
/// Nothing really interesting here; it just provides memory for the rest of the crate.
@@ -2013,6 +2070,7 @@ impl<'a> Resolver<'a> {
2013
2070
unused_macros : FxHashSet :: default ( ) ,
2014
2071
current_type_ascription : Vec :: new ( ) ,
2015
2072
injected_crate : None ,
2073
+ scope : CurrentScope :: Other ,
2016
2074
}
2017
2075
}
2018
2076
@@ -2520,6 +2578,8 @@ impl<'a> Resolver<'a> {
2520
2578
2521
2579
match item. node {
2522
2580
ItemKind :: Ty ( _, ref generics) => {
2581
+ let scope = self . scope ;
2582
+ self . scope = CurrentScope :: Type ;
2523
2583
self . with_current_self_item ( item, |this| {
2524
2584
this. with_generic_param_rib ( HasGenericParams ( generics, ItemRibKind ) , |this| {
2525
2585
let item_def_id = this. definitions . local_def_id ( item. id ) ;
@@ -2528,6 +2588,7 @@ impl<'a> Resolver<'a> {
2528
2588
} )
2529
2589
} )
2530
2590
} ) ;
2591
+ self . scope = scope;
2531
2592
}
2532
2593
2533
2594
ItemKind :: Existential ( _, ref generics) |
@@ -2611,13 +2672,20 @@ impl<'a> Resolver<'a> {
2611
2672
2612
2673
ItemKind :: Static ( ref ty, _, ref expr) |
2613
2674
ItemKind :: Const ( ref ty, ref expr) => {
2675
+ let scope = self . scope ;
2676
+ self . scope = match item. node {
2677
+ ItemKind :: Static ( ..) => CurrentScope :: Static ,
2678
+ ItemKind :: Const ( ..) => CurrentScope :: Const ,
2679
+ _ => unreachable ! ( ) ,
2680
+ } ;
2614
2681
debug ! ( "resolve_item ItemKind::Const" ) ;
2615
2682
self . with_item_rib ( |this| {
2616
2683
this. visit_ty ( ty) ;
2617
2684
this. with_constant_rib ( |this| {
2618
2685
this. visit_expr ( expr) ;
2619
2686
} ) ;
2620
2687
} ) ;
2688
+ self . scope = scope;
2621
2689
}
2622
2690
2623
2691
ItemKind :: Use ( ref use_tree) => {
0 commit comments