@@ -416,8 +416,25 @@ impl FromStr for RustTarget {
416416 return Ok ( Self :: Nightly ) ;
417417 }
418418
419- let Some ( ( major_str, tail) ) = input. split_once ( '.' ) else {
420- return Err ( invalid_input ( input, "accepted values are of the form \" 1.71\" , \" 1.71.1\" or \" nightly\" ." ) ) ;
419+ let ( version, pre_release) =
420+ if let Some ( ( version, pre_release) ) = input. split_once ( '-' ) {
421+ ( version, pre_release)
422+ } else {
423+ ( input, "" )
424+ } ;
425+
426+ const MSG : & str = r#"accepted values are of the form "1.71", "1.71.1" , "1.71.1-beta", "1.71.1-beta.1", "1.71.1-nightly" or "nightly"."# ;
427+
428+ if !( pre_release. is_empty ( ) /* stable */
429+ || pre_release == "beta"
430+ || pre_release. starts_with ( "beta." )
431+ || pre_release == "nightly" )
432+ {
433+ return Err ( invalid_input ( input, MSG ) ) ;
434+ }
435+
436+ let Some ( ( major_str, tail) ) = version. split_once ( '.' ) else {
437+ return Err ( invalid_input ( input, MSG ) ) ;
421438 } ;
422439
423440 if major_str != "1" {
@@ -427,7 +444,7 @@ impl FromStr for RustTarget {
427444 ) ) ;
428445 }
429446
430- let ( minor, patch) = if let Some ( ( minor_str, patch_str) ) =
447+ let ( mut minor, mut patch) = if let Some ( ( minor_str, patch_str) ) =
431448 tail. split_once ( '.' )
432449 {
433450 let Ok ( minor) = minor_str. parse :: < u64 > ( ) else {
@@ -444,6 +461,12 @@ impl FromStr for RustTarget {
444461 ( minor, 0 )
445462 } ;
446463
464+ if pre_release == "nightly" {
465+ // treat nightly as incomplete and therefore as the previous maximaly patched stable
466+ minor -= 1 ;
467+ patch = u64:: MAX ;
468+ }
469+
447470 Self :: stable ( minor, patch) . map_err ( |err| invalid_input ( input, err) )
448471 }
449472}
@@ -519,7 +542,9 @@ mod test {
519542 // Two targets are equivalent if they enable the same set of features
520543 let expected = RustFeatures :: new_with_latest_edition ( expected) ;
521544 let found = RustFeatures :: new_with_latest_edition (
522- input. parse :: < RustTarget > ( ) . unwrap ( ) ,
545+ input. parse :: < RustTarget > ( ) . unwrap_or_else ( |_| {
546+ panic ! ( "{input} should parse as a valid target" )
547+ } ) ,
523548 ) ;
524549 assert_eq ! (
525550 expected,
@@ -542,6 +567,9 @@ mod test {
542567 test_target ( "1.71.1" , RustTarget :: Stable_1_71 ) ;
543568 test_target ( "1.72" , RustTarget :: Stable_1_71 ) ;
544569 test_target ( "1.73" , RustTarget :: Stable_1_73 ) ;
570+ test_target ( "1.82.0-beta" , RustTarget :: Stable_1_82 ) ;
571+ test_target ( "1.82.0-beta.1" , RustTarget :: Stable_1_82 ) ;
572+ test_target ( "1.83.1-nightly" , RustTarget :: Stable_1_82 ) ;
545573 test_target ( "1.18446744073709551615" , LATEST_STABLE_RUST ) ;
546574 test_target ( "nightly" , RustTarget :: Nightly ) ;
547575 }
0 commit comments