]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_interface/src/passes.rs
bump version to 1.80.1+dfsg1-1~bpo12+pve1
[rustc.git] / compiler / rustc_interface / src / passes.rs
CommitLineData
9ffffee4 1use crate::errors;
532ac7d7 2use crate::interface::{Compiler, Result};
532ac7d7 3use crate::proc_macro_decls;
dfeec247 4use crate::util;
532ac7d7 5
5099ac24 6use rustc_ast::{self as ast, visit};
ba9703b0 7use rustc_codegen_ssa::traits::CodegenBackend;
17df50a5 8use rustc_data_structures::parallel;
9ffffee4 9use rustc_data_structures::steal::Steal;
781aab86 10use rustc_data_structures::sync::{Lrc, OnceLock, WorkerLocal};
9ffffee4 11use rustc_errors::PResult;
353b0b11 12use rustc_expand::base::{ExtCtxt, LintStoreExpand};
add651ee 13use rustc_feature::Features;
353b0b11 14use rustc_fs_util::try_canonicalize;
9ffffee4
FG
15use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE};
16use rustc_lint::{unerased_lint_store, BufferedEarlyLint, EarlyCheckNode, LintStore};
cdc7bbd5 17use rustc_metadata::creader::CStore;
ba9703b0
XL
18use rustc_middle::arena::Arena;
19use rustc_middle::dep_graph::DepGraph;
923072b8 20use rustc_middle::ty::{self, GlobalCtxt, RegisteredTools, TyCtxt};
781aab86 21use rustc_middle::util::Providers;
31ef2f64
FG
22use rustc_parse::{
23 new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal, validate_attr,
24};
4b012472 25use rustc_passes::{abi_test, hir_stats, layout_test};
9ffffee4 26use rustc_resolve::Resolver;
fe692bf9
FG
27use rustc_session::code_stats::VTableSizeInfo;
28use rustc_session::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType};
ed00b5ec 29use rustc_session::cstore::Untracked;
064997fb 30use rustc_session::output::filename_for_input;
ba9703b0 31use rustc_session::search_paths::PathKind;
c295e0f8 32use rustc_session::{Limit, Session};
5099ac24 33use rustc_span::symbol::{sym, Symbol};
04454e1e 34use rustc_span::FileName;
9c376795 35use rustc_target::spec::PanicStrategy;
ba9703b0 36use rustc_trait_selection::traits;
532ac7d7
XL
37
38use std::any::Any;
532ac7d7 39use std::ffi::OsString;
74b04a01 40use std::io::{self, BufWriter, Write};
3c0e092e 41use std::path::{Path, PathBuf};
4b012472 42use std::sync::LazyLock;
17df50a5 43use std::{env, fs, iter};
31ef2f64 44use tracing::{info, instrument};
532ac7d7 45
9c376795 46pub fn parse<'a>(sess: &'a Session) -> PResult<'a, ast::Crate> {
31ef2f64
FG
47 let krate = sess.time("parse_crate", || {
48 let mut parser = unwrap_or_emit_fatal(match &sess.io.input {
49 Input::File(file) => new_parser_from_file(&sess.psess, file, None),
50 Input::Str { input, name } => {
51 new_parser_from_source_str(&sess.psess, name.clone(), input.clone())
52 }
53 });
54 parser.parse_crate_mod()
532ac7d7 55 })?;
532ac7d7 56
064997fb 57 if sess.opts.unstable_opts.input_stats {
6a06907d
XL
58 eprintln!("Lines of code: {}", sess.source_map().count_lines());
59 eprintln!("Pre-expansion node count: {}", count_nodes(&krate));
532ac7d7
XL
60 }
61
064997fb 62 if let Some(ref s) = sess.opts.unstable_opts.show_span {
4b012472 63 rustc_ast_passes::show_span::run(sess.dcx(), s, &krate);
532ac7d7
XL
64 }
65
064997fb 66 if sess.opts.unstable_opts.hir_stats {
f2b60f7d 67 hir_stats::print_ast_stats(&krate, "PRE EXPANSION AST STATS", "ast-stats-1");
532ac7d7
XL
68 }
69
70 Ok(krate)
71}
72
73fn count_nodes(krate: &ast::Crate) -> usize {
74b04a01 74 let mut counter = rustc_ast_passes::node_count::NodeCounter::new();
532ac7d7
XL
75 visit::walk_crate(&mut counter, krate);
76 counter.count
77}
78
5099ac24 79fn pre_expansion_lint<'a>(
5869c6ff 80 sess: &Session,
add651ee 81 features: &Features,
5869c6ff 82 lint_store: &LintStore,
5099ac24
FG
83 registered_tools: &RegisteredTools,
84 check_node: impl EarlyCheckNode<'a>,
487cf647 85 node_name: Symbol,
5869c6ff 86) {
487cf647
FG
87 sess.prof.generic_activity_with_arg("pre_AST_expansion_lint_checks", node_name.as_str()).run(
88 || {
89 rustc_lint::check_ast_node(
90 sess,
add651ee 91 features,
487cf647
FG
92 true,
93 lint_store,
94 registered_tools,
95 None,
96 rustc_lint::BuiltinCombinedPreExpansionLintPass::new(),
97 check_node,
98 );
99 },
100 );
ba9703b0
XL
101}
102
5099ac24
FG
103// Cannot implement directly for `LintStore` due to trait coherence.
104struct LintStoreExpandImpl<'a>(&'a LintStore);
105
106impl LintStoreExpand for LintStoreExpandImpl<'_> {
107 fn pre_expansion_lint(
108 &self,
109 sess: &Session,
add651ee 110 features: &Features,
5099ac24
FG
111 registered_tools: &RegisteredTools,
112 node_id: ast::NodeId,
113 attrs: &[ast::Attribute],
114 items: &[rustc_ast::ptr::P<ast::Item>],
487cf647 115 name: Symbol,
5099ac24 116 ) {
add651ee 117 pre_expansion_lint(sess, features, self.0, registered_tools, (node_id, attrs, items), name);
5099ac24
FG
118 }
119}
120
4b012472 121/// Runs the "early phases" of the compiler: initial `cfg` processing,
136023e0
XL
122/// syntax expansion, secondary `cfg` expansion, synthesis of a test
123/// harness if one is to be provided, injection of a dependency on the
124/// standard library and prelude, and name resolution.
9ffffee4 125#[instrument(level = "trace", skip(krate, resolver))]
353b0b11
FG
126fn configure_and_expand(
127 mut krate: ast::Crate,
128 pre_configured_attrs: &[ast::Attribute],
129 resolver: &mut Resolver<'_, '_>,
130) -> ast::Crate {
9ffffee4
FG
131 let tcx = resolver.tcx();
132 let sess = tcx.sess;
add651ee 133 let features = tcx.features();
4b012472 134 let lint_store = unerased_lint_store(tcx.sess);
9ffffee4 135 let crate_name = tcx.crate_name(LOCAL_CRATE);
353b0b11 136 let lint_check_node = (&krate, pre_configured_attrs);
add651ee
FG
137 pre_expansion_lint(
138 sess,
139 features,
140 lint_store,
141 tcx.registered_tools(()),
142 lint_check_node,
143 crate_name,
144 );
136023e0 145 rustc_builtin_macros::register_builtin_macros(resolver);
e1599b0c 146
353b0b11
FG
147 let num_standard_library_imports = sess.time("crate_injection", || {
148 rustc_builtin_macros::standard_library_imports::inject(
149 &mut krate,
150 pre_configured_attrs,
151 resolver,
152 sess,
add651ee 153 features,
353b0b11 154 )
e1599b0c
XL
155 });
156
4b012472 157 util::check_attr_crate_type(sess, pre_configured_attrs, resolver.lint_buffer());
e74abb32 158
532ac7d7 159 // Expand all macros
dfeec247 160 krate = sess.time("macro_expand_crate", || {
532ac7d7
XL
161 // Windows dlls do not have rpaths, so they don't know how to find their
162 // dependencies. It's up to us to tell the system where to find all the
163 // dependent dlls. Note that this uses cfg!(windows) as opposed to
164 // targ_cfg because syntax extensions are always loaded for the host
165 // compiler, not for the target.
166 //
167 // This is somewhat of an inherently racy operation, however, as
168 // multiple threads calling this function could possibly continue
169 // extending PATH far beyond what it should. To solve this for now we
170 // just don't add any new elements to PATH which are already there
171 // within PATH. This is basically a targeted fix at #17360 for rustdoc
172 // which runs rustc in parallel but has been seen (#33844) to cause
173 // problems with PATH becoming too long.
174 let mut old_path = OsString::new();
175 if cfg!(windows) {
176 old_path = env::var_os("PATH").unwrap_or(old_path);
e8be2606
FG
177 let mut new_path = Vec::from_iter(
178 sess.host_filesearch(PathKind::All).search_paths().map(|p| p.dir.clone()),
179 );
532ac7d7
XL
180 for path in env::split_paths(&old_path) {
181 if !new_path.contains(&path) {
182 new_path.push(path);
183 }
184 }
185 env::set_var(
186 "PATH",
187 &env::join_paths(
dfeec247
XL
188 new_path.iter().filter(|p| env::join_paths(iter::once(p)).is_ok()),
189 )
190 .unwrap(),
532ac7d7
XL
191 );
192 }
193
194 // Create the config for macro expansion
353b0b11 195 let recursion_limit = get_recursion_limit(pre_configured_attrs, sess);
dfeec247 196 let cfg = rustc_expand::expand::ExpansionConfig {
add651ee
FG
197 crate_name: crate_name.to_string(),
198 features,
136023e0 199 recursion_limit,
064997fb 200 trace_mac: sess.opts.unstable_opts.trace_macros,
353b0b11 201 should_test: sess.is_test_crate(),
064997fb
FG
202 span_debug: sess.opts.unstable_opts.span_debug,
203 proc_macro_backtrace: sess.opts.unstable_opts.proc_macro_backtrace,
532ac7d7
XL
204 };
205
5099ac24
FG
206 let lint_store = LintStoreExpandImpl(lint_store);
207 let mut ecx = ExtCtxt::new(sess, cfg, resolver, Some(&lint_store));
353b0b11 208 ecx.num_standard_library_imports = num_standard_library_imports;
532ac7d7 209 // Expand macros now!
dfeec247 210 let krate = sess.time("expand_crate", || ecx.monotonic_expander().expand_crate(krate));
532ac7d7
XL
211
212 // The rest is error reporting
213
c620b35d 214 sess.psess.buffered_lints.with_lock(|buffered_lints: &mut Vec<BufferedEarlyLint>| {
064997fb
FG
215 buffered_lints.append(&mut ecx.buffered_early_lint);
216 });
217
dfeec247 218 sess.time("check_unused_macros", || {
532ac7d7
XL
219 ecx.check_unused_macros();
220 });
221
9ffffee4
FG
222 // If we hit a recursion limit, exit early to avoid later passes getting overwhelmed
223 // with a large AST
224 if ecx.reduced_recursion_limit.is_some() {
c0240ec0 225 sess.dcx().abort_if_errors();
9ffffee4
FG
226 unreachable!();
227 }
b9856134 228
532ac7d7
XL
229 if cfg!(windows) {
230 env::set_var("PATH", &old_path);
231 }
ba9703b0 232
9ffffee4
FG
233 krate
234 });
532ac7d7 235
dfeec247 236 sess.time("maybe_building_test_harness", || {
add651ee 237 rustc_builtin_macros::test_harness::inject(&mut krate, sess, features, resolver)
532ac7d7
XL
238 });
239
dfeec247 240 let has_proc_macro_decls = sess.time("AST_validation", || {
add651ee
FG
241 rustc_ast_passes::ast_validation::check_crate(
242 sess,
243 features,
244 &krate,
245 resolver.lint_buffer(),
246 )
532ac7d7
XL
247 });
248
add651ee 249 let crate_types = tcx.crate_types();
5099ac24 250 let is_executable_crate = crate_types.contains(&CrateType::Executable);
f9f354fc 251 let is_proc_macro_crate = crate_types.contains(&CrateType::ProcMacro);
e1599b0c 252
5099ac24
FG
253 if crate_types.len() > 1 {
254 if is_executable_crate {
c0240ec0 255 sess.dcx().emit_err(errors::MixedBinCrate);
5099ac24
FG
256 }
257 if is_proc_macro_crate {
c0240ec0 258 sess.dcx().emit_err(errors::MixedProcMacroCrate);
5099ac24
FG
259 }
260 }
261
9c376795 262 if is_proc_macro_crate && sess.panic_strategy() == PanicStrategy::Abort {
c0240ec0 263 sess.dcx().emit_warn(errors::ProcMacroCratePanicAbort);
9c376795
FG
264 }
265
353b0b11
FG
266 sess.time("maybe_create_a_macro_crate", || {
267 let is_test_crate = sess.is_test_crate();
9ffffee4 268 rustc_builtin_macros::proc_macro_harness::inject(
353b0b11 269 &mut krate,
9ffffee4 270 sess,
add651ee 271 features,
9ffffee4 272 resolver,
9ffffee4
FG
273 is_proc_macro_crate,
274 has_proc_macro_decls,
275 is_test_crate,
4b012472 276 sess.dcx(),
9ffffee4
FG
277 )
278 });
532ac7d7 279
532ac7d7
XL
280 // Done with macro expansion!
281
353b0b11
FG
282 resolver.resolve_crate(&krate);
283
284 krate
285}
286
287fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) {
288 let sess = tcx.sess;
c620b35d 289 let (resolver, krate) = &*tcx.resolver_for_lowering().borrow();
353b0b11
FG
290 let mut lint_buffer = resolver.lint_buffer.steal();
291
064997fb 292 if sess.opts.unstable_opts.input_stats {
4b012472 293 eprintln!("Post-expansion node count: {}", count_nodes(krate));
532ac7d7
XL
294 }
295
064997fb 296 if sess.opts.unstable_opts.hir_stats {
4b012472 297 hir_stats::print_ast_stats(krate, "POST EXPANSION AST STATS", "ast-stats-2");
532ac7d7
XL
298 }
299
532ac7d7 300 // Needs to go *after* expansion to be able to check the results of macro expansion.
dfeec247 301 sess.time("complete_gated_feature_checking", || {
4b012472 302 rustc_ast_passes::feature_gate::check_crate(krate, sess, tcx.features());
532ac7d7
XL
303 });
304
305 // Add all buffered lints from the `ParseSess` to the `Session`.
c620b35d 306 sess.psess.buffered_lints.with_lock(|buffered_lints| {
5e7ed085
FG
307 info!("{} parse sess buffered_lints", buffered_lints.len());
308 for early_lint in buffered_lints.drain(..) {
353b0b11 309 lint_buffer.add_early_lint(early_lint);
5e7ed085
FG
310 }
311 });
532ac7d7 312
3c0e092e 313 // Gate identifiers containing invalid Unicode codepoints that were recovered during lexing.
c620b35d
FG
314 sess.psess.bad_unicode_identifiers.with_lock(|identifiers| {
315 for (ident, mut spans) in identifiers.drain(..) {
3c0e092e 316 spans.sort();
a2a8927a
XL
317 if ident == sym::ferris {
318 let first_span = spans[0];
c0240ec0 319 sess.dcx().emit_err(errors::FerrisIdentifier { spans, first_span });
a2a8927a 320 } else {
c0240ec0 321 sess.dcx().emit_err(errors::EmojiIdentifier { spans, ident });
a2a8927a 322 }
3c0e092e
XL
323 }
324 });
325
4b012472 326 let lint_store = unerased_lint_store(tcx.sess);
353b0b11
FG
327 rustc_lint::check_ast_node(
328 sess,
add651ee 329 tcx.features(),
353b0b11
FG
330 false,
331 lint_store,
332 tcx.registered_tools(()),
333 Some(lint_buffer),
334 rustc_lint::BuiltinCombinedEarlyLintPass::new(),
335 (&**krate, &*krate.attrs),
336 )
532ac7d7
XL
337}
338
532ac7d7
XL
339// Returns all the paths that correspond to generated files.
340fn generated_output_paths(
add651ee 341 tcx: TyCtxt<'_>,
532ac7d7
XL
342 outputs: &OutputFilenames,
343 exact_name: bool,
487cf647 344 crate_name: Symbol,
532ac7d7 345) -> Vec<PathBuf> {
add651ee 346 let sess = tcx.sess;
532ac7d7
XL
347 let mut out_filenames = Vec::new();
348 for output_type in sess.opts.output_types.keys() {
fe692bf9
FG
349 let out_filename = outputs.path(*output_type);
350 let file = out_filename.as_path().to_path_buf();
532ac7d7
XL
351 match *output_type {
352 // If the filename has been overridden using `-o`, it will not be modified
353 // by appending `.rlib`, `.exe`, etc., so we can skip this transformation.
dfeec247 354 OutputType::Exe if !exact_name => {
add651ee 355 for crate_type in tcx.crate_types().iter() {
ba9703b0 356 let p = filename_for_input(sess, *crate_type, crate_name, outputs);
fe692bf9 357 out_filenames.push(p.as_path().to_path_buf());
dfeec247
XL
358 }
359 }
064997fb 360 OutputType::DepInfo if sess.opts.unstable_opts.dep_info_omit_d_target => {
532ac7d7
XL
361 // Don't add the dep-info output when omitting it from dep-info targets
362 }
fe692bf9
FG
363 OutputType::DepInfo if out_filename.is_stdout() => {
364 // Don't add the dep-info output when it goes to stdout
365 }
532ac7d7
XL
366 _ => {
367 out_filenames.push(file);
368 }
369 }
370 }
371 out_filenames
372}
373
3c0e092e 374fn output_contains_path(output_paths: &[PathBuf], input_path: &Path) -> bool {
353b0b11 375 let input_path = try_canonicalize(input_path).ok();
532ac7d7
XL
376 if input_path.is_none() {
377 return false;
378 }
ed00b5ec 379 output_paths.iter().any(|output_path| try_canonicalize(output_path).ok() == input_path)
532ac7d7
XL
380}
381
ed00b5ec
FG
382fn output_conflicts_with_dir(output_paths: &[PathBuf]) -> Option<&PathBuf> {
383 output_paths.iter().find(|output_path| output_path.is_dir())
532ac7d7
XL
384}
385
3c0e092e 386fn escape_dep_filename(filename: &str) -> String {
532ac7d7 387 // Apparently clang and gcc *only* escape spaces:
136023e0 388 // https://llvm.org/klaus/clang/commit/9d50634cfc268ecc9a7250226dd5ca0e945240d4
a2a8927a 389 filename.replace(' ', "\\ ")
532ac7d7
XL
390}
391
f035d41b
XL
392// Makefile comments only need escaping newlines and `\`.
393// The result can be unescaped by anything that can unescape `escape_default` and friends.
394fn escape_dep_env(symbol: Symbol) -> String {
395 let s = symbol.as_str();
396 let mut escaped = String::with_capacity(s.len());
397 for c in s.chars() {
398 match c {
399 '\n' => escaped.push_str(r"\n"),
400 '\r' => escaped.push_str(r"\r"),
401 '\\' => escaped.push_str(r"\\"),
402 _ => escaped.push(c),
403 }
404 }
405 escaped
406}
407
353b0b11 408fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[PathBuf]) {
532ac7d7 409 // Write out dependency rules to the dep-info file if requested
353b0b11 410 let sess = tcx.sess;
532ac7d7
XL
411 if !sess.opts.output_types.contains_key(&OutputType::DepInfo) {
412 return;
413 }
fe692bf9
FG
414 let deps_output = outputs.path(OutputType::DepInfo);
415 let deps_filename = deps_output.as_path();
532ac7d7 416
9c376795 417 let result: io::Result<()> = try {
532ac7d7
XL
418 // Build a list of files used to compile the output and
419 // write Makefile-compatible dependency rules
dfeec247
XL
420 let mut files: Vec<String> = sess
421 .source_map()
532ac7d7
XL
422 .files()
423 .iter()
424 .filter(|fmap| fmap.is_real_file())
425 .filter(|fmap| !fmap.is_imported())
17df50a5 426 .map(|fmap| escape_dep_filename(&fmap.name.prefer_local().to_string()))
532ac7d7 427 .collect();
416331ca 428
136023e0
XL
429 // Account for explicitly marked-to-track files
430 // (e.g. accessed in proc macros).
c620b35d 431 let file_depinfo = sess.psess.file_depinfo.borrow();
f2b60f7d
FG
432
433 let normalize_path = |path: PathBuf| {
136023e0
XL
434 let file = FileName::from(path);
435 escape_dep_filename(&file.prefer_local().to_string())
f2b60f7d
FG
436 };
437
4b012472
FG
438 // The entries will be used to declare dependencies beween files in a
439 // Makefile-like output, so the iteration order does not matter.
440 #[allow(rustc::potential_query_instability)]
f2b60f7d
FG
441 let extra_tracked_files =
442 file_depinfo.iter().map(|path_sym| normalize_path(PathBuf::from(path_sym.as_str())));
136023e0
XL
443 files.extend(extra_tracked_files);
444
f2b60f7d
FG
445 // We also need to track used PGO profile files
446 if let Some(ref profile_instr) = sess.opts.cg.profile_use {
447 files.push(normalize_path(profile_instr.as_path().to_path_buf()));
448 }
449 if let Some(ref profile_sample) = sess.opts.unstable_opts.profile_sample_use {
450 files.push(normalize_path(profile_sample.as_path().to_path_buf()));
451 }
452
49aad941
FG
453 // Debugger visualizer files
454 for debugger_visualizer in tcx.debugger_visualizers(LOCAL_CRATE) {
455 files.push(normalize_path(debugger_visualizer.path.clone().unwrap()));
456 }
457
416331ca 458 if sess.binary_dep_depinfo() {
064997fb 459 if let Some(ref backend) = sess.opts.unstable_opts.codegen_backend {
04454e1e
FG
460 if backend.contains('.') {
461 // If the backend name contain a `.`, it is the path to an external dynamic
462 // library. If not, it is not a path.
463 files.push(backend.to_string());
464 }
465 }
466
353b0b11
FG
467 for &cnum in tcx.crates(()) {
468 let source = tcx.used_crate_source(cnum);
9ffffee4
FG
469 if let Some((path, _)) = &source.dylib {
470 files.push(escape_dep_filename(&path.display().to_string()));
471 }
472 if let Some((path, _)) = &source.rlib {
473 files.push(escape_dep_filename(&path.display().to_string()));
474 }
475 if let Some((path, _)) = &source.rmeta {
476 files.push(escape_dep_filename(&path.display().to_string()));
416331ca 477 }
9ffffee4 478 }
416331ca
XL
479 }
480
fe692bf9
FG
481 let write_deps_to_file = |file: &mut dyn Write| -> io::Result<()> {
482 for path in out_filenames {
483 writeln!(file, "{}: {}\n", path.display(), files.join(" "))?;
484 }
532ac7d7 485
fe692bf9
FG
486 // Emit a fake target for each input file to the compilation. This
487 // prevents `make` from spitting out an error if a file is later
488 // deleted. For more info see #28735
489 for path in files {
490 writeln!(file, "{path}:")?;
491 }
f035d41b 492
fe692bf9 493 // Emit special comments with information about accessed environment variables.
c620b35d 494 let env_depinfo = sess.psess.env_depinfo.borrow();
fe692bf9 495 if !env_depinfo.is_empty() {
4b012472
FG
496 // We will soon sort, so the initial order does not matter.
497 #[allow(rustc::potential_query_instability)]
fe692bf9
FG
498 let mut envs: Vec<_> = env_depinfo
499 .iter()
500 .map(|(k, v)| (escape_dep_env(*k), v.map(escape_dep_env)))
501 .collect();
502 envs.sort_unstable();
f035d41b 503 writeln!(file)?;
fe692bf9
FG
504 for (k, v) in envs {
505 write!(file, "# env-dep:{k}")?;
506 if let Some(v) = v {
507 write!(file, "={v}")?;
508 }
509 writeln!(file)?;
510 }
511 }
512
513 Ok(())
514 };
515
516 match deps_output {
517 OutFileName::Stdout => {
518 let mut file = BufWriter::new(io::stdout());
519 write_deps_to_file(&mut file)?;
520 }
521 OutFileName::Real(ref path) => {
522 let mut file = BufWriter::new(fs::File::create(path)?);
523 write_deps_to_file(&mut file)?;
f035d41b
XL
524 }
525 }
9c376795 526 };
532ac7d7 527
416331ca
XL
528 match result {
529 Ok(_) => {
530 if sess.opts.json_artifact_notifications {
4b012472 531 sess.dcx().emit_artifact_notification(deps_filename, "dep-info");
416331ca 532 }
416331ca 533 }
f2b60f7d 534 Err(error) => {
c0240ec0 535 sess.dcx().emit_fatal(errors::ErrorWritingDependencies { path: deps_filename, error });
f2b60f7d 536 }
532ac7d7
XL
537 }
538}
539
c620b35d 540fn resolver_for_lowering_raw<'tcx>(
9ffffee4
FG
541 tcx: TyCtxt<'tcx>,
542 (): (),
c620b35d 543) -> (&'tcx Steal<(ty::ResolverAstLowering, Lrc<ast::Crate>)>, &'tcx ty::ResolverGlobalCtxt) {
9ffffee4 544 let arenas = Resolver::arenas();
353b0b11
FG
545 let _ = tcx.registered_tools(()); // Uses `crate_for_resolver`.
546 let (krate, pre_configured_attrs) = tcx.crate_for_resolver(()).steal();
547 let mut resolver = Resolver::new(tcx, &pre_configured_attrs, krate.spans.inner_span, &arenas);
548 let krate = configure_and_expand(krate, &pre_configured_attrs, &mut resolver);
9ffffee4
FG
549
550 // Make sure we don't mutate the cstore from here on.
781aab86 551 tcx.untracked().cstore.freeze();
9ffffee4
FG
552
553 let ty::ResolverOutputs {
554 global_ctxt: untracked_resolutions,
555 ast_lowering: untracked_resolver_for_lowering,
556 } = resolver.into_outputs();
557
c620b35d
FG
558 let resolutions = tcx.arena.alloc(untracked_resolutions);
559 (tcx.arena.alloc(Steal::new((untracked_resolver_for_lowering, Lrc::new(krate)))), resolutions)
9ffffee4
FG
560}
561
4b012472
FG
562pub(crate) fn write_dep_info(tcx: TyCtxt<'_>) {
563 // Make sure name resolution and macro expansion is run for
564 // the side-effect of providing a complete set of all
565 // accessed files and env vars.
c620b35d 566 let _ = tcx.resolver_for_lowering();
4b012472 567
9ffffee4 568 let sess = tcx.sess;
4b012472 569 let _timer = sess.timer("write_dep_info");
9ffffee4 570 let crate_name = tcx.crate_name(LOCAL_CRATE);
dfeec247 571
4b012472 572 let outputs = tcx.output_filenames(());
dfeec247 573 let output_paths =
add651ee 574 generated_output_paths(tcx, &outputs, sess.io.output_file.is_some(), crate_name);
dfeec247 575
532ac7d7 576 // Ensure the source file isn't accidentally overwritten during compilation.
4b012472 577 if let Some(input_path) = sess.io.input.opt_path() {
532ac7d7
XL
578 if sess.opts.will_create_output_file() {
579 if output_contains_path(&output_paths, input_path) {
c0240ec0 580 sess.dcx().emit_fatal(errors::InputFileWouldBeOverWritten { path: input_path });
532ac7d7 581 }
4b012472 582 if let Some(dir_path) = output_conflicts_with_dir(&output_paths) {
c0240ec0 583 sess.dcx().emit_fatal(errors::GeneratedFileConflictsWithDirectory {
9ffffee4
FG
584 input_path,
585 dir_path,
586 });
532ac7d7
XL
587 }
588 }
589 }
590
9c376795 591 if let Some(ref dir) = sess.io.temps_dir {
3c0e092e 592 if fs::create_dir_all(dir).is_err() {
c0240ec0 593 sess.dcx().emit_fatal(errors::TempsDirError);
3c0e092e
XL
594 }
595 }
596
353b0b11 597 write_out_deps(tcx, &outputs, &output_paths);
532ac7d7
XL
598
599 let only_dep_info = sess.opts.output_types.contains_key(&OutputType::DepInfo)
600 && sess.opts.output_types.len() == 1;
601
602 if !only_dep_info {
9c376795 603 if let Some(ref dir) = sess.io.output_dir {
532ac7d7 604 if fs::create_dir_all(dir).is_err() {
c0240ec0 605 sess.dcx().emit_fatal(errors::OutDirError);
532ac7d7
XL
606 }
607 }
608 }
532ac7d7
XL
609}
610
923072b8 611pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| {
3dfed10e 612 let providers = &mut Providers::default();
532ac7d7 613 providers.analysis = analysis;
064997fb 614 providers.hir_crate = rustc_ast_lowering::lower_to_hir;
c620b35d
FG
615 providers.resolver_for_lowering_raw = resolver_for_lowering_raw;
616 providers.stripped_cfg_items =
617 |tcx, _| tcx.arena.alloc_from_iter(tcx.resolutions(()).stripped_cfg_items.steal());
618 providers.resolutions = |tcx, ()| tcx.resolver_for_lowering_raw(()).1;
353b0b11 619 providers.early_lint_checks = early_lint_checks;
532ac7d7 620 proc_macro_decls::provide(providers);
c295e0f8 621 rustc_const_eval::provide(providers);
ba9703b0 622 rustc_middle::hir::provide(providers);
31ef2f64
FG
623 rustc_borrowck::provide(providers);
624 rustc_mir_build::provide(providers);
c295e0f8
XL
625 rustc_mir_transform::provide(providers);
626 rustc_monomorphize::provide(providers);
532ac7d7 627 rustc_privacy::provide(providers);
353b0b11 628 rustc_resolve::provide(providers);
2b03887a
FG
629 rustc_hir_analysis::provide(providers);
630 rustc_hir_typeck::provide(providers);
532ac7d7
XL
631 ty::provide(providers);
632 traits::provide(providers);
532ac7d7
XL
633 rustc_passes::provide(providers);
634 rustc_traits::provide(providers);
fc512014 635 rustc_ty_utils::provide(providers);
60c5eb7d 636 rustc_metadata::provide(providers);
532ac7d7 637 rustc_lint::provide(providers);
ba9703b0 638 rustc_symbol_mangling::provide(providers);
e74abb32 639 rustc_codegen_ssa::provide(providers);
3dfed10e
XL
640 *providers
641});
532ac7d7 642
60c5eb7d
XL
643pub fn create_global_ctxt<'tcx>(
644 compiler: &'tcx Compiler,
add651ee
FG
645 crate_types: Vec<CrateType>,
646 stable_crate_id: StableCrateId,
74b04a01 647 dep_graph: DepGraph,
9c376795 648 untracked: Untracked,
781aab86 649 gcx_cell: &'tcx OnceLock<GlobalCtxt<'tcx>>,
60c5eb7d 650 arena: &'tcx WorkerLocal<Arena<'tcx>>,
064997fb 651 hir_arena: &'tcx WorkerLocal<rustc_hir::Arena<'tcx>>,
9ffffee4 652) -> &'tcx GlobalCtxt<'tcx> {
136023e0
XL
653 // We're constructing the HIR here; we don't care what we will
654 // read, since we haven't even constructed the *input* to
655 // incr. comp. yet.
656 dep_graph.assert_ignored();
657
4b012472 658 let sess = &compiler.sess;
17df50a5 659 let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess);
532ac7d7 660
4b012472 661 let codegen_backend = &compiler.codegen_backend;
781aab86
FG
662 let mut providers = *DEFAULT_QUERY_PROVIDERS;
663 codegen_backend.provide(&mut providers);
532ac7d7 664
60c5eb7d 665 if let Some(callback) = compiler.override_queries {
781aab86 666 callback(sess, &mut providers);
60c5eb7d 667 }
532ac7d7 668
49aad941 669 let incremental = dep_graph.is_fully_enabled();
6a06907d 670
9ffffee4
FG
671 sess.time("setup_global_ctxt", || {
672 gcx_cell.get_or_init(move || {
dfeec247
XL
673 TyCtxt::create_global_ctxt(
674 sess,
add651ee
FG
675 crate_types,
676 stable_crate_id,
dfeec247 677 arena,
064997fb 678 hir_arena,
9c376795 679 untracked,
ba9703b0 680 dep_graph,
3c0e092e 681 rustc_query_impl::query_callbacks(arena),
49aad941 682 rustc_query_impl::query_system(
781aab86
FG
683 providers.queries,
684 providers.extern_queries,
49aad941
FG
685 query_result_on_disk_cache,
686 incremental,
687 ),
781aab86 688 providers.hooks,
e8be2606 689 compiler.current_gcx.clone(),
dfeec247
XL
690 )
691 })
9ffffee4 692 })
532ac7d7
XL
693}
694
e8be2606
FG
695/// Runs all analyses that we guarantee to run, even if errors were reported in earlier analyses.
696/// This function never fails.
697fn run_required_analyses(tcx: TyCtxt<'_>) {
c620b35d
FG
698 if tcx.sess.opts.unstable_opts.hir_stats {
699 rustc_passes::hir_stats::print_hir_stats(tcx);
700 }
c620b35d 701 #[cfg(debug_assertions)]
ba9703b0 702 rustc_passes::hir_id_validator::check_crate(tcx);
532ac7d7 703 let sess = tcx.sess;
dfeec247
XL
704 sess.time("misc_checking_1", || {
705 parallel!(
706 {
781aab86 707 sess.time("looking_for_entry_point", || tcx.ensure().entry_fn(()));
532ac7d7 708
17df50a5
XL
709 sess.time("looking_for_derive_registrar", || {
710 tcx.ensure().proc_macro_decls_static(())
711 });
cdc7bbd5 712
136023e0 713 CStore::from_tcx(tcx).report_unused_deps(tcx);
dfeec247
XL
714 },
715 {
c295e0f8 716 tcx.hir().par_for_each_module(|module| {
6a06907d
XL
717 tcx.ensure().check_mod_loops(module);
718 tcx.ensure().check_mod_attrs(module);
719 tcx.ensure().check_mod_naked_functions(module);
720 tcx.ensure().check_mod_unstable_api_usage(module);
721 tcx.ensure().check_mod_const_bodies(module);
dfeec247 722 });
136023e0
XL
723 },
724 {
5e7ed085
FG
725 sess.time("unused_lib_feature_checking", || {
726 rustc_passes::stability::check_unused_or_stable_features(tcx)
727 });
728 },
729 {
730 // We force these queries to run,
136023e0
XL
731 // since they might not otherwise get called.
732 // This marks the corresponding crate-level attributes
733 // as used, and ensures that their values are valid.
734 tcx.ensure().limits(());
5e7ed085 735 tcx.ensure().stability_index(());
dfeec247
XL
736 }
737 );
532ac7d7 738 });
e8be2606 739 rustc_hir_analysis::check_crate(tcx);
dfeec247 740 sess.time("MIR_borrow_checking", || {
ed00b5ec 741 tcx.hir().par_body_owners(|def_id| {
c0240ec0
FG
742 // Run unsafety check because it's responsible for stealing and
743 // deallocating THIR.
744 tcx.ensure().check_unsafety(def_id);
ed00b5ec
FG
745 tcx.ensure().mir_borrowck(def_id)
746 });
532ac7d7 747 });
dfeec247 748 sess.time("MIR_effect_checking", || {
c295e0f8 749 for def_id in tcx.hir().body_owners() {
064997fb 750 tcx.ensure().has_ffi_unwind_calls(def_id);
f035d41b 751
49aad941
FG
752 // If we need to codegen, ensure that we emit all errors from
753 // `mir_drops_elaborated_and_const_checked` now, to avoid discovering
754 // them later during codegen.
755 if tcx.sess.opts.output_types.should_codegen()
756 || tcx.hir().body_const_context(def_id).is_some()
757 {
758 tcx.ensure().mir_drops_elaborated_and_const_checked(def_id);
759 tcx.ensure().unused_generic_params(ty::InstanceDef::Item(def_id.to_def_id()));
f035d41b 760 }
532ac7d7
XL
761 }
762 });
781aab86 763 tcx.hir().par_body_owners(|def_id| {
4b012472 764 if tcx.is_coroutine(def_id.to_def_id()) {
ed00b5ec 765 tcx.ensure().mir_coroutine_witnesses(def_id);
e8be2606
FG
766 tcx.ensure().check_coroutine_obligations(
767 tcx.typeck_root_def_id(def_id.to_def_id()).expect_local(),
768 );
781aab86
FG
769 }
770 });
dfeec247 771 sess.time("layout_testing", || layout_test::test_layout(tcx));
781aab86 772 sess.time("abi_testing", || abi_test::test_abi(tcx));
e8be2606
FG
773}
774
775/// Runs the type-checking, region checking and other miscellaneous analysis
776/// passes on the crate.
777fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
778 run_required_analyses(tcx);
779
780 let sess = tcx.sess;
532ac7d7
XL
781
782 // Avoid overwhelming user with errors if borrow checking failed.
48663c56 783 // I'm not sure how helpful this is, to be honest, but it avoids a
5869c6ff 784 // lot of annoying errors in the ui tests (basically,
532ac7d7
XL
785 // lint warnings and so on -- kindck used to do this abort, but
786 // kindck is gone now). -nmatsakis
c620b35d
FG
787 //
788 // But we exclude lint errors from this, because lint errors are typically
789 // less serious and we're more likely to want to continue (#87337).
790 if let Some(guar) = sess.dcx().has_errors_excluding_lint_errors() {
791 return Err(guar);
532ac7d7
XL
792 }
793
dfeec247
XL
794 sess.time("misc_checking_3", || {
795 parallel!(
796 {
2b03887a 797 tcx.ensure().effective_visibilities(());
dfeec247
XL
798
799 parallel!(
800 {
17df50a5 801 tcx.ensure().check_private_in_public(());
dfeec247
XL
802 },
803 {
5099ac24
FG
804 tcx.hir()
805 .par_for_each_module(|module| tcx.ensure().check_mod_deathness(module));
dfeec247 806 },
dfeec247
XL
807 {
808 sess.time("lint_checking", || {
add651ee 809 rustc_lint::check_crate(tcx);
dfeec247 810 });
add651ee
FG
811 },
812 {
813 tcx.ensure().clashing_extern_declarations(());
dfeec247
XL
814 }
815 );
816 },
817 {
818 sess.time("privacy_checking_modules", || {
c295e0f8 819 tcx.hir().par_for_each_module(|module| {
6a06907d 820 tcx.ensure().check_mod_privacy(module);
dfeec247 821 });
532ac7d7 822 });
dfeec247
XL
823 }
824 );
04454e1e
FG
825
826 // This check has to be run after all lints are done processing. We don't
827 // define a lint filter, as all lint checks should have finished at this point.
781aab86 828 sess.time("check_lint_expectations", || tcx.ensure().check_expectations(None));
ed00b5ec
FG
829
830 // This query is only invoked normally if a diagnostic is emitted that needs any
831 // diagnostic item. If the crate compiles without checking any diagnostic items,
832 // we will fail to emit overlap diagnostics. Thus we invoke it here unconditionally.
833 let _ = tcx.all_diagnostic_items(());
532ac7d7
XL
834 });
835
fe692bf9
FG
836 if sess.opts.unstable_opts.print_vtable_sizes {
837 let traits = tcx.traits(LOCAL_CRATE);
838
839 for &tr in traits {
31ef2f64 840 if !tcx.is_object_safe(tr) {
fe692bf9
FG
841 continue;
842 }
843
844 let name = ty::print::with_no_trimmed_paths!(tcx.def_path_str(tr));
845
846 let mut first_dsa = true;
847
848 // Number of vtable entries, if we didn't have upcasting
849 let mut entries_ignoring_upcasting = 0;
850 // Number of vtable entries needed solely for upcasting
851 let mut entries_for_upcasting = 0;
852
853 let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(tcx, tr));
854
ed00b5ec
FG
855 // A slightly edited version of the code in
856 // `rustc_trait_selection::traits::vtable::vtable_entries`, that works without self
857 // type and just counts number of entries.
fe692bf9 858 //
ed00b5ec
FG
859 // Note that this is technically wrong, for traits which have associated types in
860 // supertraits:
fe692bf9
FG
861 //
862 // trait A: AsRef<Self::T> + AsRef<()> { type T; }
863 //
ed00b5ec
FG
864 // Without self type we can't normalize `Self::T`, so we can't know if `AsRef<Self::T>`
865 // and `AsRef<()>` are the same trait, thus we assume that those are different, and
866 // potentially over-estimate how many vtable entries there are.
fe692bf9
FG
867 //
868 // Similarly this is wrong for traits that have methods with possibly-impossible bounds.
869 // For example:
870 //
871 // trait B<T> { fn f(&self) where T: Copy; }
872 //
873 // Here `dyn B<u8>` will have 4 entries, while `dyn B<String>` will only have 3.
874 // However, since we don't know `T`, we can't know if `T: Copy` holds or not,
875 // thus we lean on the bigger side and say it has 4 entries.
876 traits::vtable::prepare_vtable_segments(tcx, trait_ref, |segment| {
877 match segment {
878 traits::vtable::VtblSegment::MetadataDSA => {
879 // If this is the first dsa, it would be included either way,
880 // otherwise it's needed for upcasting
881 if std::mem::take(&mut first_dsa) {
882 entries_ignoring_upcasting += 3;
883 } else {
884 entries_for_upcasting += 3;
885 }
886 }
887
888 traits::vtable::VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
889 // Lookup the shape of vtable for the trait.
890 let own_existential_entries =
891 tcx.own_existential_vtable_entries(trait_ref.def_id());
892
ed00b5ec
FG
893 // The original code here ignores the method if its predicates are
894 // impossible. We can't really do that as, for example, all not trivial
895 // bounds on generic parameters are impossible (since we don't know the
896 // parameters...), see the comment above.
fe692bf9
FG
897 entries_ignoring_upcasting += own_existential_entries.len();
898
899 if emit_vptr {
900 entries_for_upcasting += 1;
901 }
902 }
903 }
904
905 std::ops::ControlFlow::Continue::<std::convert::Infallible>(())
906 });
907
908 sess.code_stats.record_vtable_size(
909 tr,
910 &name,
911 VTableSizeInfo {
912 trait_name: name.clone(),
913 entries: entries_ignoring_upcasting + entries_for_upcasting,
914 entries_ignoring_upcasting,
915 entries_for_upcasting,
916 upcasting_cost_percent: entries_for_upcasting as f64
917 / entries_ignoring_upcasting as f64
918 * 100.,
919 },
920 )
921 }
922 }
923
532ac7d7
XL
924 Ok(())
925}
926
927/// Runs the codegen backend, after which the AST and analysis can
928/// be discarded.
929pub fn start_codegen<'tcx>(
930 codegen_backend: &dyn CodegenBackend,
dc9dc135 931 tcx: TyCtxt<'tcx>,
532ac7d7 932) -> Box<dyn Any> {
3dfed10e 933 info!("Pre-codegen\n{:?}", tcx.debug_stats());
532ac7d7 934
487cf647 935 let (metadata, need_metadata_module) = rustc_metadata::fs::encode_and_write_metadata(tcx);
48663c56 936
dfeec247 937 let codegen = tcx.sess.time("codegen_crate", move || {
e74abb32 938 codegen_backend.codegen_crate(tcx, metadata, need_metadata_module)
48663c56 939 });
532ac7d7 940
ed00b5ec 941 // Don't run this test assertions when not doing codegen. Compiletest tries to build
5869c6ff
XL
942 // build-fail tests in check mode first and expects it to not give an error in that case.
943 if tcx.sess.opts.output_types.should_codegen() {
5869c6ff
XL
944 rustc_symbol_mangling::test::report_symbol_names(tcx);
945 }
946
3dfed10e 947 info!("Post-codegen\n{:?}", tcx.debug_stats());
532ac7d7
XL
948
949 if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) {
487cf647 950 if let Err(error) = rustc_mir_transform::dump_mir::emit_mir(tcx) {
c620b35d 951 tcx.dcx().emit_fatal(errors::CantEmitMIR { error });
532ac7d7
XL
952 }
953 }
954
955 codegen
956}
c295e0f8
XL
957
958fn get_recursion_limit(krate_attrs: &[ast::Attribute], sess: &Session) -> Limit {
959 if let Some(attr) = krate_attrs
960 .iter()
961 .find(|attr| attr.has_name(sym::recursion_limit) && attr.value_str().is_none())
962 {
963 // This is here mainly to check for using a macro, such as
964 // #![recursion_limit = foo!()]. That is not supported since that
965 // would require expanding this while in the middle of expansion,
966 // which needs to know the limit before expanding. Otherwise,
967 // validation would normally be caught in AstValidator (via
968 // `check_builtin_attribute`), but by the time that runs the macro
969 // is expanded, and it doesn't give an error.
970 validate_attr::emit_fatal_malformed_builtin_attribute(
c620b35d 971 &sess.psess,
c295e0f8
XL
972 attr,
973 sym::recursion_limit,
974 );
975 }
976 rustc_middle::middle::limits::get_recursion_limit(krate_attrs, sess)
977}