Skip to content

Commit f53995d

Browse files
committed
Make the current crate's name available in Session
Previously, this was only accessible with a full `TyCtxt`, or by looking at `sess.opts.crate_name`. The option is not reliable though -- it doesn't consider `#![crate_name]` and doesn't infer the name from the file stem. Add all variants of the crate name to `Session` instead: - Add a new `CrateName` struct to make it more clear what's going on - Distinguish between the crate name and filestem (previously the filestem was often called the crate name even though it was unnormalized) - Add `is_build_script` helper - Distinguish between crate name and filestem in tools - Distinguish the normalized and unnormalized crate name while calculating the filestem - Remove unnecessary `crate_name` arguments
1 parent 9b4ae96 commit f53995d

File tree

32 files changed

+282
-188
lines changed

32 files changed

+282
-188
lines changed

compiler/rustc_codegen_ssa/src/back/link.rs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -107,14 +107,14 @@ pub fn link_binary(
107107
});
108108

109109
if outputs.outputs.should_link() {
110-
let output = out_filename(sess, crate_type, outputs, crate_info.local_crate_name);
110+
let output = out_filename(sess, crate_type, outputs);
111111
let tmpdir = TempDirBuilder::new()
112112
.prefix("rustc")
113113
.tempdir_in(output.parent().unwrap_or_else(|| Path::new(".")))
114114
.unwrap_or_else(|error| sess.dcx().emit_fatal(errors::CreateTempDir { error }));
115115
let path = MaybeTempDir::new(tmpdir, sess.opts.cg.save_temps);
116116

117-
let crate_name = format!("{}", crate_info.local_crate_name);
117+
let crate_name = format!("{}", sess.crate_name());
118118
let out_filename = output.file_for_writing(
119119
outputs,
120120
OutputType::Exe,
@@ -2747,12 +2747,8 @@ fn add_order_independent_options(
27472747
cmd.optimize();
27482748

27492749
// Gather the set of NatVis files, if any, and write them out to a temp directory.
2750-
let natvis_visualizers = collect_natvis_visualizers(
2751-
tmpdir,
2752-
sess,
2753-
&crate_info.local_crate_name,
2754-
&crate_info.natvis_debugger_visualizers,
2755-
);
2750+
let natvis_visualizers =
2751+
collect_natvis_visualizers(tmpdir, sess, &crate_info.natvis_debugger_visualizers);
27562752

27572753
// Pass debuginfo, NatVis debugger visualizers and strip flags down to the linker.
27582754
cmd.debuginfo(sess.opts.cg.strip, &natvis_visualizers);
@@ -2783,13 +2779,12 @@ fn add_order_independent_options(
27832779
fn collect_natvis_visualizers(
27842780
tmpdir: &Path,
27852781
sess: &Session,
2786-
crate_name: &Symbol,
27872782
natvis_debugger_visualizers: &BTreeSet<DebuggerVisualizerFile>,
27882783
) -> Vec<PathBuf> {
27892784
let mut visualizer_paths = Vec::with_capacity(natvis_debugger_visualizers.len());
27902785

27912786
for (index, visualizer) in natvis_debugger_visualizers.iter().enumerate() {
2792-
let visualizer_out_file = tmpdir.join(format!("{}-{}.natvis", crate_name.as_str(), index));
2787+
let visualizer_out_file = tmpdir.join(format!("{}-{}.natvis", sess.crate_name(), index));
27932788

27942789
match fs::write(&visualizer_out_file, &visualizer.src) {
27952790
Ok(()) => {

compiler/rustc_driver_impl/src/lib.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ use rustc_session::config::{
5656
use rustc_session::getopts::{self, Matches};
5757
use rustc_session::lint::{Lint, LintId};
5858
use rustc_session::output::invalid_output_for_target;
59-
use rustc_session::{EarlyDiagCtxt, Session, config};
59+
use rustc_session::{CrateName, EarlyDiagCtxt, Session, config};
6060
use rustc_span::def_id::LOCAL_CRATE;
6161
use rustc_span::{DUMMY_SP, FileName};
6262
use rustc_target::json::ToJson;
@@ -589,6 +589,12 @@ fn process_rlink(sess: &Session, compiler: &interface::Compiler) {
589589
};
590590
}
591591
};
592+
593+
// This is the first point at which we have both a Session and the crate name.
594+
let name = CrateName::from_normalized(sess, crate_info.local_crate_name, None);
595+
#[expect(deprecated, reason = "we never previously loaded the crate name")]
596+
sess.crate_name.set(name).expect("-Zlink-only should not build a full TyCtxt");
597+
592598
compiler.codegen_backend.link(sess, compiled_modules, crate_info, metadata, &outputs);
593599
} else {
594600
dcx.emit_fatal(RlinkNotAFile {});
@@ -683,8 +689,8 @@ fn print_crate_info(
683689
// no crate attributes, print out an error and exit
684690
return Compilation::Continue;
685691
};
686-
let t_outputs = rustc_interface::util::build_output_filenames(attrs, sess);
687-
let crate_name = passes::get_crate_name(sess, attrs);
692+
passes::load_crate_name(sess, attrs);
693+
let t_outputs = rustc_interface::util::build_output_filenames(sess);
688694
let crate_types = collect_crate_types(
689695
sess,
690696
&codegen_backend.supported_crate_types(sess),
@@ -693,9 +699,7 @@ fn print_crate_info(
693699
DUMMY_SP,
694700
);
695701
for &style in &crate_types {
696-
let fname = rustc_session::output::filename_for_input(
697-
sess, style, crate_name, &t_outputs,
698-
);
702+
let fname = rustc_session::output::filename_for_input(sess, style, &t_outputs);
699703
println_info!("{}", fname.as_path().file_name().unwrap().to_string_lossy());
700704
}
701705
}
@@ -704,16 +708,17 @@ fn print_crate_info(
704708
// no crate attributes, print out an error and exit
705709
return Compilation::Continue;
706710
};
707-
println_info!("{}", passes::get_crate_name(sess, attrs));
711+
passes::load_crate_name(sess, attrs);
712+
println_info!("{}", sess.crate_name());
708713
}
709714
CrateRootLintLevels => {
710715
let Some(attrs) = attrs.as_ref() else {
711716
// no crate attributes, print out an error and exit
712717
return Compilation::Continue;
713718
};
714-
let crate_name = passes::get_crate_name(sess, attrs);
719+
passes::load_crate_name(sess, attrs);
715720
let lint_store = crate::unerased_lint_store(sess);
716-
let features = rustc_expand::config::features(sess, attrs, crate_name);
721+
let features = rustc_expand::config::features(sess, attrs);
717722
let registered_tools =
718723
rustc_resolve::registered_tools_ast(sess.dcx(), attrs, sess, &features);
719724
let lint_levels = rustc_lint::LintLevelsBuilder::crate_root(

compiler/rustc_expand/src/config.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ pub struct StripUnconfigured<'a> {
4646
pub lint_node_id: NodeId,
4747
}
4848

49-
pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) -> Features {
49+
pub fn features(sess: &Session, krate_attrs: &[Attribute]) -> Features {
50+
let crate_name = sess.crate_name();
5051
let mut features = Features::default();
5152

5253
if let Some(hir::Attribute::Parsed(AttributeKind::Feature(feature_idents, _))) =

compiler/rustc_incremental/src/persist/fs.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,6 @@ use rustc_data_structures::{base_n, flock};
117117
use rustc_fs_util::{LinkOrCopy, link_or_copy, try_canonicalize};
118118
use rustc_middle::bug;
119119
use rustc_session::{Session, StableCrateId};
120-
use rustc_span::Symbol;
121120
use tracing::debug;
122121

123122
use crate::errors;
@@ -210,11 +209,7 @@ pub fn in_incr_comp_dir(incr_comp_session_dir: &Path, file_name: &str) -> PathBu
210209
/// The garbage collection will take care of it.
211210
///
212211
/// [`rustc_interface::queries::dep_graph`]: ../../rustc_interface/struct.Queries.html#structfield.dep_graph
213-
pub(crate) fn prepare_session_directory(
214-
sess: &Session,
215-
crate_name: Symbol,
216-
stable_crate_id: StableCrateId,
217-
) {
212+
pub(crate) fn prepare_session_directory(sess: &Session, stable_crate_id: StableCrateId) {
218213
if sess.opts.incremental.is_none() {
219214
return;
220215
}
@@ -224,7 +219,7 @@ pub(crate) fn prepare_session_directory(
224219
debug!("prepare_session_directory");
225220

226221
// {incr-comp-dir}/{crate-name-and-disambiguator}
227-
let crate_dir = crate_path(sess, crate_name, stable_crate_id);
222+
let crate_dir = crate_path(sess, stable_crate_id);
228223
debug!("crate-dir: {}", crate_dir.display());
229224
create_dir(sess, &crate_dir, "crate");
230225

@@ -597,11 +592,14 @@ fn string_to_timestamp(s: &str) -> Result<SystemTime, &'static str> {
597592
Ok(UNIX_EPOCH + duration)
598593
}
599594

600-
fn crate_path(sess: &Session, crate_name: Symbol, stable_crate_id: StableCrateId) -> PathBuf {
595+
fn crate_path(sess: &Session, stable_crate_id: StableCrateId) -> PathBuf {
601596
let incr_dir = sess.opts.incremental.as_ref().unwrap().clone();
602597

603-
let crate_name =
604-
format!("{crate_name}-{}", stable_crate_id.as_u64().to_base_fixed_len(CASE_INSENSITIVE));
598+
let crate_name = format!(
599+
"{}-{}",
600+
sess.crate_name(),
601+
stable_crate_id.as_u64().to_base_fixed_len(CASE_INSENSITIVE)
602+
);
605603
incr_dir.join(crate_name)
606604
}
607605

compiler/rustc_incremental/src/persist/load.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use rustc_serialize::Decodable;
1212
use rustc_serialize::opaque::MemDecoder;
1313
use rustc_session::config::IncrementalStateAssertion;
1414
use rustc_session::{Session, StableCrateId};
15-
use rustc_span::Symbol;
1615
use tracing::{debug, warn};
1716

1817
use super::data::*;
@@ -205,13 +204,9 @@ pub fn load_query_result_cache(sess: &Session) -> Option<OnDiskCache> {
205204

206205
/// Setups the dependency graph by loading an existing graph from disk and set up streaming of a
207206
/// new graph to an incremental session directory.
208-
pub fn setup_dep_graph(
209-
sess: &Session,
210-
crate_name: Symbol,
211-
stable_crate_id: StableCrateId,
212-
) -> DepGraph {
207+
pub fn setup_dep_graph(sess: &Session, stable_crate_id: StableCrateId) -> DepGraph {
213208
// `load_dep_graph` can only be called after `prepare_session_directory`.
214-
prepare_session_directory(sess, crate_name, stable_crate_id);
209+
prepare_session_directory(sess, stable_crate_id);
215210

216211
let res = sess.opts.build_dep_graph().then(|| load_dep_graph(sess));
217212

compiler/rustc_interface/src/passes.rs

Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@ use rustc_parse::lexer::StripTokens;
3333
use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal};
3434
use rustc_passes::{abi_test, input_stats, layout_test};
3535
use rustc_resolve::{Resolver, ResolverOutputs};
36-
use rustc_session::Session;
3736
use rustc_session::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType};
3837
use rustc_session::cstore::Untracked;
3938
use rustc_session::output::{filename_for_input, invalid_output_for_target};
4039
use rustc_session::parse::feature_err;
4140
use rustc_session::search_paths::PathKind;
41+
use rustc_session::{CrateName, Session};
4242
use rustc_span::{
4343
DUMMY_SP, ErrorGuaranteed, ExpnKind, SourceFileHash, SourceFileHashAlgorithm, Span, Symbol, sym,
4444
};
@@ -309,14 +309,13 @@ fn configure_and_expand(
309309
fn print_macro_stats(ecx: &ExtCtxt<'_>) {
310310
use std::fmt::Write;
311311

312-
let crate_name = ecx.ecfg.crate_name.as_str();
313-
let crate_name = if crate_name == "build_script_build" {
312+
let crate_name = if ecx.ecfg.crate_name == sym::build_script_build {
314313
// This is a build script. Get the package name from the environment.
315314
let pkg_name =
316315
std::env::var("CARGO_PKG_NAME").unwrap_or_else(|_| "<unknown crate>".to_string());
317316
format!("{pkg_name} build script")
318317
} else {
319-
crate_name.to_string()
318+
ecx.ecfg.crate_name.to_string()
320319
};
321320

322321
// No instability because we immediately sort the produced vector.
@@ -508,7 +507,6 @@ fn generated_output_paths(
508507
tcx: TyCtxt<'_>,
509508
outputs: &OutputFilenames,
510509
exact_name: bool,
511-
crate_name: Symbol,
512510
) -> Vec<PathBuf> {
513511
let sess = tcx.sess;
514512
let mut out_filenames = Vec::new();
@@ -520,7 +518,7 @@ fn generated_output_paths(
520518
// by appending `.rlib`, `.exe`, etc., so we can skip this transformation.
521519
OutputType::Exe if !exact_name => {
522520
for crate_type in tcx.crate_types().iter() {
523-
let p = filename_for_input(sess, *crate_type, crate_name, outputs);
521+
let p = filename_for_input(sess, *crate_type, outputs);
524522
out_filenames.push(p.as_path().to_path_buf());
525523
}
526524
}
@@ -814,11 +812,9 @@ pub fn write_dep_info(tcx: TyCtxt<'_>) {
814812

815813
let sess = tcx.sess;
816814
let _timer = sess.timer("write_dep_info");
817-
let crate_name = tcx.crate_name(LOCAL_CRATE);
818815

819816
let outputs = tcx.output_filenames(());
820-
let output_paths =
821-
generated_output_paths(tcx, outputs, sess.io.output_file.is_some(), crate_name);
817+
let output_paths = generated_output_paths(tcx, outputs, sess.io.output_file.is_some());
822818

823819
// Ensure the source file isn't accidentally overwritten during compilation.
824820
if let Some(input_path) = sess.io.input.opt_path() {
@@ -920,7 +916,8 @@ pub fn create_and_enter_global_ctxt<T, F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> T>(
920916

921917
let pre_configured_attrs = rustc_expand::config::pre_configure_attrs(sess, &krate.attrs);
922918

923-
let crate_name = get_crate_name(sess, &pre_configured_attrs);
919+
load_crate_name(sess, &pre_configured_attrs);
920+
924921
let crate_types = collect_crate_types(
925922
sess,
926923
&compiler.codegen_backend.supported_crate_types(sess),
@@ -929,15 +926,15 @@ pub fn create_and_enter_global_ctxt<T, F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> T>(
929926
krate.spans.inner_span,
930927
);
931928
let stable_crate_id = StableCrateId::new(
932-
crate_name,
929+
sess.crate_name(),
933930
crate_types.contains(&CrateType::Executable),
934931
sess.opts.cg.metadata.clone(),
935932
sess.cfg_version,
936933
);
937934

938-
let outputs = util::build_output_filenames(&pre_configured_attrs, sess);
935+
let outputs = util::build_output_filenames(sess);
939936

940-
let dep_graph = setup_dep_graph(sess, crate_name, stable_crate_id);
937+
let dep_graph = setup_dep_graph(sess, stable_crate_id);
941938

942939
let cstore =
943940
FreezeLock::new(Box::new(CStore::new(compiler.codegen_backend.metadata_loader())) as _);
@@ -1001,14 +998,12 @@ pub fn create_and_enter_global_ctxt<T, F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> T>(
1001998
|tcx| {
1002999
let feed = tcx.create_crate_num(stable_crate_id).unwrap();
10031000
assert_eq!(feed.key(), LOCAL_CRATE);
1004-
feed.crate_name(crate_name);
1001+
feed.crate_name(sess.crate_name());
10051002

10061003
let feed = tcx.feed_unit_query();
1007-
feed.features_query(tcx.arena.alloc(rustc_expand::config::features(
1008-
tcx.sess,
1009-
&pre_configured_attrs,
1010-
crate_name,
1011-
)));
1004+
feed.features_query(
1005+
tcx.arena.alloc(rustc_expand::config::features(tcx.sess, &pre_configured_attrs)),
1006+
);
10121007
feed.crate_for_resolver(tcx.arena.alloc(Steal::new((krate, pre_configured_attrs))));
10131008
feed.output_filenames(Arc::new(outputs));
10141009

@@ -1257,8 +1252,25 @@ pub(crate) fn start_codegen<'tcx>(
12571252
(codegen, crate_info, metadata)
12581253
}
12591254

1260-
/// Compute and validate the crate name.
1261-
pub fn get_crate_name(sess: &Session, krate_attrs: &[ast::Attribute]) -> Symbol {
1255+
/// Compute and validate the crate name, then store it on the Session.
1256+
///
1257+
/// NOTE: this function will panic if called more than once in the same Session.
1258+
#[expect(deprecated, reason = "initial crate name loading")]
1259+
#[track_caller]
1260+
pub fn load_crate_name(sess: &Session, krate_attrs: &[ast::Attribute]) {
1261+
let new_name = get_crate_name(sess, krate_attrs);
1262+
1263+
// When we have `--print=file-names,crate-name`, we try to load the crate name more than once.
1264+
// Rather than panicking, just allow that as long as we'd use the same name both times.
1265+
if let Some(existing) = sess.crate_name.get()
1266+
&& *existing == new_name
1267+
{
1268+
return;
1269+
}
1270+
sess.crate_name.set(new_name).expect("`load_crate_name` called more than once!");
1271+
}
1272+
1273+
fn get_crate_name(sess: &Session, krate_attrs: &[ast::Attribute]) -> CrateName {
12621274
// We validate *all* occurrences of `#![crate_name]`, pick the first find and
12631275
// if a crate name was passed on the command line via `--crate-name` we enforce
12641276
// that they match.
@@ -1269,11 +1281,7 @@ pub fn get_crate_name(sess: &Session, krate_attrs: &[ast::Attribute]) -> Symbol
12691281
let attr_crate_name =
12701282
parse_crate_name(sess, krate_attrs, ShouldEmit::EarlyFatal { also_emit_lints: true });
12711283

1272-
let validate = |name, span| {
1273-
rustc_session::output::validate_crate_name(sess, name, span);
1274-
name
1275-
};
1276-
1284+
#[expect(deprecated, reason = "sess.crate_name isn't set yet")]
12771285
if let Some(crate_name) = &sess.opts.crate_name {
12781286
let crate_name = Symbol::intern(crate_name);
12791287
if let Some((attr_crate_name, span)) = attr_crate_name
@@ -1285,11 +1293,11 @@ pub fn get_crate_name(sess: &Session, krate_attrs: &[ast::Attribute]) -> Symbol
12851293
attr_crate_name,
12861294
});
12871295
}
1288-
return validate(crate_name, None);
1296+
return CrateName::from_normalized(sess, crate_name, None);
12891297
}
12901298

12911299
if let Some((crate_name, span)) = attr_crate_name {
1292-
return validate(crate_name, Some(span));
1300+
return CrateName::from_normalized(sess, crate_name, Some(span));
12931301
}
12941302

12951303
if let Input::File(ref path) = sess.io.input
@@ -1298,11 +1306,11 @@ pub fn get_crate_name(sess: &Session, krate_attrs: &[ast::Attribute]) -> Symbol
12981306
if file_stem.starts_with('-') {
12991307
sess.dcx().emit_err(errors::CrateNameInvalid { crate_name: file_stem });
13001308
} else {
1301-
return validate(Symbol::intern(&file_stem.replace('-', "_")), None);
1309+
return CrateName::from_unnormalized(sess, file_stem, None);
13021310
}
13031311
}
13041312

1305-
sym::rust_out
1313+
CrateName::from_normalized(sess, sym::rust_out, None)
13061314
}
13071315

13081316
pub(crate) fn parse_crate_name(

0 commit comments

Comments
 (0)