@@ -194,6 +194,39 @@ enum ResolutionError<'a> {
194194 ConstParamDependentOnTypeParam ,
195195}
196196
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+
197230/// Combines an error with provided span and emits it.
198231///
199232/// 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<'_>,
210243 -> DiagnosticBuilder < ' sess > {
211244 match resolution_error {
212245 ResolutionError :: GenericParamsFromOuterFunction ( outer_res) => {
246+ let msg = resolver. scope . generic_param_resolution_error_message ( ) ;
213247 let mut err = struct_span_err ! ( resolver. session,
214248 span,
215249 E0401 ,
216- "can't use generic parameters from outer function" ,
250+ "can't use generic parameters {}" ,
251+ msg,
217252 ) ;
218- err. span_label ( span, format ! ( "use of generic parameter from outer function" ) ) ;
253+ err. span_label ( span, & format ! ( "use of generic parameter {}" , msg ) ) ;
219254
220255 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+ } ;
221261 match outer_res {
222262 Res :: SelfTy ( maybe_trait_defid, maybe_impl_defid) => {
223263 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<'_>,
241281 } ,
242282 Res :: Def ( DefKind :: TyParam , def_id) => {
243283 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+ ) ) ;
245288 }
246289 }
247290 Res :: Def ( DefKind :: ConstParam , def_id) => {
248291 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+ ) ) ;
250296 }
251297 }
252298 _ => {
@@ -258,7 +304,14 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>,
258304 // Try to retrieve the span of the function signature and generate a new message with
259305 // a local type or const parameter.
260306 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) {
262315 // Suggest the modification to the user
263316 err. span_suggestion (
264317 sugg_span,
@@ -267,6 +320,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>,
267320 Applicability :: MachineApplicable ,
268321 ) ;
269322 } else if let Some ( sp) = cm. generate_fn_name_span ( span) {
323+ // FIXME: needs to use proper scope navigation to avoid errors like #45447
270324 err. span_label ( sp,
271325 format ! ( "try adding a local generic parameter in this method instead" ) ) ;
272326 } else {
@@ -1688,6 +1742,9 @@ pub struct Resolver<'a> {
16881742 current_type_ascription : Vec < Span > ,
16891743
16901744 injected_crate : Option < Module < ' a > > ,
1745+
1746+ /// Used for more accurate error when using type parameters in a associated items.
1747+ scope : CurrentScope ,
16911748}
16921749
16931750/// Nothing really interesting here; it just provides memory for the rest of the crate.
@@ -2013,6 +2070,7 @@ impl<'a> Resolver<'a> {
20132070 unused_macros : FxHashSet :: default ( ) ,
20142071 current_type_ascription : Vec :: new ( ) ,
20152072 injected_crate : None ,
2073+ scope : CurrentScope :: Other ,
20162074 }
20172075 }
20182076
@@ -2520,6 +2578,8 @@ impl<'a> Resolver<'a> {
25202578
25212579 match item. node {
25222580 ItemKind :: Ty ( _, ref generics) => {
2581+ let scope = self . scope ;
2582+ self . scope = CurrentScope :: Type ;
25232583 self . with_current_self_item ( item, |this| {
25242584 this. with_generic_param_rib ( HasGenericParams ( generics, ItemRibKind ) , |this| {
25252585 let item_def_id = this. definitions . local_def_id ( item. id ) ;
@@ -2528,6 +2588,7 @@ impl<'a> Resolver<'a> {
25282588 } )
25292589 } )
25302590 } ) ;
2591+ self . scope = scope;
25312592 }
25322593
25332594 ItemKind :: Existential ( _, ref generics) |
@@ -2611,13 +2672,20 @@ impl<'a> Resolver<'a> {
26112672
26122673 ItemKind :: Static ( ref ty, _, ref expr) |
26132674 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+ } ;
26142681 debug ! ( "resolve_item ItemKind::Const" ) ;
26152682 self . with_item_rib ( |this| {
26162683 this. visit_ty ( ty) ;
26172684 this. with_constant_rib ( |this| {
26182685 this. visit_expr ( expr) ;
26192686 } ) ;
26202687 } ) ;
2688+ self . scope = scope;
26212689 }
26222690
26232691 ItemKind :: Use ( ref use_tree) => {
0 commit comments