Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit a19047a

Browse files
pietroalbinipvdrz
authored andcommitted
implement range support in //@ edition
1 parent 51ff895 commit a19047a

File tree

2 files changed

+272
-8
lines changed

2 files changed

+272
-8
lines changed

‎src/tools/compiletest/src/directives.rs

Lines changed: 103 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -432,10 +432,11 @@ impl TestProps {
432432
panic!("`compiler-flags` directive should be spelled `compile-flags`");
433433
}
434434

435-
if let Some(edition) = config.parse_edition(ln, testfile, line_number) {
435+
if let Some(range) = parse_edition_range(config,ln, testfile, line_number) {
436436
// The edition is added at the start, since flags from //@compile-flags must
437437
// be passed to rustc last.
438-
self.compile_flags.insert(0, format!("--edition={}", edition.trim()));
438+
self.compile_flags
439+
.insert(0, format!("--edition={}", range.edition_to_test(config)));
439440
has_edition = true;
440441
}
441442

@@ -1125,10 +1126,6 @@ impl Config {
11251126
}
11261127
}
11271128

1128-
fn parse_edition(&self, line: &str, testfile: &Utf8Path, line_number: usize) -> Option<String> {
1129-
self.parse_name_value_directive(line, "edition", testfile, line_number)
1130-
}
1131-
11321129
fn set_name_directive(&self, line: &str, directive: &str, value: &mut bool) {
11331130
match value {
11341131
true => {
@@ -1784,3 +1781,103 @@ enum IgnoreDecision {
17841781
Continue,
17851782
Error { message: String },
17861783
}
1784+
1785+
fn parse_edition_range(
1786+
config: &Config,
1787+
line: &str,
1788+
testfile: &Utf8Path,
1789+
line_number: usize,
1790+
) -> Option<EditionRange> {
1791+
let raw = config.parse_name_value_directive(line, "edition", testfile, line_number)?;
1792+
1793+
if let Some((greter_equal_than, lower_than)) = raw.split_once("..") {
1794+
Some(match (maybe_parse_edition(greter_equal_than), maybe_parse_edition(lower_than)) {
1795+
(Some(greater_equal_than), Some(lower_than)) if lower_than < greater_equal_than => {
1796+
panic!("the left side of `//@ edition` cannot be higher than the right side");
1797+
}
1798+
(Some(greater_equal_than), Some(lower_than)) if lower_than == greater_equal_than => {
1799+
panic!("the left side of `//@ edition` cannot be equal to the right side");
1800+
}
1801+
(Some(greater_equal_than), Some(lower_than)) => {
1802+
EditionRange::Range { greater_equal_than, lower_than }
1803+
}
1804+
(Some(greater_equal_than), None) => EditionRange::GreaterEqualThan(greater_equal_than),
1805+
(None, Some(_)) => panic!("..edition is not a supported range in //@ edition"),
1806+
(None, None) => panic!("'..' is not a supported range in //@ edition"),
1807+
})
1808+
} else {
1809+
Some(EditionRange::Exact(maybe_parse_edition(&raw).expect("empty value for //@ edition")))
1810+
}
1811+
}
1812+
1813+
fn maybe_parse_edition(mut input: &str) -> Option<Edition> {
1814+
input = input.trim();
1815+
if input.is_empty() {
1816+
return None;
1817+
}
1818+
Some(parse_edition(input))
1819+
}
1820+
1821+
fn parse_edition(mut input: &str) -> Edition {
1822+
input = input.trim();
1823+
if input == "future" {
1824+
Edition::Future
1825+
} else {
1826+
Edition::Year(input.parse().expect(&format!("'{input}' doesn't look like an edition")))
1827+
}
1828+
}
1829+
1830+
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
1831+
enum Edition {
1832+
// Note that the ordering here is load-bearing, as we want the future edition to be last.
1833+
Year(u32),
1834+
Future,
1835+
}
1836+
1837+
impl std::fmt::Display for Edition {
1838+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1839+
match self {
1840+
Edition::Year(year) => write!(f, "{year}"),
1841+
Edition::Future => f.write_str("future"),
1842+
}
1843+
}
1844+
}
1845+
1846+
impl From<u32> for Edition {
1847+
fn from(value: u32) -> Self {
1848+
Edition::Year(value)
1849+
}
1850+
}
1851+
1852+
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
1853+
enum EditionRange {
1854+
Exact(Edition),
1855+
GreaterEqualThan(Edition),
1856+
Range { greater_equal_than: Edition, lower_than: Edition },
1857+
}
1858+
1859+
impl EditionRange {
1860+
fn edition_to_test(&self, config: &Config) -> Edition {
1861+
let min_edition = Edition::Year(2015);
1862+
let requested: Edition =
1863+
config.edition.as_deref().map(parse_edition).unwrap_or(min_edition);
1864+
1865+
match *self {
1866+
EditionRange::Exact(exact) => exact,
1867+
EditionRange::GreaterEqualThan(greater_equal_than) => {
1868+
if requested >= greater_equal_than {
1869+
requested
1870+
} else {
1871+
greater_equal_than // Lower bound
1872+
}
1873+
}
1874+
EditionRange::Range { greater_equal_than, lower_than } => {
1875+
if requested >= greater_equal_than && requested < lower_than {
1876+
requested
1877+
} else {
1878+
greater_equal_than // Lower bound
1879+
}
1880+
}
1881+
}
1882+
}
1883+
}

‎src/tools/compiletest/src/directives/tests.rs

Lines changed: 169 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use camino::Utf8Path;
44
use semver::Version;
55

66
use super::{
7-
DirectivesCache, EarlyProps, extract_llvm_version, extract_version_range, iter_directives,
8-
parse_normalize_rule,
7+
DirectivesCache, EarlyProps, Edition,EditionRange, extract_llvm_version,
8+
extract_version_range, iter_directives,parse_normalize_rule,
99
};
1010
use crate::common::{Config, Debugger, TestMode};
1111
use crate::executor::{CollectedTestDesc, ShouldPanic};
@@ -71,6 +71,7 @@ fn test_parse_normalize_rule() {
7171
struct ConfigBuilder {
7272
mode: Option<String>,
7373
channel: Option<String>,
74+
edition: Option<String>,
7475
host: Option<String>,
7576
target: Option<String>,
7677
stage: Option<u32>,
@@ -94,6 +95,11 @@ impl ConfigBuilder {
9495
self
9596
}
9697

98+
fn edition(&mut self, s: &str) -> &mut Self {
99+
self.edition = Some(s.to_owned());
100+
self
101+
}
102+
97103
fn host(&mut self, s: &str) -> &mut Self {
98104
self.host = Some(s.to_owned());
99105
self
@@ -181,6 +187,10 @@ impl ConfigBuilder {
181187
];
182188
let mut args: Vec<String> = args.iter().map(ToString::to_string).collect();
183189

190+
if let Some(edition) = &self.edition {
191+
args.push(format!("--edition={edition}"));
192+
}
193+
184194
if let Some(ref llvm_version) = self.llvm_version {
185195
args.push("--llvm-version".to_owned());
186196
args.push(llvm_version.clone());
@@ -939,3 +949,160 @@ fn test_needs_target_std() {
939949
let config = cfg().target("x86_64-unknown-linux-gnu").build();
940950
assert!(!check_ignore(&config, "//@ needs-target-std"));
941951
}
952+
953+
fn y(year: u32) -> Edition {
954+
Edition::Year(year)
955+
}
956+
957+
fn parse_edition_range(line: &str) -> Option<EditionRange> {
958+
let config = cfg().build();
959+
super::parse_edition_range(&config, line)
960+
}
961+
962+
#[test]
963+
fn test_parse_edition_range() {
964+
assert_eq!(None, parse_edition_range("hello-world"));
965+
assert_eq!(None, parse_edition_range("edition"));
966+
967+
assert_eq!(Some(EditionRange::Exact(y(2018))), parse_edition_range("edition: 2018"));
968+
assert_eq!(Some(EditionRange::Exact(y(2021))), parse_edition_range("edition:2021"));
969+
assert_eq!(Some(EditionRange::Exact(y(2024))), parse_edition_range("edition: 2024 "));
970+
assert_eq!(Some(EditionRange::Exact(Edition::Future)), parse_edition_range("edition: future"));
971+
972+
assert_eq!(Some(EditionRange::LowerThan(y(2018))), parse_edition_range("edition: ..2018"));
973+
assert_eq!(Some(EditionRange::LowerThan(y(2021))), parse_edition_range("edition:.. 2021"));
974+
assert_eq!(Some(EditionRange::LowerThan(y(2024))), parse_edition_range("edition: .. 2024 "));
975+
assert_eq!(
976+
Some(EditionRange::LowerThan(Edition::Future)),
977+
parse_edition_range("edition: ..future")
978+
);
979+
980+
assert_eq!(
981+
Some(EditionRange::GreaterEqualThan(y(2018))),
982+
parse_edition_range("edition: 2018..")
983+
);
984+
assert_eq!(
985+
Some(EditionRange::GreaterEqualThan(y(2021))),
986+
parse_edition_range("edition:2021 ..")
987+
);
988+
assert_eq!(
989+
Some(EditionRange::GreaterEqualThan(y(2024))),
990+
parse_edition_range("edition: 2024 .. ")
991+
);
992+
assert_eq!(
993+
Some(EditionRange::GreaterEqualThan(Edition::Future)),
994+
parse_edition_range("edition: future.. ")
995+
);
996+
997+
assert_eq!(
998+
Some(EditionRange::Range { greater_equal_than: y(2018), lower_than: y(2024) }),
999+
parse_edition_range("edition: 2018..2024")
1000+
);
1001+
assert_eq!(
1002+
Some(EditionRange::Range { greater_equal_than: y(2015), lower_than: y(2021) }),
1003+
parse_edition_range("edition:2015 .. 2021 ")
1004+
);
1005+
assert_eq!(
1006+
Some(EditionRange::Range { greater_equal_than: y(2021), lower_than: y(2027) }),
1007+
parse_edition_range("edition: 2021 .. 2027 ")
1008+
);
1009+
assert_eq!(
1010+
Some(EditionRange::Range { greater_equal_than: y(2021), lower_than: Edition::Future }),
1011+
parse_edition_range("edition: 2021..future")
1012+
);
1013+
}
1014+
1015+
#[test]
1016+
#[should_panic = "empty value for //@ edition"]
1017+
fn test_parse_edition_range_empty() {
1018+
parse_edition_range("edition:");
1019+
}
1020+
1021+
#[test]
1022+
#[should_panic = "'hello' doesn't look like an edition"]
1023+
fn test_parse_edition_range_invalid_edition() {
1024+
parse_edition_range("edition: hello");
1025+
}
1026+
1027+
#[test]
1028+
#[should_panic = "'..' is not a supported range in //@ edition"]
1029+
fn test_parse_edition_range_double_dots() {
1030+
parse_edition_range("edition: ..");
1031+
}
1032+
1033+
#[test]
1034+
#[should_panic = "the left side of `//@ edition` cannot be higher than the right side"]
1035+
fn test_parse_edition_range_inverted_range() {
1036+
parse_edition_range("edition: 2021..2015");
1037+
}
1038+
1039+
#[test]
1040+
#[should_panic = "the left side of `//@ edition` cannot be higher than the right side"]
1041+
fn test_parse_edition_range_inverted_range_future() {
1042+
parse_edition_range("edition: future..2015");
1043+
}
1044+
1045+
#[test]
1046+
#[should_panic = "the left side of `//@ edition` cannot be equal to the right side"]
1047+
fn test_parse_edition_range_empty_range() {
1048+
parse_edition_range("edition: 2021..2021");
1049+
}
1050+
1051+
#[track_caller]
1052+
fn assert_edition_to_test(
1053+
expected: impl Into<Edition>,
1054+
range: EditionRange,
1055+
default: Option<&str>,
1056+
) {
1057+
let mut cfg = cfg();
1058+
if let Some(default) = default {
1059+
cfg.edition(default);
1060+
}
1061+
assert_eq!(expected.into(), range.edition_to_test(&cfg.build()));
1062+
}
1063+
1064+
#[test]
1065+
fn test_edition_range_edition_to_test() {
1066+
let exact = EditionRange::Exact(y(2021));
1067+
assert_edition_to_test(2021, exact, None);
1068+
assert_edition_to_test(2021, exact, Some("2018"));
1069+
assert_edition_to_test(2021, exact, Some("future"));
1070+
1071+
assert_edition_to_test(Edition::Future, EditionRange::Exact(Edition::Future), None);
1072+
1073+
let greater_equal_than = EditionRange::GreaterEqualThan(y(2021));
1074+
assert_edition_to_test(2021, greater_equal_than, None);
1075+
assert_edition_to_test(2021, greater_equal_than, Some("2015"));
1076+
assert_edition_to_test(2021, greater_equal_than, Some("2018"));
1077+
assert_edition_to_test(2021, greater_equal_than, Some("2021"));
1078+
assert_edition_to_test(2024, greater_equal_than, Some("2024"));
1079+
assert_edition_to_test(Edition::Future, greater_equal_than, Some("future"));
1080+
1081+
let lower_than = EditionRange::LowerThan(y(2021));
1082+
assert_edition_to_test(2015, lower_than, None);
1083+
assert_edition_to_test(2015, lower_than, Some("2015"));
1084+
assert_edition_to_test(2018, lower_than, Some("2018"));
1085+
assert_edition_to_test(2015, lower_than, Some("2021"));
1086+
assert_edition_to_test(2015, lower_than, Some("2024"));
1087+
assert_edition_to_test(2015, lower_than, Some("future"));
1088+
1089+
let range = EditionRange::Range { greater_equal_than: y(2018), lower_than: y(2024) };
1090+
assert_edition_to_test(2018, range, None);
1091+
assert_edition_to_test(2018, range, Some("2015"));
1092+
assert_edition_to_test(2018, range, Some("2018"));
1093+
assert_edition_to_test(2021, range, Some("2021"));
1094+
assert_edition_to_test(2018, range, Some("2024"));
1095+
assert_edition_to_test(2018, range, Some("future"));
1096+
}
1097+
1098+
#[test]
1099+
#[should_panic = "'not an edition' doesn't look like an edition"]
1100+
fn test_edition_range_edition_to_test_bad_cli() {
1101+
assert_edition_to_test(2021, EditionRange::Exact(y(2021)), Some("not an edition"));
1102+
}
1103+
1104+
#[test]
1105+
#[should_panic = "editions lower than 2015 are not supported"]
1106+
fn test_edition_range_too_low() {
1107+
assert_edition_to_test(2015, EditionRange::LowerThan(y(2012)), None);
1108+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /