Skip to content

Commit 18c275b

Browse files
committed
Auto merge of #69635 - Dylan-DPC:rollup-2oh8uu5, r=Dylan-DPC
Rollup of 6 pull requests Successful merges: - #68682 (Add documentation to compiler intrinsics) - #69544 (Unrevert "Remove `checked_add` in `Layout::repeat`") - #69617 (constify mem::forget) - #69622 (Rename `syntax` in librustc_ast/README.md) - #69623 (stash API: remove panic to fix ICE.) - #69624 (Toolstate: Don't block beta week on already broken tools.) Failed merges: - #69626 (Toolstate: don't duplicate nightly tool list.) r? @ghost
2 parents c839a7b + f8fb3ef commit 18c275b

File tree

9 files changed

+688
-95
lines changed

9 files changed

+688
-95
lines changed

src/bootstrap/toolstate.rs

+133-63
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::env;
66
use std::fmt;
77
use std::fs;
88
use std::io::{Seek, SeekFrom};
9-
use std::path::PathBuf;
9+
use std::path::{Path, PathBuf};
1010
use std::process::Command;
1111
use std::time;
1212

@@ -24,7 +24,7 @@ const OS: Option<&str> = None;
2424

2525
type ToolstateData = HashMap<Box<str>, ToolState>;
2626

