Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
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