@@ -16,7 +16,7 @@ use crate::require_c_abi_if_c_variadic;
1616use rustc_ast:: TraitObjectSyntax ;
1717use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
1818use rustc_errors:: {
19- struct_span_err, Applicability , DiagnosticBuilder , ErrorGuaranteed , FatalError ,
19+ struct_span_err, Applicability , DiagnosticBuilder , ErrorGuaranteed , FatalError , MultiSpan ,
2020} ;
2121use rustc_hir as hir;
2222use rustc_hir:: def:: { CtorOf , DefKind , Namespace , Res } ;
@@ -653,7 +653,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
653653 span, item_def_id, item_segment
654654 ) ;
655655 if tcx. generics_of ( item_def_id) . params . is_empty ( ) {
656- self . prohibit_generics ( slice:: from_ref ( item_segment) ) ;
656+ self . prohibit_generics ( slice:: from_ref ( item_segment) . iter ( ) ) ;
657657
658658 parent_substs
659659 } else {
@@ -681,7 +681,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
681681 trait_ref : & hir:: TraitRef < ' _ > ,
682682 self_ty : Ty < ' tcx > ,
683683 ) -> ty:: TraitRef < ' tcx > {
684- self . prohibit_generics ( trait_ref. path . segments . split_last ( ) . unwrap ( ) . 1 ) ;
684+ self . prohibit_generics ( trait_ref. path . segments . split_last ( ) . unwrap ( ) . 1 . iter ( ) ) ;
685685
686686 self . ast_path_to_mono_trait_ref (
687687 trait_ref. path . span ,
@@ -784,7 +784,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
784784 let args = trait_segment. args ( ) ;
785785 let infer_args = trait_segment. infer_args ;
786786
787- self . prohibit_generics ( trait_ref. path . segments . split_last ( ) . unwrap ( ) . 1 ) ;
787+ self . prohibit_generics ( trait_ref. path . segments . split_last ( ) . unwrap ( ) . 1 . iter ( ) ) ;
788788 self . complain_about_internal_fn_trait ( span, trait_def_id, trait_segment, false ) ;
789789
790790 self . instantiate_poly_trait_ref_inner (
@@ -1796,7 +1796,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
17961796 if let Some ( variant_def) = variant_def {
17971797 if permit_variants {
17981798 tcx. check_stability ( variant_def. def_id , Some ( hir_ref_id) , span, None ) ;
1799- self . prohibit_generics ( slice:: from_ref ( assoc_segment) ) ;
1799+ self . prohibit_generics ( slice:: from_ref ( assoc_segment) . iter ( ) ) ;
18001800 return Ok ( ( qself_ty, DefKind :: Variant , variant_def. def_id ) ) ;
18011801 } else {
18021802 variant_resolution = Some ( variant_def. def_id ) ;
@@ -2017,69 +2017,79 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
20172017 self . normalize_ty ( span, tcx. mk_projection ( item_def_id, item_substs) )
20182018 }
20192019
2020- pub fn prohibit_generics < ' a , T : IntoIterator < Item = & ' a hir:: PathSegment < ' a > > > (
2020+ pub fn prohibit_generics < ' a , T : Iterator < Item = & ' a hir:: PathSegment < ' a > > + Clone > (
20212021 & self ,
20222022 segments : T ,
20232023 ) -> bool {
2024- let mut has_err = false ;
2025- for segment in segments {
2026- let ( mut err_for_lt, mut err_for_ty, mut err_for_ct) = ( false , false , false ) ;
2027- for arg in segment. args ( ) . args {
2028- let ( span, kind) = match arg {
2029- hir:: GenericArg :: Lifetime ( lt) => {
2030- if err_for_lt {
2031- continue ;
2032- }
2033- err_for_lt = true ;
2034- has_err = true ;
2035- ( lt. span , "lifetime" )
2036- }
2037- hir:: GenericArg :: Type ( ty) => {
2038- if err_for_ty {
2039- continue ;
2040- }
2041- err_for_ty = true ;
2042- has_err = true ;
2043- ( ty. span , "type" )
2044- }
2045- hir:: GenericArg :: Const ( ct) => {
2046- if err_for_ct {
2047- continue ;
2048- }
2049- err_for_ct = true ;
2050- has_err = true ;
2051- ( ct. span , "const" )
2052- }
2053- hir:: GenericArg :: Infer ( inf) => {
2054- if err_for_ty {
2055- continue ;
2056- }
2057- has_err = true ;
2058- err_for_ty = true ;
2059- ( inf. span , "generic" )
2060- }
2061- } ;
2062- let mut err = struct_span_err ! (
2063- self . tcx( ) . sess,
2064- span,
2065- E0109 ,
2066- "{} arguments are not allowed for this type" ,
2067- kind,
2068- ) ;
2069- err. span_label ( span, format ! ( "{} argument not allowed" , kind) ) ;
2070- err. emit ( ) ;
2071- if err_for_lt && err_for_ty && err_for_ct {
2072- break ;
2073- }
2024+ let args = segments. clone ( ) . flat_map ( |segment| segment. args ( ) . args ) ;
2025+
2026+ let ( lt, ty, ct, inf) =
2027+ args. clone ( ) . fold ( ( false , false , false , false ) , |( lt, ty, ct, inf) , arg| match arg {
2028+ hir:: GenericArg :: Lifetime ( _) => ( true , ty, ct, inf) ,
2029+ hir:: GenericArg :: Type ( _) => ( lt, true , ct, inf) ,
2030+ hir:: GenericArg :: Const ( _) => ( lt, ty, true , inf) ,
2031+ hir:: GenericArg :: Infer ( _) => ( lt, ty, ct, true ) ,
2032+ } ) ;
2033+ let mut emitted = false ;
2034+ if lt || ty || ct || inf {
2035+ let arg_spans: Vec < Span > = args
2036+ . map ( |arg| match arg {
2037+ hir:: GenericArg :: Lifetime ( lt) => lt. span ,
2038+ hir:: GenericArg :: Type ( ty) => ty. span ,
2039+ hir:: GenericArg :: Const ( ct) => ct. span ,
2040+ hir:: GenericArg :: Infer ( inf) => inf. span ,
2041+ } )
2042+ . collect ( ) ;
2043+
2044+ let mut types = Vec :: with_capacity ( 4 ) ;
2045+ if lt {
2046+ types. push ( "lifetime" ) ;
2047+ }
2048+ if ty {
2049+ types. push ( "type" ) ;
2050+ }
2051+ if ct {
2052+ types. push ( "const" ) ;
20742053 }
2054+ if inf {
2055+ types. push ( "generic" ) ;
2056+ }
2057+ let ( kind, s) = match types[ ..] {
2058+ [ .., _, last] => (
2059+ format ! (
2060+ "{} and `{last}`" ,
2061+ types[ ..types. len( ) - 1 ]
2062+ . iter( )
2063+ . map( |& x| x)
2064+ . intersperse( ", " )
2065+ . collect:: <String >( )
2066+ ) ,
2067+ "s" ,
2068+ ) ,
2069+ [ only] => ( format ! ( "{only}" ) , "" ) ,
2070+ [ ] => unreachable ! ( ) ,
2071+ } ;
2072+ let last_span = * arg_spans. last ( ) . unwrap ( ) ;
2073+ let span: MultiSpan = arg_spans. into ( ) ;
2074+ let mut err = struct_span_err ! (
2075+ self . tcx( ) . sess,
2076+ span,
2077+ E0109 ,
2078+ "{kind} arguments are not allowed for this type" ,
2079+ ) ;
2080+ err. span_label ( last_span, format ! ( "{kind} argument{s} not allowed" ) ) ;
2081+ err. emit ( ) ;
2082+ emitted = true ;
2083+ }
20752084
2085+ for segment in segments {
20762086 // Only emit the first error to avoid overloading the user with error messages.
20772087 if let [ binding, ..] = segment. args ( ) . bindings {
2078- has_err = true ;
20792088 Self :: prohibit_assoc_ty_binding ( self . tcx ( ) , binding. span ) ;
2089+ return true ;
20802090 }
20812091 }
2082- has_err
2092+ emitted
20832093 }
20842094
20852095 // FIXME(eddyb, varkor) handle type paths here too, not just value ones.
@@ -2229,7 +2239,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
22292239 // Check for desugared `impl Trait`.
22302240 assert ! ( ty:: is_impl_trait_defn( tcx, did) . is_none( ) ) ;
22312241 let item_segment = path. segments . split_last ( ) . unwrap ( ) ;
2232- self . prohibit_generics ( item_segment. 1 ) ;
2242+ self . prohibit_generics ( item_segment. 1 . iter ( ) ) ;
22332243 let substs = self . ast_path_substs_for_ty ( span, did, item_segment. 0 ) ;
22342244 self . normalize_ty ( span, tcx. mk_opaque ( did, substs) )
22352245 }
@@ -2242,7 +2252,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
22422252 did,
22432253 ) => {
22442254 assert_eq ! ( opt_self_ty, None ) ;
2245- self . prohibit_generics ( path. segments . split_last ( ) . unwrap ( ) . 1 ) ;
2255+ self . prohibit_generics ( path. segments . split_last ( ) . unwrap ( ) . 1 . iter ( ) ) ;
22462256 self . ast_path_to_ty ( span, did, path. segments . last ( ) . unwrap ( ) )
22472257 }
22482258 Res :: Def ( kind @ DefKind :: Variant , def_id) if permit_variants => {
@@ -2265,7 +2275,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
22652275 }
22662276 Res :: Def ( DefKind :: TyParam , def_id) => {
22672277 assert_eq ! ( opt_self_ty, None ) ;
2268- self . prohibit_generics ( path. segments ) ;
2278+ self . prohibit_generics ( path. segments . iter ( ) ) ;
22692279
22702280 let def_id = def_id. expect_local ( ) ;
22712281 let item_def_id = tcx. hir ( ) . ty_param_owner ( def_id) ;
@@ -2276,13 +2286,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
22762286 Res :: SelfTy { trait_ : Some ( _) , alias_to : None } => {
22772287 // `Self` in trait or type alias.
22782288 assert_eq ! ( opt_self_ty, None ) ;
2279- self . prohibit_generics ( path. segments ) ;
2289+ self . prohibit_generics ( path. segments . iter ( ) ) ;
22802290 tcx. types . self_param
22812291 }
22822292 Res :: SelfTy { trait_ : _, alias_to : Some ( ( def_id, forbid_generic) ) } => {
22832293 // `Self` in impl (we know the concrete type).
22842294 assert_eq ! ( opt_self_ty, None ) ;
2285- self . prohibit_generics ( path. segments ) ;
2295+ self . prohibit_generics ( path. segments . iter ( ) ) ;
22862296 // Try to evaluate any array length constants.
22872297 let ty = tcx. at ( span) . type_of ( def_id) ;
22882298 // HACK(min_const_generics): Forbid generic `Self` types
@@ -2324,7 +2334,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
23242334 }
23252335 Res :: Def ( DefKind :: AssocTy , def_id) => {
23262336 debug_assert ! ( path. segments. len( ) >= 2 ) ;
2327- self . prohibit_generics ( & path. segments [ ..path. segments . len ( ) - 2 ] ) ;
2337+ self . prohibit_generics ( path. segments [ ..path. segments . len ( ) - 2 ] . iter ( ) ) ;
23282338 self . qpath_to_ty (
23292339 span,
23302340 opt_self_ty,
@@ -2335,7 +2345,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
23352345 }
23362346 Res :: PrimTy ( prim_ty) => {
23372347 assert_eq ! ( opt_self_ty, None ) ;
2338- self . prohibit_generics ( path. segments ) ;
2348+ self . prohibit_generics ( path. segments . iter ( ) ) ;
23392349 match prim_ty {
23402350 hir:: PrimTy :: Bool => tcx. types . bool ,
23412351 hir:: PrimTy :: Char => tcx. types . char ,
0 commit comments