27-
#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
27+
#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)]
2828
#[serde(rename_all = "kebab-case")]
2929
/// Whether a tool can be compiled, tested or neither
3030
pub enum ToolState {
@@ -143,10 +143,31 @@ pub struct ToolStateCheck;
143143
impl Step for ToolStateCheck {
144144
type Output = ();
145145

146-
/// Runs the `linkchecker` tool as compiled in `stage` by the `host` compiler.
146+
/// Checks tool state status.
147147
///
148-
/// This tool in `src/tools` will verify the validity of all our links in the
149-
/// documentation to ensure we don't have a bunch of dead ones.
148+
/// This is intended to be used in the `checktools.sh` script. To use
149+
/// this, set `save-toolstates` in `config.toml` so that tool status will
150+
/// be saved to a JSON file. Then, run `x.py test --no-fail-fast` for all
151+
/// of the tools to populate the JSON file. After that is done, this
152+
/// command can be run to check for any status failures, and exits with an
153+
/// error if there are any.
154+
///
155+
/// This also handles publishing the results to the `history` directory of
156+
/// the toolstate repo https://github.com/rust-lang-nursery/rust-toolstate
157+
/// if the env var `TOOLSTATE_PUBLISH` is set. Note that there is a
158+
/// *separate* step of updating the `latest.json` file and creating GitHub
159+
/// issues and comments in `src/ci/publish_toolstate.sh`, which is only
160+
/// performed on master. (The shell/python code is intended to be migrated
161+
/// here eventually.)
162+
///
163+
/// The rules for failure are:
164+
/// * If the PR modifies a tool, the status must be test-pass.
165+
/// NOTE: There is intent to change this, see
166+
/// https://github.com/rust-lang/rust/issues/65000.
167+
/// * All "stable" tools must be test-pass on the stable or beta branches.
168+
/// * During beta promotion week, a PR is not allowed to "regress" a
169+
/// stable tool. That is, the status is not allowed to get worse
170+
/// (test-pass to test-fail or build-fail).
150171
fn run(self, builder: &Builder<'_>) {
151172
if builder.config.dry_run {
152173
return;
@@ -171,6 +192,8 @@ impl Step for ToolStateCheck {
171192
}
172193

173194
check_changed_files(&toolstates);
195+
checkout_toolstate_repo();
196+
let old_toolstate = read_old_toolstate();
174197

175198
for (tool, _) in STABLE_TOOLS.iter() {
176199
let state = toolstates[*tool];
@@ -180,11 +203,24 @@ impl Step for ToolStateCheck {
180203
did_error = true;
181204
eprintln!("error: Tool `{}` should be test-pass but is {}", tool, state);
182205
} else if in_beta_week {
183-
did_error = true;
184-
eprintln!(
185-
"error: Tool `{}` should be test-pass but is {} during beta week.",
186-
tool, state
187-
);
206+
let old_state = old_toolstate
207+
.iter()
208+
.find(|ts| ts.tool == *tool)
209+
.expect("latest.json missing tool")
210+
.state();
211+
if state < old_state {
212+
did_error = true;
213+
eprintln!(
214+
"error: Tool `{}` has regressed from {} to {} during beta week.",
215+
tool, old_state, state
216+
);
217+
} else {
218+
eprintln!(
219+
"warning: Tool `{}` is not test-pass (is `{}`), \
220+
this should be fixed before beta is branched.",
221+
tool, state
222+
);
223+
}
188224
}
189225
}
190226
}
@@ -247,6 +283,70 @@ impl Builder<'_> {
247283
}
248284
}
249285

286+
fn toolstate_repo() -> String {
287+
env::var("TOOLSTATE_REPO")
288+
.unwrap_or_else(|_| "https://github.com/rust-lang-nursery/rust-toolstate.git".to_string())
289+
}
290+
291+
/// Directory where the toolstate repo is checked out.
292+
const TOOLSTATE_DIR: &str = "rust-toolstate";
293+
294+
/// Checks out the toolstate repo into `TOOLSTATE_DIR`.
295+
fn checkout_toolstate_repo() {
296+
if let Ok(token) = env::var("TOOLSTATE_REPO_ACCESS_TOKEN") {
297+
prepare_toolstate_config(&token);
298+
}
299+
if Path::new(TOOLSTATE_DIR).exists() {
300+
eprintln!("Cleaning old toolstate directory...");
301+
t!(fs::remove_dir_all(TOOLSTATE_DIR));
302+
}
303+
304+
let status = Command::new("git")
305+
.arg("clone")
306+
.arg("--depth=1")
307+
.arg(toolstate_repo())
308+
.arg(TOOLSTATE_DIR)
309+
.status();
310+
let success = match status {
311+
Ok(s) => s.success(),
312+
Err(_) => false,
313+
};
314+
if !success {
315+
panic!("git clone unsuccessful (status: {:?})", status);
316+
}
317+
}
318+
319+
/// Sets up config and authentication for modifying the toolstate repo.
320+
fn prepare_toolstate_config(token: &str) {
321+
fn git_config(key: &str, value: &str) {
322+
let status = Command::new("git").arg("config").arg("--global").arg(key).arg(value).status();
323+
let success = match status {
324+
Ok(s) => s.success(),
325+
Err(_) => false,
326+
};
327+
if !success {
328+
panic!("git config key={} value={} successful (status: {:?})", key, value, status);
329+
}
330+
}
331+
332+
// If changing anything here, then please check that src/ci/publish_toolstate.sh is up to date
333+
// as well.
334+
git_config("user.email", "7378925+rust-toolstate-update@users.noreply.github.com");
335+
git_config("user.name", "Rust Toolstate Update");
336+
git_config("credential.helper", "store");
337+
338+
let credential = format!("https://{}:x-oauth-basic@github.com\n", token,);
339+
let git_credential_path = PathBuf::from(t!(env::var("HOME"))).join(".git-credentials");
340+
t!(fs::write(&git_credential_path, credential));
341+
}
342+
343+
/// Reads the latest toolstate from the toolstate repo.
344+
fn read_old_toolstate() -> Vec<RepoState> {
345+
let latest_path = Path::new(TOOLSTATE_DIR).join("_data").join("latest.json");
346+
let old_toolstate = t!(fs::read(latest_path));
347+
t!(serde_json::from_slice(&old_toolstate))
348+
}
349+
250350
/// This function `commit_toolstate_change` provides functionality for pushing a change
251351
/// to the `rust-toolstate` repository.
252352
///
@@ -274,45 +374,7 @@ impl Builder<'_> {
274374
/// * See <https://help.github.com/articles/about-commit-email-addresses/>
275375
/// if a private email by GitHub is wanted.
276376
fn commit_toolstate_change(current_toolstate: &ToolstateData, in_beta_week: bool) {
277-
fn git_config(key: &str, value: &str) {
278-
let status = Command::new("git").arg("config").arg("--global").arg(key).arg(value).status();
279-
let success = match status {
280-
Ok(s) => s.success(),
281-
Err(_) => false,
282-
};
283-
if !success {
284-
panic!("git config key={} value={} successful (status: {:?})", key, value, status);
285-
}
286-
}
287-
288-
// If changing anything here, then please check that src/ci/publish_toolstate.sh is up to date
289-
// as well.
290-
git_config("user.email", "7378925+rust-toolstate-update@users.noreply.github.com");
291-
git_config("user.name", "Rust Toolstate Update");
292-
git_config("credential.helper", "store");
293-
294-
let credential = format!(
295-
"https://{}:x-oauth-basic@github.com\n",
296-
t!(env::var("TOOLSTATE_REPO_ACCESS_TOKEN")),
297-
);
298-
let git_credential_path = PathBuf::from(t!(env::var("HOME"))).join(".git-credentials");
299-
t!(fs::write(&git_credential_path, credential));
300-
301-
let status = Command::new("git")
302-
.arg("clone")
303-
.arg("--depth=1")
304-
.arg(t!(env::var("TOOLSTATE_REPO")))
305-
.status();
306-
let success = match status {
307-
Ok(s) => s.success(),
308-
Err(_) => false,
309-
};
310-
if !success {
311-
panic!("git clone successful (status: {:?})", status);
312-
}
313-
314-
let old_toolstate = t!(fs::read("rust-toolstate/_data/latest.json"));
315-
let old_toolstate: Vec<RepoState> = t!(serde_json::from_slice(&old_toolstate));
377+
let old_toolstate = read_old_toolstate();
316378

317379
let message = format!("({} CI update)", OS.expect("linux/windows only"));
318380
let mut success = false;
@@ -322,7 +384,7 @@ fn commit_toolstate_change(current_toolstate: &ToolstateData, in_beta_week: bool
322384

323385
// `git commit` failing means nothing to commit.
324386
let status = t!(Command::new("git")
325-
.current_dir("rust-toolstate")
387+
.current_dir(TOOLSTATE_DIR)
326388
.arg("commit")
327389
.arg("-a")
328390
.arg("-m")
@@ -334,7 +396,7 @@ fn commit_toolstate_change(current_toolstate: &ToolstateData, in_beta_week: bool
334396
}
335397

336398
let status = t!(Command::new("git")
337-
.current_dir("rust-toolstate")
399+
.current_dir(TOOLSTATE_DIR)
338400
.arg("push")
339401
.arg("origin")
340402
.arg("master")
@@ -347,14 +409,14 @@ fn commit_toolstate_change(current_toolstate: &ToolstateData, in_beta_week: bool
347409
eprintln!("Sleeping for 3 seconds before retrying push");
348410
std::thread::sleep(std::time::Duration::from_secs(3));
349411
let status = t!(Command::new("git")
350-
.current_dir("rust-toolstate")
412+
.current_dir(TOOLSTATE_DIR)
351413
.arg("fetch")
352414
.arg("origin")
353415
.arg("master")
354416
.status());
355417
assert!(status.success());
356418
let status = t!(Command::new("git")
357-
.current_dir("rust-toolstate")
419+
.current_dir(TOOLSTATE_DIR)
358420
.arg("reset")
359421
.arg("--hard")
360422
.arg("origin/master")
@@ -375,18 +437,12 @@ fn change_toolstate(
375437
let mut regressed = false;
376438
for repo_state in old_toolstate {
377439
let tool = &repo_state.tool;
378-
let state = if cfg!(target_os = "linux") {
379-
&repo_state.linux
380-
} else if cfg!(windows) {
381-
&repo_state.windows
382-
} else {
383-
unimplemented!()
384-
};
440+
let state = repo_state.state();
385441
let new_state = current_toolstate[tool.as_str()];
386442

387-
if new_state != *state {
443+
if new_state != state {
388444
eprintln!("The state of `{}` has changed from `{}` to `{}`", tool, state, new_state);
389-
if (new_state as u8) < (*state as u8) {
445+
if new_state < state {
390446
if !["rustc-guide", "miri", "embedded-book"].contains(&tool.as_str()) {
391447
regressed = true;
392448
}
@@ -403,7 +459,9 @@ fn change_toolstate(
403459

404460
let toolstate_serialized = t!(serde_json::to_string(&current_toolstate));
405461

406-
let history_path = format!("rust-toolstate/history/{}.tsv", OS.expect("linux/windows only"));
462+
let history_path = Path::new(TOOLSTATE_DIR)
463+
.join("history")
464+
.join(format!("{}.tsv", OS.expect("linux/windows only")));
407465
let mut file = t!(fs::read_to_string(&history_path));
408466
let end_of_first_line = file.find('\n').unwrap();
409467
file.insert_str(end_of_first_line, &format!("\n{}\t{}", commit.trim(), toolstate_serialized));
@@ -418,3 +476,15 @@ struct RepoState {
418476
commit: String,
419477
datetime: String,
420478
}
479+
480+
impl RepoState {
481+
fn state(&self) -> ToolState {
482+
if cfg!(target_os = "linux") {
483+
self.linux
484+
} else if cfg!(windows) {
485+
self.windows
486+
} else {
487+
unimplemented!()
488+
}
489+
}
490+
}

src/libcore/alloc.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -241,13 +241,11 @@ impl Layout {
241241
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
242242
#[inline]
243243
pub fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutErr> {
244-
// Warning, removing the checked_add here led to segfaults in #67174. Further
245-
// analysis in #69225 seems to indicate that this is an LTO-related
246-
// miscompilation, so #67174 might be able to be reapplied in the future.
247-
let padded_size = self
248-
.size()
249-
.checked_add(self.padding_needed_for(self.align()))
250-
.ok_or(LayoutErr { private: () })?;
244+
// This cannot overflow. Quoting from the invariant of Layout:
245+
// > `size`, when rounded up to the nearest multiple of `align`,
246+
// > must not overflow (i.e., the rounded value must be less than
247+
// > `usize::MAX`)
248+
let padded_size = self.size() + self.padding_needed_for(self.align());
251249
let alloc_size = padded_size.checked_mul(n).ok_or(LayoutErr { private: () })?;
252250

253251
unsafe {

0 commit comments

Comments
 (0)