Skip to content

Rollup of 9 pull requests #139912

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 27 commits into from
Apr 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
fc8df06
update submodules if the directory doesn't exist
WaffleLapkin Apr 14, 2025
1397dab
fix typo
WaffleLapkin Apr 14, 2025
6c441cc
canonicalize test build dir before normalizing it
WaffleLapkin Apr 14, 2025
502b630
tidy: don't crush on non-existent submodules
WaffleLapkin Apr 15, 2025
52f4b16
use helper function instead of writing rustfmt stamp by hand
WaffleLapkin Apr 15, 2025
dda4d7b
slightly correct comments and diagnostics about checking modifications
WaffleLapkin Apr 15, 2025
8934ac5
add a comment for code that isn't
WaffleLapkin Apr 15, 2025
8120950
Add test for issue 125668
reddevilmidzy Apr 15, 2025
11e5987
Don't compute name of associated item if it's an RPITIT
compiler-errors Apr 15, 2025
2020adb
Fix wrong suggestion for async gen block and add regression ui test f…
GuillaumeGomez Apr 15, 2025
90aec13
commit rustfmt stump in `x t tidy` even on `check`
WaffleLapkin Apr 15, 2025
89b4eba
normalize canonical and non-canonical paths in compiletest
WaffleLapkin Apr 15, 2025
f35c85f
Add unstable foo::bar extern command line arguments
eholk Apr 8, 2025
f3f53d2
Update books
rustbot Apr 15, 2025
ea1b230
Update Cargo.lock for rustbook
ehuss Apr 15, 2025
766cd3a
Remove support for `#[rustc_mir(borrowck_graphviz_format="gen_kill")]`.
nnethercote Apr 15, 2025
62882f3
Improve `borrowck_graphviz_*` documentation.
nnethercote Apr 15, 2025
6999305
Make CodeStat's type sizes a public field
blyxyas Apr 15, 2025
723ef24
Rollup merge of #139647 - eholk:package-namespace, r=fmease
matthiaskrgr Apr 16, 2025
f7b6f15
Rollup merge of #139823 - WaffleLapkin:bootpaper, r=jieyouxu
matthiaskrgr Apr 16, 2025
b65e6b7
Rollup merge of #139867 - WaffleLapkin:tidypaper, r=jieyouxu
matthiaskrgr Apr 16, 2025
a1de2a2
Rollup merge of #139871 - GuillaumeGomez:async-gen-move, r=compiler-e…
matthiaskrgr Apr 16, 2025
b3284ad
Rollup merge of #139876 - blyxyas:write_type_sizes, r=nnethercote
matthiaskrgr Apr 16, 2025
ec6bdda
Rollup merge of #139880 - compiler-errors:rpitit-nameless, r=nnethercote
matthiaskrgr Apr 16, 2025
1bde68e
Rollup merge of #139884 - rustbot:docs-update, r=ehuss
matthiaskrgr Apr 16, 2025
e96b999
Rollup merge of #139886 - nnethercote:graphviz_borrowck, r=compiler-e…
matthiaskrgr Apr 16, 2025
0039c7d
Rollup merge of #139893 - reddevilmidzy:add-test, r=SparrowLii
matthiaskrgr Apr 16, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3376,10 +3376,15 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {

let (sugg_span, suggestion) = match tcx.sess.source_map().span_to_snippet(args_span) {
Ok(string) => {
let coro_prefix = if string.starts_with("async") {
// `async` is 5 chars long. Not using `.len()` to avoid the cast from `usize`
// to `u32`.
Some(5)
let coro_prefix = if let Some(sub) = string.strip_prefix("async") {
let trimmed_sub = sub.trim_end();
if trimmed_sub.ends_with("gen") {
// `async` is 5 chars long.
Some((trimmed_sub.len() + 5) as _)
} else {
// `async` is 5 chars long.
Some(5)
}
} else if string.starts_with("gen") {
// `gen` is 3 chars long
Some(3)
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
.iter()
.flat_map(|trait_def_id| tcx.associated_items(*trait_def_id).in_definition_order())
.filter_map(|item| {
(!item.is_impl_trait_in_trait() && item.as_tag() == assoc_tag)
.then_some(item.name())
(!item.is_impl_trait_in_trait() && item.as_tag() == assoc_tag).then(|| item.name())
})
.collect();

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_dataflow/src/framework/graphviz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ impl RustcMirAttrs {
})
} else if attr.has_name(sym::borrowck_graphviz_format) {
Self::set_field(&mut ret.formatter, tcx, &attr, |s| match s {
sym::gen_kill | sym::two_phase => Ok(s),
sym::two_phase => Ok(s),
_ => {
tcx.dcx().emit_err(UnknownFormatter { span: attr.span() });
Err(())
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_session/src/code_stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ pub struct TypeSizeInfo {

#[derive(Default)]
pub struct CodeStats {
type_sizes: Lock<FxHashSet<TypeSizeInfo>>,
pub type_sizes: Lock<FxHashSet<TypeSizeInfo>>,
}

impl CodeStats {
Expand Down
39 changes: 5 additions & 34 deletions compiler/rustc_session/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use std::str::{self, FromStr};
use std::sync::LazyLock;
use std::{cmp, fmt, fs, iter};

use externs::{ExternOpt, split_extern_opt};
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey};
use rustc_errors::emitter::HumanReadableErrorType;
Expand All @@ -39,6 +40,7 @@ use crate::utils::CanonicalizedPath;
use crate::{EarlyDiagCtxt, HashStableContext, Session, filesearch, lint};

mod cfg;
mod externs;
mod native_libs;
pub mod sigpipe;

Expand Down Expand Up @@ -2205,44 +2207,13 @@ pub fn parse_externs(
matches: &getopts::Matches,
unstable_opts: &UnstableOptions,
) -> Externs {
fn is_ascii_ident(string: &str) -> bool {
let mut chars = string.chars();
if let Some(start) = chars.next()
&& (start.is_ascii_alphabetic() || start == '_')
{
chars.all(|char| char.is_ascii_alphanumeric() || char == '_')
} else {
false
}
}

let is_unstable_enabled = unstable_opts.unstable_options;
let mut externs: BTreeMap<String, ExternEntry> = BTreeMap::new();
for arg in matches.opt_strs("extern") {
let (name, path) = match arg.split_once('=') {
None => (arg, None),
Some((name, path)) => (name.to_string(), Some(Path::new(path))),
};
let (options, name) = match name.split_once(':') {
None => (None, name),
Some((opts, name)) => (Some(opts), name.to_string()),
};

if !is_ascii_ident(&name) {
let mut error = early_dcx.early_struct_fatal(format!(
"crate name `{name}` passed to `--extern` is not a valid ASCII identifier"
));
let adjusted_name = name.replace('-', "_");
if is_ascii_ident(&adjusted_name) {
#[allow(rustc::diagnostic_outside_of_impl)] // FIXME
error.help(format!(
"consider replacing the dashes with underscores: `{adjusted_name}`"
));
}
error.emit();
}
let ExternOpt { crate_name: name, path, options } =
split_extern_opt(early_dcx, unstable_opts, &arg).unwrap_or_else(|e| e.emit());

let path = path.map(|p| CanonicalizedPath::new(p));
let path = path.map(|p| CanonicalizedPath::new(p.as_path()));

let entry = externs.entry(name.to_owned());

Expand Down
79 changes: 79 additions & 0 deletions compiler/rustc_session/src/config/externs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
//! This module contains code to help parse and manipulate `--extern` arguments.

use std::path::PathBuf;

use rustc_errors::{Diag, FatalAbort};

use super::UnstableOptions;
use crate::EarlyDiagCtxt;

#[cfg(test)]
mod tests;

/// Represents the pieces of an `--extern` argument.
pub(crate) struct ExternOpt {
pub(crate) crate_name: String,
pub(crate) path: Option<PathBuf>,
pub(crate) options: Option<String>,
}

/// Breaks out the major components of an `--extern` argument.
///
/// The options field will be a string containing comma-separated options that will need further
/// parsing and processing.
pub(crate) fn split_extern_opt<'a>(
early_dcx: &'a EarlyDiagCtxt,
unstable_opts: &UnstableOptions,
extern_opt: &str,
) -> Result<ExternOpt, Diag<'a, FatalAbort>> {
let (name, path) = match extern_opt.split_once('=') {
None => (extern_opt.to_string(), None),
Some((name, path)) => (name.to_string(), Some(PathBuf::from(path))),
};
let (options, crate_name) = match name.split_once(':') {
None => (None, name),
Some((opts, crate_name)) => {
if unstable_opts.namespaced_crates && crate_name.starts_with(':') {
// If the name starts with `:`, we know this was actually something like `foo::bar` and
// not a set of options. We can just use the original name as the crate name.
(None, name)
} else {
(Some(opts.to_string()), crate_name.to_string())
}
}
};

if !valid_crate_name(&crate_name, unstable_opts) {
let mut error = early_dcx.early_struct_fatal(format!(
"crate name `{crate_name}` passed to `--extern` is not a valid ASCII identifier"
));
let adjusted_name = crate_name.replace('-', "_");
if is_ascii_ident(&adjusted_name) {
#[allow(rustc::diagnostic_outside_of_impl)] // FIXME
error
.help(format!("consider replacing the dashes with underscores: `{adjusted_name}`"));
}
return Err(error);
}

Ok(ExternOpt { crate_name, path, options })
}

fn valid_crate_name(name: &str, unstable_opts: &UnstableOptions) -> bool {
match name.split_once("::") {
Some((a, b)) if unstable_opts.namespaced_crates => is_ascii_ident(a) && is_ascii_ident(b),
Some(_) => false,
None => is_ascii_ident(name),
}
}

fn is_ascii_ident(string: &str) -> bool {
let mut chars = string.chars();
if let Some(start) = chars.next()
&& (start.is_ascii_alphabetic() || start == '_')
{
chars.all(|char| char.is_ascii_alphanumeric() || char == '_')
} else {
false
}
}
92 changes: 92 additions & 0 deletions compiler/rustc_session/src/config/externs/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
use std::path::PathBuf;

use super::split_extern_opt;
use crate::EarlyDiagCtxt;
use crate::config::UnstableOptions;

/// Verifies split_extern_opt handles the supported cases.
#[test]
fn test_split_extern_opt() {
let early_dcx = EarlyDiagCtxt::new(<_>::default());
let unstable_opts = &UnstableOptions::default();

let extern_opt =
split_extern_opt(&early_dcx, unstable_opts, "priv,noprelude:foo=libbar.rlib").unwrap();
assert_eq!(extern_opt.crate_name, "foo");
assert_eq!(extern_opt.path, Some(PathBuf::from("libbar.rlib")));
assert_eq!(extern_opt.options, Some("priv,noprelude".to_string()));

let extern_opt = split_extern_opt(&early_dcx, unstable_opts, "priv,noprelude:foo").unwrap();
assert_eq!(extern_opt.crate_name, "foo");
assert_eq!(extern_opt.path, None);
assert_eq!(extern_opt.options, Some("priv,noprelude".to_string()));

let extern_opt = split_extern_opt(&early_dcx, unstable_opts, "foo=libbar.rlib").unwrap();
assert_eq!(extern_opt.crate_name, "foo");
assert_eq!(extern_opt.path, Some(PathBuf::from("libbar.rlib")));
assert_eq!(extern_opt.options, None);

let extern_opt = split_extern_opt(&early_dcx, unstable_opts, "foo").unwrap();
assert_eq!(extern_opt.crate_name, "foo");
assert_eq!(extern_opt.path, None);
assert_eq!(extern_opt.options, None);
}

/// Tests some invalid cases for split_extern_opt.
#[test]
fn test_split_extern_opt_invalid() {
let early_dcx = EarlyDiagCtxt::new(<_>::default());
let unstable_opts = &UnstableOptions::default();

// too many `:`s
let result = split_extern_opt(&early_dcx, unstable_opts, "priv:noprelude:foo=libbar.rlib");
assert!(result.is_err());
let _ = result.map_err(|e| e.cancel());

// can't nest externs without the unstable flag
let result = split_extern_opt(&early_dcx, unstable_opts, "noprelude:foo::bar=libbar.rlib");
assert!(result.is_err());
let _ = result.map_err(|e| e.cancel());
}

/// Tests some cases for split_extern_opt with nested crates like `foo::bar`.
#[test]
fn test_split_extern_opt_nested() {
let early_dcx = EarlyDiagCtxt::new(<_>::default());
let unstable_opts = &UnstableOptions { namespaced_crates: true, ..Default::default() };

let extern_opt =
split_extern_opt(&early_dcx, unstable_opts, "priv,noprelude:foo::bar=libbar.rlib").unwrap();
assert_eq!(extern_opt.crate_name, "foo::bar");
assert_eq!(extern_opt.path, Some(PathBuf::from("libbar.rlib")));
assert_eq!(extern_opt.options, Some("priv,noprelude".to_string()));

let extern_opt =
split_extern_opt(&early_dcx, unstable_opts, "priv,noprelude:foo::bar").unwrap();
assert_eq!(extern_opt.crate_name, "foo::bar");
assert_eq!(extern_opt.path, None);
assert_eq!(extern_opt.options, Some("priv,noprelude".to_string()));

let extern_opt = split_extern_opt(&early_dcx, unstable_opts, "foo::bar=libbar.rlib").unwrap();
assert_eq!(extern_opt.crate_name, "foo::bar");
assert_eq!(extern_opt.path, Some(PathBuf::from("libbar.rlib")));
assert_eq!(extern_opt.options, None);

let extern_opt = split_extern_opt(&early_dcx, unstable_opts, "foo::bar").unwrap();
assert_eq!(extern_opt.crate_name, "foo::bar");
assert_eq!(extern_opt.path, None);
assert_eq!(extern_opt.options, None);
}

/// Tests some invalid cases for split_extern_opt with nested crates like `foo::bar`.
#[test]
fn test_split_extern_opt_nested_invalid() {
let early_dcx = EarlyDiagCtxt::new(<_>::default());
let unstable_opts = &UnstableOptions { namespaced_crates: true, ..Default::default() };

// crates can only be nested one deep.
let result =
split_extern_opt(&early_dcx, unstable_opts, "priv,noprelude:foo::bar::baz=libbar.rlib");
assert!(result.is_err());
let _ = result.map_err(|e| e.cancel());
}
2 changes: 2 additions & 0 deletions compiler/rustc_session/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2334,6 +2334,8 @@ options! {
"the size at which the `large_assignments` lint starts to be emitted"),
mutable_noalias: bool = (true, parse_bool, [TRACKED],
"emit noalias metadata for mutable references (default: yes)"),
namespaced_crates: bool = (false, parse_bool, [TRACKED],
"allow crates to be namespaced by other crates (default: no)"),
next_solver: NextSolverConfig = (NextSolverConfig::default(), parse_next_solver_config, [TRACKED],
"enable and configure the next generation trait solver used by rustc"),
nll_facts: bool = (false, parse_bool, [UNTRACKED],
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1068,7 +1068,6 @@ symbols! {
ge,
gen_blocks,
gen_future,
gen_kill,
generator_clone,
generators,
generic_arg_infer,
Expand Down
37 changes: 24 additions & 13 deletions src/bootstrap/src/core/build_steps/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,19 @@ fn update_rustfmt_version(build: &Builder<'_>) {
let Some((version, stamp_file)) = get_rustfmt_version(build) else {
return;
};
t!(std::fs::write(stamp_file.path(), version))

t!(stamp_file.add_stamp(version).write());
}

/// Returns the Rust files modified between the `merge-base` of HEAD and
/// rust-lang/master and what is now on the disk. Does not include removed files.
/// Returns the Rust files modified between the last merge commit and what is now on the disk.
/// Does not include removed files.
///
/// Returns `None` if all files should be formatted.
fn get_modified_rs_files(build: &Builder<'_>) -> Result<Option<Vec<String>>, String> {
// In CI `get_git_modified_files` returns something different to normal environment.
// This shouldn't be called in CI anyway.
assert!(!build.config.is_running_on_ci);

if !verify_rustfmt_version(build) {
return Ok(None);
}
Expand All @@ -103,7 +108,7 @@ struct RustfmtConfig {

// Prints output describing a collection of paths, with lines such as "formatted modified file
// foo/bar/baz" or "skipped 20 untracked files".
fn print_paths(build: &Builder<'_>, verb: &str, adjective: Option<&str>, paths: &[String]) {
fn print_paths(verb: &str, adjective: Option<&str>, paths: &[String]) {
let len = paths.len();
let adjective =
if let Some(adjective) = adjective { format!("{adjective} ") } else { String::new() };
Expand All @@ -114,9 +119,6 @@ fn print_paths(build: &Builder<'_>, verb: &str, adjective: Option<&str>, paths:
} else {
println!("fmt: {verb} {len} {adjective}files");
}
if len > 1000 && !build.config.is_running_on_ci {
println!("hint: if this number seems too high, try running `git fetch origin master`");
}
}

pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) {
Expand Down Expand Up @@ -189,7 +191,7 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) {
)
.map(|x| x.to_string())
.collect();
print_paths(build, "skipped", Some("untracked"), &untracked_paths);
print_paths("skipped", Some("untracked"), &untracked_paths);

for untracked_path in untracked_paths {
// The leading `/` makes it an exact match against the
Expand All @@ -212,7 +214,13 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) {
override_builder.add(&format!("/{file}")).expect(&file);
}
}
Ok(None) => {}
Ok(None) => {
// NOTE: `Ok(None)` signifies that we need to format all files.
// The tricky part here is that if `override_builder` isn't given any white
// list files (i.e. files to be formatted, added without leading `!`), it
// will instead look for *all* files. So, by doing nothing here, we are
// actually making it so we format all files.
}
Err(err) => {
eprintln!("fmt warning: Something went wrong running git commands:");
eprintln!("fmt warning: {err}");
Expand Down Expand Up @@ -318,7 +326,7 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) {
});
let mut paths = formatted_paths.into_inner().unwrap();
paths.sort();
print_paths(build, if check { "checked" } else { "formatted" }, adjective, &paths);
print_paths(if check { "checked" } else { "formatted" }, adjective, &paths);

drop(tx);

Expand All @@ -328,7 +336,10 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) {
crate::exit!(1);
}

if !check {
update_rustfmt_version(build);
}
// Update `build/.rustfmt-stamp`, allowing this code to ignore files which have not been changed
// since last merge.
//
// NOTE: Because of the exit above, this is only reachable if formatting / format checking
// succeeded. So we are not commiting the version if formatting was not good.
update_rustfmt_version(build);
}
Loading
Loading