@@ -180,20 +180,22 @@ fn parse_subcommand(
180180 result : & mut Args ,
181181 target_list : & TargetList ,
182182 config : & CargoConfig ,
183- parent : Option < & str > ,
183+ seen : & mut Vec < String > ,
184184) -> Result < ( ) > {
185- if parent == Some ( & arg) {
185+ if seen. iter ( ) . position ( |x| x == & arg) . is_some ( ) {
186+ let chain = seen. join ( " -> " ) ;
186187 MessageInfo :: default ( ) . fatal (
187- format_args ! ( "alias {arg} has unresolvable recursive definition: {arg } -> {arg}" ) ,
188+ format_args ! ( "alias {arg} has unresolvable recursive definition: {chain } -> {arg}" ) ,
188189 shell:: ERROR_CODE ,
189190 ) ;
190191 }
191192 let subcommand = Subcommand :: from ( arg. as_ref ( ) ) ;
192193 if subcommand == Subcommand :: Other {
193194 if let Some ( alias) = config. alias ( & arg) ? {
195+ seen. push ( arg) ;
194196 let mut iter = alias. iter ( ) . cloned ( ) ;
195197 while let Some ( subarg) = iter. next ( ) {
196- parse_arg ( subarg, result, target_list, config, & mut iter, Some ( & arg ) ) ?;
198+ parse_arg ( subarg, result, target_list, config, seen , & mut iter) ?;
197199 }
198200 return Ok ( ( ) ) ;
199201 }
@@ -212,8 +214,8 @@ fn parse_arg(
212214 result : & mut Args ,
213215 target_list : & TargetList ,
214216 config : & CargoConfig ,
217+ seen : & mut Vec < String > ,
215218 iter : & mut impl Iterator < Item = String > ,
216- parent_subcommand : Option < & str > ,
217219) -> Result < ( ) > {
218220 if arg. is_empty ( ) {
219221 return Ok ( ( ) ) ;
@@ -310,7 +312,7 @@ fn parse_arg(
310312 }
311313 }
312314 } else if ( !arg. starts_with ( '-' ) || arg == "--list" ) && result. subcommand . is_none ( ) {
313- parse_subcommand ( arg, result, target_list, config, parent_subcommand ) ?;
315+ parse_subcommand ( arg, result, target_list, config, seen ) ?;
314316 } else {
315317 result. all . push ( arg. clone ( ) ) ;
316318 }
@@ -321,8 +323,9 @@ fn parse_arg(
321323pub fn parse ( target_list : & TargetList , config : & CargoConfig ) -> Result < Args > {
322324 let mut result = Args :: default ( ) ;
323325 let mut args = env:: args ( ) . skip ( 1 ) ;
326+ let mut seen = vec ! [ ] ;
324327 while let Some ( arg) = args. next ( ) {
325- parse_arg ( arg, & mut result, target_list, config, & mut args , None ) ?;
328+ parse_arg ( arg, & mut result, target_list, config, & mut seen , & mut args ) ?;
326329 }
327330
328331 Ok ( result)
@@ -334,6 +337,12 @@ mod tests {
334337 use crate :: rustc;
335338 use crate :: shell:: Verbosity ;
336339
340+ macro_rules! s {
341+ ( $s: literal) => {
342+ $s. to_owned( )
343+ } ;
344+ }
345+
337346 #[ test]
338347 fn is_verbose_test ( ) {
339348 assert ! ( !is_verbose( "b" ) ) ;
@@ -346,6 +355,23 @@ mod tests {
346355 assert ! ( !is_verbose( "-version" ) ) ;
347356 }
348357
358+ #[ test]
359+ fn test_nested_alias ( ) {
360+ let mut args = Args :: default ( ) ;
361+ let target_list =
362+ rustc:: target_list ( & mut Verbosity :: Quiet . into ( ) ) . expect ( "failed to get target list" ) ;
363+ let config = CargoConfig :: new ( None ) ;
364+
365+ parse_subcommand (
366+ "g" . to_owned ( ) ,
367+ & mut args,
368+ & target_list,
369+ & config,
370+ & mut vec ! [ s!( "x" ) , s!( "y" ) , s!( "z" ) , s!( "a" ) , s!( "e" ) , s!( "f" ) ] ,
371+ )
372+ . ok ( ) ;
373+ }
374+
349375 #[ test]
350376 #[ should_panic]
351377 fn test_recursive_alias ( ) {
@@ -359,7 +385,25 @@ mod tests {
359385 & mut args,
360386 & target_list,
361387 & config,
362- Some ( "recursive" ) ,
388+ & mut vec ! [ s!( "recursive" ) ] ,
389+ )
390+ . ok ( ) ;
391+ }
392+
393+ #[ test]
394+ #[ should_panic]
395+ fn test_nested_recursive_alias ( ) {
396+ let mut args = Args :: default ( ) ;
397+ let target_list =
398+ rustc:: target_list ( & mut Verbosity :: Quiet . into ( ) ) . expect ( "failed to get target list" ) ;
399+ let config = CargoConfig :: new ( None ) ;
400+
401+ parse_subcommand (
402+ "y" . to_owned ( ) ,
403+ & mut args,
404+ & target_list,
405+ & config,
406+ & mut vec ! [ s!( "x" ) , s!( "y" ) , s!( "z" ) , s!( "a" ) ] ,
363407 )
364408 . ok ( ) ;
365409 }
0 commit comments