From 0b89aac08d7190961544ced9e868cc20ce24d786 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 8 Aug 2023 18:28:20 +0800 Subject: [PATCH 01/11] rustc: Move `crate_types` from `Session` to `GlobalCtxt` Removes a piece of mutable state. Follow up to #114578. --- compiler/rustc_ast_lowering/src/lib.rs | 4 +- .../rustc_codegen_cranelift/src/driver/jit.rs | 2 +- compiler/rustc_codegen_llvm/src/context.rs | 2 +- .../rustc_codegen_llvm/src/debuginfo/gdb.rs | 2 +- compiler/rustc_codegen_llvm/src/mono_item.rs | 2 +- compiler/rustc_codegen_ssa/src/back/link.rs | 2 +- .../src/back/symbol_export.rs | 6 +-- compiler/rustc_codegen_ssa/src/back/write.rs | 20 +++++---- compiler/rustc_codegen_ssa/src/base.rs | 18 +++----- compiler/rustc_codegen_ssa/src/lib.rs | 1 + compiler/rustc_driver_impl/src/lib.rs | 2 - compiler/rustc_interface/src/passes.rs | 11 +++-- compiler/rustc_interface/src/queries.rs | 4 +- compiler/rustc_metadata/src/creader.rs | 6 +-- .../rustc_metadata/src/dependency_format.rs | 3 +- compiler/rustc_metadata/src/fs.rs | 2 +- compiler/rustc_metadata/src/native_libs.rs | 17 ++++--- compiler/rustc_metadata/src/rmeta/encoder.rs | 4 +- compiler/rustc_middle/src/ty/context.rs | 45 +++++++++++++++++-- compiler/rustc_passes/src/entry.rs | 2 +- compiler/rustc_passes/src/reachable.rs | 8 ++-- compiler/rustc_passes/src/weak_lang_items.rs | 2 +- compiler/rustc_resolve/src/late.rs | 6 +-- compiler/rustc_session/src/session.rs | 42 ----------------- .../clippy/clippy_lints/src/missing_inline.rs | 1 - src/tools/miri/src/bin/miri.rs | 2 +- 26 files changed, 108 insertions(+), 108 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 0aeff22ca9f8a..89775bdee263e 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -457,7 +457,7 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> { // Don't hash unless necessary, because it's expensive. let opt_hir_hash = - if tcx.sess.needs_crate_hash() { Some(compute_hir_hash(tcx, &owners)) } else { None }; + if tcx.needs_crate_hash() { Some(compute_hir_hash(tcx, &owners)) } else { None }; hir::Crate { owners, opt_hir_hash } } @@ -648,7 +648,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let bodies = SortedMap::from_presorted_elements(bodies); // Don't hash unless necessary, because it's expensive. - let (opt_hash_including_bodies, attrs_hash) = if self.tcx.sess.needs_crate_hash() { + let (opt_hash_including_bodies, attrs_hash) = if self.tcx.needs_crate_hash() { self.tcx.with_stable_hashing_context(|mut hcx| { let mut stable_hasher = StableHasher::new(); hcx.with_hir_bodies(node.def_id(), &bodies, |hcx| { diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs index 3ea3884214805..1c606494f383e 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs @@ -98,7 +98,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { tcx.sess.fatal("JIT mode doesn't work with `cargo check`"); } - if !tcx.sess.crate_types().contains(&rustc_session::config::CrateType::Executable) { + if !tcx.crate_types().contains(&rustc_session::config::CrateType::Executable) { tcx.sess.fatal("can't jit non-executable crate"); } diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index b4f7e20e05da1..24fd5bbf8c526 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -209,7 +209,7 @@ pub unsafe fn create_module<'ll>( // PIE is potentially more effective than PIC, but can only be used in executables. // If all our outputs are executables, then we can relax PIC to PIE. if reloc_model == RelocModel::Pie - || sess.crate_types().iter().all(|ty| *ty == CrateType::Executable) + || tcx.crate_types().iter().all(|ty| *ty == CrateType::Executable) { llvm::LLVMRustSetModulePIELevel(llmod); } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs index ef7c661936a08..425e935bc9f2e 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs @@ -92,7 +92,7 @@ pub fn needs_gdb_debug_scripts_section(cx: &CodegenCx<'_, '_>) -> bool { // each rlib could produce a different set of visualizers that would be embedded // in the `.debug_gdb_scripts` section. For that reason, we make sure that the // section is only emitted for leaf crates. - let embed_visualizers = cx.sess().crate_types().iter().any(|&crate_type| match crate_type { + let embed_visualizers = cx.tcx.crate_types().iter().any(|&crate_type| match crate_type { CrateType::Executable | CrateType::Dylib | CrateType::Cdylib | CrateType::Staticlib => { // These are crate types for which we will embed pretty printers since they // are treated as leaf crates. diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index e8cda626f549b..38e8220569a2a 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -111,7 +111,7 @@ impl CodegenCx<'_, '_> { } // Symbols from executables can't really be imported any further. - let all_exe = self.tcx.sess.crate_types().iter().all(|ty| *ty == CrateType::Executable); + let all_exe = self.tcx.crate_types().iter().all(|ty| *ty == CrateType::Executable); let is_declaration_for_linker = is_declaration || linkage == llvm::Linkage::AvailableExternallyLinkage; if all_exe && !is_declaration_for_linker { diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index cd6201648ee9b..bb65c3c81d952 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -69,7 +69,7 @@ pub fn link_binary<'a>( let _timer = sess.timer("link_binary"); let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata); let mut tempfiles_for_stdout_output: Vec = Vec::new(); - for &crate_type in sess.crate_types().iter() { + for &crate_type in &codegen_results.crate_info.crate_types { // Ignore executable crates if we have -Z no-codegen, as they will error. if (sess.opts.unstable_opts.no_codegen || !sess.opts.output_types.should_codegen()) && !output_metadata diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 326b28ad1041e..8fb2ccb7e8a4c 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -19,7 +19,7 @@ use rustc_session::config::{CrateType, OomStrategy}; use rustc_target::spec::SanitizerSet; pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel { - crates_export_threshold(&tcx.sess.crate_types()) + crates_export_threshold(tcx.crate_types()) } fn crate_export_threshold(crate_type: CrateType) -> SymbolExportLevel { @@ -290,8 +290,8 @@ fn exported_symbols_provider_local( })); } - if tcx.sess.crate_types().contains(&CrateType::Dylib) - || tcx.sess.crate_types().contains(&CrateType::ProcMacro) + if tcx.crate_types().contains(&CrateType::Dylib) + || tcx.crate_types().contains(&CrateType::ProcMacro) { let symbol_name = metadata_symbol_name(tcx); let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, &symbol_name)); diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 4071852574191..f485af00bcad7 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -123,7 +123,7 @@ pub struct ModuleConfig { impl ModuleConfig { fn new( kind: ModuleKind, - sess: &Session, + tcx: TyCtxt<'_>, no_builtins: bool, is_compiler_builtins: bool, ) -> ModuleConfig { @@ -135,6 +135,7 @@ impl ModuleConfig { }; } + let sess = tcx.sess; let opt_level_and_size = if_regular!(Some(sess.opts.optimize), None); let save_temps = sess.opts.cg.save_temps; @@ -166,7 +167,7 @@ impl ModuleConfig { // `#![no_builtins]` is assumed to not participate in LTO and // instead goes on to generate object code. EmitObj::Bitcode - } else if need_bitcode_in_object(sess) { + } else if need_bitcode_in_object(tcx) { EmitObj::ObjectCode(BitcodeSection::Full) } else { EmitObj::ObjectCode(BitcodeSection::None) @@ -414,9 +415,10 @@ pub struct CompiledModules { pub allocator_module: Option, } -fn need_bitcode_in_object(sess: &Session) -> bool { +fn need_bitcode_in_object(tcx: TyCtxt<'_>) -> bool { + let sess = tcx.sess; let requested_for_rlib = sess.opts.cg.embed_bitcode - && sess.crate_types().contains(&CrateType::Rlib) + && tcx.crate_types().contains(&CrateType::Rlib) && sess.opts.output_types.contains_key(&OutputType::Exe); let forced_by_target = sess.target.forces_embed_bitcode; requested_for_rlib || forced_by_target @@ -450,11 +452,11 @@ pub fn start_async_codegen( let crate_info = CrateInfo::new(tcx, target_cpu); let regular_config = - ModuleConfig::new(ModuleKind::Regular, sess, no_builtins, is_compiler_builtins); + ModuleConfig::new(ModuleKind::Regular, tcx, no_builtins, is_compiler_builtins); let metadata_config = - ModuleConfig::new(ModuleKind::Metadata, sess, no_builtins, is_compiler_builtins); + ModuleConfig::new(ModuleKind::Metadata, tcx, no_builtins, is_compiler_builtins); let allocator_config = - ModuleConfig::new(ModuleKind::Allocator, sess, no_builtins, is_compiler_builtins); + ModuleConfig::new(ModuleKind::Allocator, tcx, no_builtins, is_compiler_builtins); let (shared_emitter, shared_emitter_main) = SharedEmitter::new(); let (codegen_worker_send, codegen_worker_receive) = channel(); @@ -1092,7 +1094,7 @@ fn start_executing_work( }; let cgcx = CodegenContext:: { - crate_types: sess.crate_types().to_vec(), + crate_types: tcx.crate_types().to_vec(), each_linked_rlib_for_lto, lto: sess.lto(), fewer_names: sess.fewer_names(), @@ -2063,7 +2065,7 @@ fn msvc_imps_needed(tcx: TyCtxt<'_>) -> bool { ); tcx.sess.target.is_like_windows && - tcx.sess.crate_types().iter().any(|ct| *ct == CrateType::Rlib) && + tcx.crate_types().iter().any(|ct| *ct == CrateType::Rlib) && // ThinLTO can't handle this workaround in all cases, so we don't // emit the `__imp_` symbols. Instead we make them unnecessary by disallowing // dynamic linking when linker plugin LTO is enabled. diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 4819ab22723d9..aa003e4e89811 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -779,18 +779,13 @@ pub fn codegen_crate( impl CrateInfo { pub fn new(tcx: TyCtxt<'_>, target_cpu: String) -> CrateInfo { - let exported_symbols = tcx - .sess - .crate_types() + let crate_types = tcx.crate_types().to_vec(); + let exported_symbols = crate_types .iter() .map(|&c| (c, crate::back::linker::exported_symbols(tcx, c))) .collect(); - let linked_symbols = tcx - .sess - .crate_types() - .iter() - .map(|&c| (c, crate::back::linker::linked_symbols(tcx, c))) - .collect(); + let linked_symbols = + crate_types.iter().map(|&c| (c, crate::back::linker::linked_symbols(tcx, c))).collect(); let local_crate_name = tcx.crate_name(LOCAL_CRATE); let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID); let subsystem = attr::first_attr_value_str_by_name(crate_attrs, sym::windows_subsystem); @@ -829,6 +824,7 @@ impl CrateInfo { let mut info = CrateInfo { target_cpu, + crate_types, exported_symbols, linked_symbols, local_crate_name, @@ -916,7 +912,7 @@ impl CrateInfo { }); } - let embed_visualizers = tcx.sess.crate_types().iter().any(|&crate_type| match crate_type { + let embed_visualizers = tcx.crate_types().iter().any(|&crate_type| match crate_type { CrateType::Executable | CrateType::Dylib | CrateType::Cdylib => { // These are crate types for which we invoke the linker and can embed // NatVis visualizers. @@ -1013,7 +1009,7 @@ fn determine_cgu_reuse<'tcx>(tcx: TyCtxt<'tcx>, cgu: &CodegenUnit<'tcx>) -> CguR match compute_per_cgu_lto_type( &tcx.sess.lto(), &tcx.sess.opts, - &tcx.sess.crate_types(), + tcx.crate_types(), ModuleKind::Regular, ) { ComputedLtoType::No => CguReuse::PostLto, diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index be4c81638d63f..f577f653ccd66 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -150,6 +150,7 @@ impl From<&cstore::NativeLib> for NativeLib { #[derive(Debug, Encodable, Decodable)] pub struct CrateInfo { pub target_cpu: String, + pub crate_types: Vec, pub exported_symbols: FxHashMap>, pub linked_symbols: FxHashMap>, pub local_crate_name: Symbol, diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index ec77569d4b877..7bbed0877f07b 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -653,8 +653,6 @@ fn show_md_content_with_pager(content: &str, color: ColorConfig) { pub fn try_process_rlink(sess: &Session, compiler: &interface::Compiler) -> Compilation { if sess.opts.unstable_opts.link_only { if let Input::File(file) = &sess.io.input { - // FIXME: #![crate_type] and #![crate_name] support not implemented yet - sess.init_crate_types(collect_crate_types(sess, &[])); let outputs = compiler.build_output_filenames(sess, &[]); let rlink_data = fs::read(file).unwrap_or_else(|err| { sess.emit_fatal(RlinkUnableToRead { err }); diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 07c559354c097..c4603cbf1f8e7 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -248,7 +248,7 @@ fn configure_and_expand( rustc_ast_passes::ast_validation::check_crate(sess, &krate, resolver.lint_buffer()) }); - let crate_types = sess.crate_types(); + let crate_types = tcx.crate_types(); let is_executable_crate = crate_types.contains(&CrateType::Executable); let is_proc_macro_crate = crate_types.contains(&CrateType::ProcMacro); @@ -340,11 +340,12 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) { // Returns all the paths that correspond to generated files. fn generated_output_paths( - sess: &Session, + tcx: TyCtxt<'_>, outputs: &OutputFilenames, exact_name: bool, crate_name: Symbol, ) -> Vec { + let sess = tcx.sess; let mut out_filenames = Vec::new(); for output_type in sess.opts.output_types.keys() { let out_filename = outputs.path(*output_type); @@ -353,7 +354,7 @@ fn generated_output_paths( // If the filename has been overridden using `-o`, it will not be modified // by appending `.rlib`, `.exe`, etc., so we can skip this transformation. OutputType::Exe if !exact_name => { - for crate_type in sess.crate_types().iter() { + for crate_type in tcx.crate_types().iter() { let p = filename_for_input(sess, *crate_type, crate_name, outputs); out_filenames.push(p.as_path().to_path_buf()); } @@ -586,7 +587,7 @@ fn output_filenames(tcx: TyCtxt<'_>, (): ()) -> Arc { let outputs = util::build_output_filenames(&krate.attrs, sess); let output_paths = - generated_output_paths(sess, &outputs, sess.io.output_file.is_some(), crate_name); + generated_output_paths(tcx, &outputs, sess.io.output_file.is_some(), crate_name); // Ensure the source file isn't accidentally overwritten during compilation. if let Some(ref input_path) = sess.io.input.opt_path() { @@ -664,6 +665,7 @@ pub static DEFAULT_EXTERN_QUERY_PROVIDERS: LazyLock = LazyLock: pub fn create_global_ctxt<'tcx>( compiler: &'tcx Compiler, + crate_types: Vec, lint_store: Lrc, dep_graph: DepGraph, untracked: Untracked, @@ -696,6 +698,7 @@ pub fn create_global_ctxt<'tcx>( gcx_cell.get_or_init(move || { TyCtxt::create_global_ctxt( sess, + crate_types, lint_store, arena, hir_arena, diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index b805ff09ee4c6..84b49c21db05c 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -235,12 +235,12 @@ impl<'tcx> Queries<'tcx> { let untracked = Untracked { cstore, source_span, definitions }; // FIXME: Move these fields from session to tcx and make them immutable. - sess.init_crate_types(crate_types); sess.stable_crate_id.set(stable_crate_id).expect("not yet initialized"); sess.init_features(rustc_expand::config::features(sess, &pre_configured_attrs)); let qcx = passes::create_global_ctxt( self.compiler, + crate_types, lint_store, self.dep_graph(dep_graph_future), untracked, @@ -320,7 +320,7 @@ impl<'tcx> Queries<'tcx> { let (crate_hash, prepare_outputs, dep_graph) = self.global_ctxt()?.enter(|tcx| { ( - if tcx.sess.needs_crate_hash() { Some(tcx.crate_hash(LOCAL_CRATE)) } else { None }, + if tcx.needs_crate_hash() { Some(tcx.crate_hash(LOCAL_CRATE)) } else { None }, tcx.output_filenames(()).clone(), tcx.dep_graph.clone(), ) diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 7c9aaeb5762b4..3c76f9a8e52c9 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -545,7 +545,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { name, // The all loop is because `--crate-type=rlib --crate-type=rlib` is // legal and produces both inside this type. - self.sess.crate_types().iter().all(|c| *c == CrateType::Rlib), + self.tcx.crate_types().iter().all(|c| *c == CrateType::Rlib), hash, extra_filename, false, // is_host @@ -689,7 +689,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { fn inject_panic_runtime(&mut self, krate: &ast::Crate) { // If we're only compiling an rlib, then there's no need to select a // panic runtime, so we just skip this section entirely. - let any_non_rlib = self.sess.crate_types().iter().any(|ct| *ct != CrateType::Rlib); + let any_non_rlib = self.tcx.crate_types().iter().any(|ct| *ct != CrateType::Rlib); if !any_non_rlib { info!("panic runtime injection skipped, only generating rlib"); return; @@ -818,7 +818,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // At this point we've determined that we need an allocator. Let's see // if our compilation session actually needs an allocator based on what // we're emitting. - let all_rlib = self.sess.crate_types().iter().all(|ct| matches!(*ct, CrateType::Rlib)); + let all_rlib = self.tcx.crate_types().iter().all(|ct| matches!(*ct, CrateType::Rlib)); if all_rlib { return; } diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs index 72b208a713276..783d35ac7e6f2 100644 --- a/compiler/rustc_metadata/src/dependency_format.rs +++ b/compiler/rustc_metadata/src/dependency_format.rs @@ -66,8 +66,7 @@ use rustc_session::cstore::CrateDepKind; use rustc_session::cstore::LinkagePreference::{self, RequireDynamic, RequireStatic}; pub(crate) fn calculate(tcx: TyCtxt<'_>) -> Dependencies { - tcx.sess - .crate_types() + tcx.crate_types() .iter() .map(|&ty| { let linkage = calculate_type(tcx, ty); diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs index 69a77e82f9874..2a9662b809aef 100644 --- a/compiler/rustc_metadata/src/fs.rs +++ b/compiler/rustc_metadata/src/fs.rs @@ -56,7 +56,7 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) { // Always create a file at `metadata_filename`, even if we have nothing to write to it. // This simplifies the creation of the output `out_filename` when requested. - let metadata_kind = tcx.sess.metadata_kind(); + let metadata_kind = tcx.metadata_kind(); match metadata_kind { MetadataKind::None => { std::fs::File::create(&metadata_filename).unwrap_or_else(|err| { diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index ca5043cc26339..098c411c8d675 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -52,10 +52,11 @@ fn find_bundled_library( verbatim: Option, kind: NativeLibKind, has_cfg: bool, - sess: &Session, + tcx: TyCtxt<'_>, ) -> Option { + let sess = tcx.sess; if let NativeLibKind::Static { bundle: Some(true) | None, whole_archive } = kind - && sess.crate_types().iter().any(|t| matches!(t, &CrateType::Rlib | CrateType::Staticlib)) + && tcx.crate_types().iter().any(|t| matches!(t, &CrateType::Rlib | CrateType::Staticlib)) && (sess.opts.unstable_opts.packed_bundled_libs || has_cfg || whole_archive == Some(true)) { let verbatim = verbatim.unwrap_or(false); @@ -364,7 +365,7 @@ impl<'tcx> Collector<'tcx> { }; let kind = kind.unwrap_or(NativeLibKind::Unspecified); - let filename = find_bundled_library(name, verbatim, kind, cfg.is_some(), sess); + let filename = find_bundled_library(name, verbatim, kind, cfg.is_some(), self.tcx); self.libs.push(NativeLib { name, filename, @@ -442,9 +443,13 @@ impl<'tcx> Collector<'tcx> { // Add if not found let new_name: Option<&str> = passed_lib.new_name.as_deref(); let name = Symbol::intern(new_name.unwrap_or(&passed_lib.name)); - let sess = self.tcx.sess; - let filename = - find_bundled_library(name, passed_lib.verbatim, passed_lib.kind, false, sess); + let filename = find_bundled_library( + name, + passed_lib.verbatim, + passed_lib.kind, + false, + self.tcx, + ); self.libs.push(NativeLib { name, filename, diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index b34fead821f99..be91ad4088a26 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1741,7 +1741,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_proc_macros(&mut self) -> Option { - let is_proc_macro = self.tcx.sess.crate_types().contains(&CrateType::ProcMacro); + let is_proc_macro = self.tcx.crate_types().contains(&CrateType::ProcMacro); if is_proc_macro { let tcx = self.tcx; let hir = tcx.hir(); @@ -2204,7 +2204,7 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) { source_file_cache, interpret_allocs: Default::default(), required_source_files, - is_proc_macro: tcx.sess.crate_types().contains(&CrateType::ProcMacro), + is_proc_macro: tcx.crate_types().contains(&CrateType::ProcMacro), hygiene_ctxt: &hygiene_ctxt, symbol_table: Default::default(), }; diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 8ac1d02ce50e6..0846d465cb740 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -59,8 +59,7 @@ use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; use rustc_session::config::CrateType; use rustc_session::cstore::{CrateStoreDyn, Untracked}; use rustc_session::lint::Lint; -use rustc_session::Limit; -use rustc_session::Session; +use rustc_session::{Limit, MetadataKind, Session}; use rustc_span::def_id::{DefPathHash, StableCrateId}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -527,6 +526,7 @@ pub struct GlobalCtxt<'tcx> { interners: CtxtInterners<'tcx>, pub sess: &'tcx Session, + crate_types: Vec, /// This only ever stores a `LintStore` but we don't want a dependency on that type here. /// @@ -687,6 +687,7 @@ impl<'tcx> TyCtxt<'tcx> { /// has a valid reference to the context, to allow formatting values that need it. pub fn create_global_ctxt( s: &'tcx Session, + crate_types: Vec, lint_store: Lrc, arena: &'tcx WorkerLocal>, hir_arena: &'tcx WorkerLocal>, @@ -705,6 +706,7 @@ impl<'tcx> TyCtxt<'tcx> { GlobalCtxt { sess: s, + crate_types, lint_store, arena, hir_arena, @@ -800,6 +802,43 @@ impl<'tcx> TyCtxt<'tcx> { } } + #[inline] + pub fn crate_types(self) -> &'tcx [CrateType] { + &self.crate_types + } + + pub fn metadata_kind(self) -> MetadataKind { + self.crate_types() + .iter() + .map(|ty| match *ty { + CrateType::Executable | CrateType::Staticlib | CrateType::Cdylib => { + MetadataKind::None + } + CrateType::Rlib => MetadataKind::Uncompressed, + CrateType::Dylib | CrateType::ProcMacro => MetadataKind::Compressed, + }) + .max() + .unwrap_or(MetadataKind::None) + } + + pub fn needs_metadata(self) -> bool { + self.metadata_kind() != MetadataKind::None + } + + pub fn needs_crate_hash(self) -> bool { + // Why is the crate hash needed for these configurations? + // - debug_assertions: for the "fingerprint the result" check in + // `rustc_query_system::query::plumbing::execute_job`. + // - incremental: for query lookups. + // - needs_metadata: for putting into crate metadata. + // - instrument_coverage: for putting into coverage data (see + // `hash_mir_source`). + cfg!(debug_assertions) + || self.sess.opts.incremental.is_some() + || self.needs_metadata() + || self.sess.instrument_coverage() + } + #[inline] pub fn stable_crate_id(self, crate_num: CrateNum) -> StableCrateId { if crate_num == LOCAL_CRATE { @@ -986,7 +1025,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn local_crate_exports_generics(self) -> bool { debug_assert!(self.sess.opts.share_generics()); - self.sess.crate_types().iter().any(|crate_type| { + self.crate_types().iter().any(|crate_type| { match crate_type { CrateType::Executable | CrateType::Staticlib diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index ffd8f77b78b8f..6a29159e91787 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -31,7 +31,7 @@ struct EntryContext<'tcx> { } fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> { - let any_exe = tcx.sess.crate_types().iter().any(|ty| *ty == CrateType::Executable); + let any_exe = tcx.crate_types().iter().any(|ty| *ty == CrateType::Executable); if !any_exe { // No need to find a main function. return None; diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index 7dec5b0acc882..f9d34ea71baf5 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -364,10 +364,10 @@ fn has_custom_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { fn reachable_set(tcx: TyCtxt<'_>, (): ()) -> LocalDefIdSet { let effective_visibilities = &tcx.effective_visibilities(()); - let any_library = - tcx.sess.crate_types().iter().any(|ty| { - *ty == CrateType::Rlib || *ty == CrateType::Dylib || *ty == CrateType::ProcMacro - }); + let any_library = tcx + .crate_types() + .iter() + .any(|ty| *ty == CrateType::Rlib || *ty == CrateType::Dylib || *ty == CrateType::ProcMacro); let mut reachable_context = ReachableContext { tcx, maybe_typeck_results: None, diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs index fc6372cf99ee8..75e071f1fcfed 100644 --- a/compiler/rustc_passes/src/weak_lang_items.rs +++ b/compiler/rustc_passes/src/weak_lang_items.rs @@ -43,7 +43,7 @@ pub fn check_crate(tcx: TyCtxt<'_>, items: &mut lang_items::LanguageItems) { fn verify(tcx: TyCtxt<'_>, items: &lang_items::LanguageItems) { // We only need to check for the presence of weak lang items if we're // emitting something that's not an rlib. - let needs_check = tcx.sess.crate_types().iter().any(|kind| match *kind { + let needs_check = tcx.crate_types().iter().any(|kind| match *kind { CrateType::Dylib | CrateType::ProcMacro | CrateType::Cdylib diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 6007295b9305f..c87db96a5dd92 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -4374,7 +4374,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { if let Some(res) = res && let Some(def_id) = res.opt_def_id() && !def_id.is_local() - && self.r.tcx.sess.crate_types().contains(&CrateType::ProcMacro) + && self.r.tcx.crate_types().contains(&CrateType::ProcMacro) && matches!(self.r.tcx.sess.opts.resolve_doc_links, ResolveDocLinks::ExportedMetadata) { // Encoding foreign def ids in proc macro crate metadata will ICE. return None; @@ -4389,7 +4389,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { match self.r.tcx.sess.opts.resolve_doc_links { ResolveDocLinks::None => return, ResolveDocLinks::ExportedMetadata - if !self.r.tcx.sess.crate_types().iter().copied().any(CrateType::has_metadata) + if !self.r.tcx.crate_types().iter().copied().any(CrateType::has_metadata) || !maybe_exported.eval(self.r) => { return; @@ -4448,7 +4448,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { .into_iter() .filter_map(|tr| { if !tr.def_id.is_local() - && self.r.tcx.sess.crate_types().contains(&CrateType::ProcMacro) + && self.r.tcx.crate_types().contains(&CrateType::ProcMacro) && matches!( self.r.tcx.sess.opts.resolve_doc_links, ResolveDocLinks::ExportedMetadata diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index b25a62991255b..a1f995ad27976 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -152,7 +152,6 @@ pub struct Session { /// Input, input file path and output file path to this compilation process. pub io: CompilerIO, - crate_types: OnceCell>, /// The `stable_crate_id` is constructed out of the crate name and all the /// `-C metadata` arguments passed to the compiler. Its value forms a unique /// global identifier for the crate. It is used to allow multiple crates @@ -314,51 +313,11 @@ impl Session { self.stable_crate_id.get().copied().unwrap() } - pub fn crate_types(&self) -> &[CrateType] { - self.crate_types.get().unwrap().as_slice() - } - /// Returns true if the crate is a testing one. pub fn is_test_crate(&self) -> bool { self.opts.test } - pub fn needs_crate_hash(&self) -> bool { - // Why is the crate hash needed for these configurations? - // - debug_assertions: for the "fingerprint the result" check in - // `rustc_query_system::query::plumbing::execute_job`. - // - incremental: for query lookups. - // - needs_metadata: for putting into crate metadata. - // - instrument_coverage: for putting into coverage data (see - // `hash_mir_source`). - cfg!(debug_assertions) - || self.opts.incremental.is_some() - || self.needs_metadata() - || self.instrument_coverage() - } - - pub fn metadata_kind(&self) -> MetadataKind { - self.crate_types() - .iter() - .map(|ty| match *ty { - CrateType::Executable | CrateType::Staticlib | CrateType::Cdylib => { - MetadataKind::None - } - CrateType::Rlib => MetadataKind::Uncompressed, - CrateType::Dylib | CrateType::ProcMacro => MetadataKind::Compressed, - }) - .max() - .unwrap_or(MetadataKind::None) - } - - pub fn needs_metadata(&self) -> bool { - self.metadata_kind() != MetadataKind::None - } - - pub fn init_crate_types(&self, crate_types: Vec) { - self.crate_types.set(crate_types).expect("`crate_types` was initialized twice") - } - #[rustc_lint_diagnostics] #[track_caller] pub fn struct_span_warn>( @@ -1516,7 +1475,6 @@ pub fn build_session( parse_sess, sysroot, io, - crate_types: OnceCell::new(), stable_crate_id: OnceCell::new(), features: OnceCell::new(), incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)), diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs index a41d5a9ce8d2f..93f6025c71d67 100644 --- a/src/tools/clippy/clippy_lints/src/missing_inline.rs +++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs @@ -74,7 +74,6 @@ fn is_executable_or_proc_macro(cx: &LateContext<'_>) -> bool { use rustc_session::config::CrateType; cx.tcx - .sess .crate_types() .iter() .any(|t: &CrateType| matches!(t, CrateType::Executable | CrateType::ProcMacro)) diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 1ec4cbc4de71d..97718f1f4a9f7 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -69,7 +69,7 @@ impl rustc_driver::Callbacks for MiriCompilerCalls { } init_late_loggers(handler, tcx); - if !tcx.sess.crate_types().contains(&CrateType::Executable) { + if !tcx.crate_types().contains(&CrateType::Executable) { tcx.sess.fatal("miri only makes sense on bin crates"); } From 907aa440cf51859b97dd0a1e25b6f15d344f4ebe Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 8 Aug 2023 20:08:24 +0800 Subject: [PATCH 02/11] rustc: Move `stable_crate_id` from `Session` to `GlobalCtxt` Removes a piece of mutable state. Follow up to #114578. --- compiler/rustc_codegen_ssa/src/back/linker.rs | 2 +- compiler/rustc_interface/src/passes.rs | 4 +++- compiler/rustc_interface/src/queries.rs | 4 ++-- compiler/rustc_middle/src/dep_graph/dep_node.rs | 4 ++-- compiler/rustc_middle/src/hir/map/mod.rs | 2 +- .../rustc_middle/src/middle/exported_symbols.rs | 2 +- compiler/rustc_middle/src/mir/mono.rs | 4 ++-- compiler/rustc_middle/src/ty/context.rs | 16 ++++++++++++---- compiler/rustc_session/src/session.rs | 12 ------------ compiler/rustc_symbol_mangling/src/lib.rs | 2 +- 10 files changed, 25 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index a1e322f4b3130..11afe0fbc3c90 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -1703,7 +1703,7 @@ fn exported_symbols_for_proc_macro_crate(tcx: TyCtxt<'_>) -> Vec { return Vec::new(); } - let stable_crate_id = tcx.sess.local_stable_crate_id(); + let stable_crate_id = tcx.stable_crate_id(LOCAL_CRATE); let proc_macro_decls_name = tcx.sess.generate_proc_macro_decls_symbol(stable_crate_id); let metadata_symbol_name = exported_symbols::metadata_symbol_name(tcx); diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index c4603cbf1f8e7..def9fdcd3c72b 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -12,7 +12,7 @@ use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal}; use rustc_errors::PResult; use rustc_expand::base::{ExtCtxt, LintStoreExpand}; use rustc_fs_util::try_canonicalize; -use rustc_hir::def_id::LOCAL_CRATE; +use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE}; use rustc_lint::{unerased_lint_store, BufferedEarlyLint, EarlyCheckNode, LintStore}; use rustc_metadata::creader::CStore; use rustc_middle::arena::Arena; @@ -666,6 +666,7 @@ pub static DEFAULT_EXTERN_QUERY_PROVIDERS: LazyLock = LazyLock: pub fn create_global_ctxt<'tcx>( compiler: &'tcx Compiler, crate_types: Vec, + stable_crate_id: StableCrateId, lint_store: Lrc, dep_graph: DepGraph, untracked: Untracked, @@ -699,6 +700,7 @@ pub fn create_global_ctxt<'tcx>( TyCtxt::create_global_ctxt( sess, crate_types, + stable_crate_id, lint_store, arena, hir_arena, diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 84b49c21db05c..7687e83da7685 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -234,13 +234,13 @@ impl<'tcx> Queries<'tcx> { debug_assert_eq!(_id, CRATE_DEF_ID); let untracked = Untracked { cstore, source_span, definitions }; - // FIXME: Move these fields from session to tcx and make them immutable. - sess.stable_crate_id.set(stable_crate_id).expect("not yet initialized"); + // FIXME: Move features from session to tcx and make them immutable. sess.init_features(rustc_expand::config::features(sess, &pre_configured_attrs)); let qcx = passes::create_global_ctxt( self.compiler, crate_types, + stable_crate_id, lint_store, self.dep_graph(dep_graph_future), untracked, diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 4e242c684e38d..06251bccc9856 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -60,7 +60,7 @@ use crate::mir::mono::MonoItem; use crate::ty::TyCtxt; use rustc_data_structures::fingerprint::Fingerprint; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::definitions::DefPathHash; use rustc_hir::{HirId, ItemLocalId, OwnerId}; use rustc_query_system::dep_graph::FingerprintStyle; @@ -371,7 +371,7 @@ impl<'tcx> DepNodeParams> for HirId { fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { if tcx.fingerprint_style(dep_node.kind) == FingerprintStyle::HirId { let (local_hash, local_id) = Fingerprint::from(dep_node.hash).split(); - let def_path_hash = DefPathHash::new(tcx.sess.local_stable_crate_id(), local_hash); + let def_path_hash = DefPathHash::new(tcx.stable_crate_id(LOCAL_CRATE), local_hash); let def_id = tcx .def_path_hash_to_def_id(def_path_hash, &mut || { panic!("Failed to extract HirId: {:?} {}", dep_node.kind, dep_node.hash) diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index fbc3226387455..224f897492bbe 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -1210,7 +1210,7 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh { owner_spans.hash_stable(&mut hcx, &mut stable_hasher); } tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher); - tcx.sess.local_stable_crate_id().hash_stable(&mut hcx, &mut stable_hasher); + tcx.stable_crate_id(LOCAL_CRATE).hash_stable(&mut hcx, &mut stable_hasher); // Hash visibility information since it does not appear in HIR. resolutions.visibilities.hash_stable(&mut hcx, &mut stable_hasher); resolutions.has_pub_restricted.hash_stable(&mut hcx, &mut stable_hasher); diff --git a/compiler/rustc_middle/src/middle/exported_symbols.rs b/compiler/rustc_middle/src/middle/exported_symbols.rs index f19812619b213..e30b6b203d73c 100644 --- a/compiler/rustc_middle/src/middle/exported_symbols.rs +++ b/compiler/rustc_middle/src/middle/exported_symbols.rs @@ -72,6 +72,6 @@ pub fn metadata_symbol_name(tcx: TyCtxt<'_>) -> String { format!( "rust_metadata_{}_{:08x}", tcx.crate_name(LOCAL_CRATE), - tcx.sess.local_stable_crate_id(), + tcx.stable_crate_id(LOCAL_CRATE), ) } diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index ddb6cc15bc189..8fd980d5a9e9c 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -524,13 +524,13 @@ impl<'tcx> CodegenUnitNameBuilder<'tcx> { // local crate's ID. Otherwise there can be collisions between CGUs // instantiating stuff for upstream crates. let local_crate_id = if cnum != LOCAL_CRATE { - let local_stable_crate_id = tcx.sess.local_stable_crate_id(); + let local_stable_crate_id = tcx.stable_crate_id(LOCAL_CRATE); format!("-in-{}.{:08x}", tcx.crate_name(LOCAL_CRATE), local_stable_crate_id) } else { String::new() }; - let stable_crate_id = tcx.sess.local_stable_crate_id(); + let stable_crate_id = tcx.stable_crate_id(LOCAL_CRATE); format!("{}.{:08x}{}", tcx.crate_name(cnum), stable_crate_id, local_crate_id) }); diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 0846d465cb740..be839e03cff69 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -527,6 +527,12 @@ pub struct GlobalCtxt<'tcx> { pub sess: &'tcx Session, crate_types: Vec, + /// The `stable_crate_id` is constructed out of the crate name and all the + /// `-C metadata` arguments passed to the compiler. Its value forms a unique + /// global identifier for the crate. It is used to allow multiple crates + /// with the same name to coexist. See the + /// `rustc_symbol_mangling` crate for more information. + stable_crate_id: StableCrateId, /// This only ever stores a `LintStore` but we don't want a dependency on that type here. /// @@ -688,6 +694,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn create_global_ctxt( s: &'tcx Session, crate_types: Vec, + stable_crate_id: StableCrateId, lint_store: Lrc, arena: &'tcx WorkerLocal>, hir_arena: &'tcx WorkerLocal>, @@ -707,6 +714,7 @@ impl<'tcx> TyCtxt<'tcx> { GlobalCtxt { sess: s, crate_types, + stable_crate_id, lint_store, arena, hir_arena, @@ -842,7 +850,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn stable_crate_id(self, crate_num: CrateNum) -> StableCrateId { if crate_num == LOCAL_CRATE { - self.sess.local_stable_crate_id() + self.stable_crate_id } else { self.cstore_untracked().stable_crate_id(crate_num) } @@ -852,7 +860,7 @@ impl<'tcx> TyCtxt<'tcx> { /// that the crate in question has already been loaded by the CrateStore. #[inline] pub fn stable_crate_id_to_crate_num(self, stable_crate_id: StableCrateId) -> CrateNum { - if stable_crate_id == self.sess.local_stable_crate_id() { + if stable_crate_id == self.stable_crate_id(LOCAL_CRATE) { LOCAL_CRATE } else { self.cstore_untracked().stable_crate_id_to_crate_num(stable_crate_id) @@ -869,7 +877,7 @@ impl<'tcx> TyCtxt<'tcx> { // If this is a DefPathHash from the local crate, we can look up the // DefId in the tcx's `Definitions`. - if stable_crate_id == self.sess.local_stable_crate_id() { + if stable_crate_id == self.stable_crate_id(LOCAL_CRATE) { self.untracked.definitions.read().local_def_path_hash_to_def_id(hash, err).to_def_id() } else { // If this is a DefPathHash from an upstream crate, let the CrateStore map @@ -886,7 +894,7 @@ impl<'tcx> TyCtxt<'tcx> { // statements within the query system and we'd run into endless // recursion otherwise. let (crate_name, stable_crate_id) = if def_id.is_local() { - (self.crate_name(LOCAL_CRATE), self.sess.local_stable_crate_id()) + (self.crate_name(LOCAL_CRATE), self.stable_crate_id(LOCAL_CRATE)) } else { let cstore = &*self.cstore_untracked(); (cstore.crate_name(def_id.krate), cstore.stable_crate_id(def_id.krate)) diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index a1f995ad27976..5d7572f65a55f 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -152,13 +152,6 @@ pub struct Session { /// Input, input file path and output file path to this compilation process. pub io: CompilerIO, - /// The `stable_crate_id` is constructed out of the crate name and all the - /// `-C metadata` arguments passed to the compiler. Its value forms a unique - /// global identifier for the crate. It is used to allow multiple crates - /// with the same name to coexist. See the - /// `rustc_symbol_mangling` crate for more information. - pub stable_crate_id: OnceCell, - features: OnceCell, incr_comp_session: OneThread>, @@ -309,10 +302,6 @@ impl Session { self.parse_sess.span_diagnostic.emit_future_breakage_report(diags); } - pub fn local_stable_crate_id(&self) -> StableCrateId { - self.stable_crate_id.get().copied().unwrap() - } - /// Returns true if the crate is a testing one. pub fn is_test_crate(&self) -> bool { self.opts.test @@ -1475,7 +1464,6 @@ pub fn build_session( parse_sess, sysroot, io, - stable_crate_id: OnceCell::new(), features: OnceCell::new(), incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)), cgu_reuse_tracker, diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index 22fd1f09f3a3c..74538e9f5a3fc 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -180,7 +180,7 @@ fn compute_symbol_name<'tcx>( if let Some(def_id) = def_id.as_local() { if tcx.proc_macro_decls_static(()) == Some(def_id) { - let stable_crate_id = tcx.sess.local_stable_crate_id(); + let stable_crate_id = tcx.stable_crate_id(LOCAL_CRATE); return tcx.sess.generate_proc_macro_decls_symbol(stable_crate_id); } } From 32e6a2239bdfc741007e30243d26eb378bb9e975 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 10 Aug 2023 12:20:47 +0200 Subject: [PATCH 03/11] remove myself from the review rotation --- triagebot.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index 3b2114855c14c..bc9aaee154062 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -527,7 +527,6 @@ bootstrap = [ ] infra-ci = [ "@Mark-Simulacrum", - "@pietroalbini", ] rustdoc = [ "@jsha", From 26efc2f358a91c170be29df1aa6ceef703d22020 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 10 Aug 2023 12:24:00 +0200 Subject: [PATCH 04/11] update my entry in the mailmap --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index 601064b77d438..f34586bd7f7ed 100644 --- a/.mailmap +++ b/.mailmap @@ -458,6 +458,7 @@ Philipp Matthias Schäfer phosphorus Pierre Krieger pierwill <19642016+pierwill@users.noreply.github.com> +Pietro Albini Pradyumna Rahul Przemysław Wesołek Przemek Wesołek r00ster From d558353f2860298fabb898923dc41c99190a5ab4 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 10 Aug 2023 12:35:34 +0200 Subject: [PATCH 05/11] make the provisional cache slightly less broken --- .../src/solve/search_graph/cache.rs | 32 +++++---- .../src/solve/search_graph/mod.rs | 65 +++++++++++-------- .../cycles/inductive-not-on-stack.rs | 2 +- .../cycles/inductive-not-on-stack.stderr | 15 +---- 4 files changed, 59 insertions(+), 55 deletions(-) diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs b/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs index 56f126e91572f..be48447e27c24 100644 --- a/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs +++ b/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs @@ -19,21 +19,25 @@ rustc_index::newtype_index! { #[derive(Debug, Clone)] pub(super) struct ProvisionalEntry<'tcx> { - // In case we have a coinductive cycle, this is the - // the currently least restrictive result of this goal. - pub(super) response: QueryResult<'tcx>, - // In case of a cycle, the position of deepest stack entry involved - // in that cycle. This is monotonically decreasing in the stack as all - // elements between the current stack element in the deepest stack entry - // involved have to also be involved in that cycle. - // - // We can only move entries to the global cache once we're complete done - // with the cycle. If this entry has not been involved in a cycle, - // this is just its own depth. + /// In case we have a coinductive cycle, this is the + /// the current provisional result of this goal. + /// + /// This starts out as `None` for all goals and gets to some + /// when the goal gets popped from the stack or we rerun evaluation + /// for this goal to reach a fixpoint. + pub(super) response: Option>, + /// In case of a cycle, the position of deepest stack entry involved + /// in that cycle. This is monotonically decreasing in the stack as all + /// elements between the current stack element in the deepest stack entry + /// involved have to also be involved in that cycle. + /// + /// We can only move entries to the global cache once we're complete done + /// with the cycle. If this entry has not been involved in a cycle, + /// this is just its own depth. pub(super) depth: StackDepth, - // The goal for this entry. Should always be equal to the corresponding goal - // in the lookup table. + /// The goal for this entry. Should always be equal to the corresponding goal + /// in the lookup table. pub(super) input: CanonicalInput<'tcx>, } @@ -92,7 +96,7 @@ impl<'tcx> ProvisionalCache<'tcx> { self.entries[entry_index].depth } - pub(super) fn provisional_result(&self, entry_index: EntryIndex) -> QueryResult<'tcx> { + pub(super) fn provisional_result(&self, entry_index: EntryIndex) -> Option> { self.entries[entry_index].response } } diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs index 21c8d476902ab..b860f374c0ab3 100644 --- a/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/search_graph/mod.rs @@ -13,7 +13,7 @@ use rustc_middle::traits::solve::CacheData; use rustc_middle::traits::solve::{CanonicalInput, Certainty, EvaluationCache, QueryResult}; use rustc_middle::ty::TyCtxt; use rustc_session::Limit; -use std::{collections::hash_map::Entry, mem}; +use std::collections::hash_map::Entry; rustc_index::newtype_index! { pub struct StackDepth {} @@ -216,8 +216,8 @@ impl<'tcx> SearchGraph<'tcx> { cycle_participants: Default::default(), }; assert_eq!(self.stack.push(entry), depth); - let response = Self::response_no_constraints(tcx, input, Certainty::Yes); - let entry_index = cache.entries.push(ProvisionalEntry { response, depth, input }); + let entry_index = + cache.entries.push(ProvisionalEntry { response: None, depth, input }); v.insert(entry_index); } // We have a nested goal which relies on a goal `root` deeper in the stack. @@ -243,23 +243,31 @@ impl<'tcx> SearchGraph<'tcx> { root.cycle_participants.insert(e.input); } - // NOTE: The goals on the stack aren't the only goals involved in this cycle. - // We can also depend on goals which aren't part of the stack but coinductively - // depend on the stack themselves. We already checked whether all the goals - // between these goals and their root on the stack. This means that as long as - // each goal in a cycle is checked for coinductivity by itself, simply checking - // the stack is enough. - if self.stack.raw[stack_depth.index()..] - .iter() - .all(|g| g.input.value.goal.predicate.is_coinductive(tcx)) - { - // If we're in a coinductive cycle, we have to retry proving the current goal - // until we reach a fixpoint. - self.stack[stack_depth].has_been_used = true; - return cache.provisional_result(entry_index); + // If we're in a cycle, we have to retry proving the current goal + // until we reach a fixpoint. + self.stack[stack_depth].has_been_used = true; + return if let Some(result) = cache.provisional_result(entry_index) { + result } else { - return Self::response_no_constraints(tcx, input, Certainty::OVERFLOW); - } + // If we don't have a provisional result yet, the goal has to + // still be on the stack. + let mut goal_on_stack = false; + let mut is_coinductive = true; + for entry in self.stack.raw[stack_depth.index()..] + .iter() + .skip_while(|entry| entry.input != input) + { + goal_on_stack = true; + is_coinductive &= entry.input.value.goal.predicate.is_coinductive(tcx); + } + debug_assert!(goal_on_stack); + + if is_coinductive { + Self::response_no_constraints(tcx, input, Certainty::Yes) + } else { + Self::response_no_constraints(tcx, input, Certainty::OVERFLOW) + } + }; } } @@ -288,15 +296,18 @@ impl<'tcx> SearchGraph<'tcx> { let provisional_entry_index = *cache.lookup_table.get(&stack_entry.input).unwrap(); let provisional_entry = &mut cache.entries[provisional_entry_index]; - let prev_response = mem::replace(&mut provisional_entry.response, response); - if stack_entry.has_been_used && prev_response != response { - // If so, remove all entries whose result depends on this goal - // from the provisional cache... + if stack_entry.has_been_used + && provisional_entry.response.map_or(true, |r| r != response) + { + // If so, update the provisional result for this goal and remove + // all entries whose result depends on this goal from the provisional + // cache... // - // That's not completely correct, as a nested goal can also + // That's not completely correct, as a nested goal can also only // depend on a goal which is lower in the stack so it doesn't // actually depend on the current goal. This should be fairly // rare and is hopefully not relevant for performance. + provisional_entry.response = Some(response); #[allow(rustc::potential_query_instability)] cache.lookup_table.retain(|_key, index| *index <= provisional_entry_index); cache.entries.truncate(provisional_entry_index.index() + 1); @@ -315,8 +326,8 @@ impl<'tcx> SearchGraph<'tcx> { }); // We're now done with this goal. In case this goal is involved in a larger cycle - // do not remove it from the provisional cache and do not add it to the global - // cache. + // do not remove it from the provisional cache and update its provisional result. + // We only add the root of cycles to the global cache. // // It is not possible for any nested goal to depend on something deeper on the // stack, as this would have also updated the depth of the current goal. @@ -348,6 +359,8 @@ impl<'tcx> SearchGraph<'tcx> { dep_node, result, ) + } else { + provisional_entry.response = Some(result); } result diff --git a/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.rs b/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.rs index f06b98a79cfe3..3cfe7ab87f60a 100644 --- a/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.rs +++ b/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.rs @@ -39,7 +39,7 @@ fn impls_ar() {} fn main() { impls_a::<()>(); - //~^ ERROR overflow evaluating the requirement `(): A` + // FIXME(-Ztrait-solver=next): This is broken and should error. impls_ar::<()>(); //~^ ERROR overflow evaluating the requirement `(): AR` diff --git a/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.stderr b/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.stderr index 33fac603cbdda..0e1c86c1bb34a 100644 --- a/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.stderr +++ b/tests/ui/traits/new-solver/cycles/inductive-not-on-stack.stderr @@ -1,16 +1,3 @@ -error[E0275]: overflow evaluating the requirement `(): A` - --> $DIR/inductive-not-on-stack.rs:41:5 - | -LL | impls_a::<()>(); - | ^^^^^^^^^^^^^ - | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`inductive_not_on_stack`) -note: required by a bound in `impls_a` - --> $DIR/inductive-not-on-stack.rs:25:15 - | -LL | fn impls_a() {} - | ^ required by this bound in `impls_a` - error[E0275]: overflow evaluating the requirement `(): AR` --> $DIR/inductive-not-on-stack.rs:44:5 | @@ -24,6 +11,6 @@ note: required by a bound in `impls_ar` LL | fn impls_ar() {} | ^^ required by this bound in `impls_ar` -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0275`. From 02529d2cbecfd4edb6f481c8f0aaad9ad1fadfbb Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 10 Aug 2023 12:56:53 +0200 Subject: [PATCH 06/11] add and move trait solver cycle tests --- .../runaway-impl-candidate-selection.rs | 0 .../runaway-impl-candidate-selection.stderr | 0 .../fixpoint-exponential-growth.rs | 0 .../fixpoint-exponential-growth.stderr | 0 .../incompleteness-unstable-result.rs | 0 .../incompleteness-unstable-result.stderr | 0 .../double-cycle-inductive-coinductive.rs | 37 ++++++++++++++ .../double-cycle-inductive-coinductive.stderr | 29 +++++++++++ .../cycles/inductive-cycle-but-err.rs | 48 +++++++++++++++++++ .../cycles/inductive-cycle-but-err.stderr | 16 +++++++ .../cycles/inductive-cycle-but-ok.rs | 44 +++++++++++++++++ ...cycle-discarded-coinductive-constraints.rs | 36 ++++++++++++++ .../leak-check-coinductive-cycle.rs | 2 +- .../{ => cycles}/provisional-result-done.rs | 0 .../new-solver/dyn-any-dont-prefer-impl.rs | 4 ++ .../{ => overflow}/exponential-trait-goals.rs | 0 .../exponential-trait-goals.stderr | 0 .../recursive-self-normalization-2.rs | 0 .../recursive-self-normalization-2.stderr | 0 .../recursive-self-normalization.rs | 0 .../recursive-self-normalization.stderr | 0 21 files changed, 215 insertions(+), 1 deletion(-) rename tests/ui/traits/new-solver/{ => assembly}/runaway-impl-candidate-selection.rs (100%) rename tests/ui/traits/new-solver/{ => assembly}/runaway-impl-candidate-selection.stderr (100%) rename tests/ui/traits/new-solver/{ => cycles}/coinduction/fixpoint-exponential-growth.rs (100%) rename tests/ui/traits/new-solver/{ => cycles}/coinduction/fixpoint-exponential-growth.stderr (100%) rename tests/ui/traits/new-solver/{ => cycles}/coinduction/incompleteness-unstable-result.rs (100%) rename tests/ui/traits/new-solver/{ => cycles}/coinduction/incompleteness-unstable-result.stderr (100%) create mode 100644 tests/ui/traits/new-solver/cycles/double-cycle-inductive-coinductive.rs create mode 100644 tests/ui/traits/new-solver/cycles/double-cycle-inductive-coinductive.stderr create mode 100644 tests/ui/traits/new-solver/cycles/inductive-cycle-but-err.rs create mode 100644 tests/ui/traits/new-solver/cycles/inductive-cycle-but-err.stderr create mode 100644 tests/ui/traits/new-solver/cycles/inductive-cycle-but-ok.rs create mode 100644 tests/ui/traits/new-solver/cycles/inductive-cycle-discarded-coinductive-constraints.rs rename tests/ui/traits/new-solver/{ => cycles}/leak-check-coinductive-cycle.rs (100%) rename tests/ui/traits/new-solver/{ => cycles}/provisional-result-done.rs (100%) rename tests/ui/traits/new-solver/{ => overflow}/exponential-trait-goals.rs (100%) rename tests/ui/traits/new-solver/{ => overflow}/exponential-trait-goals.stderr (100%) rename tests/ui/traits/new-solver/{ => overflow}/recursive-self-normalization-2.rs (100%) rename tests/ui/traits/new-solver/{ => overflow}/recursive-self-normalization-2.stderr (100%) rename tests/ui/traits/new-solver/{ => overflow}/recursive-self-normalization.rs (100%) rename tests/ui/traits/new-solver/{ => overflow}/recursive-self-normalization.stderr (100%) diff --git a/tests/ui/traits/new-solver/runaway-impl-candidate-selection.rs b/tests/ui/traits/new-solver/assembly/runaway-impl-candidate-selection.rs similarity index 100% rename from tests/ui/traits/new-solver/runaway-impl-candidate-selection.rs rename to tests/ui/traits/new-solver/assembly/runaway-impl-candidate-selection.rs diff --git a/tests/ui/traits/new-solver/runaway-impl-candidate-selection.stderr b/tests/ui/traits/new-solver/assembly/runaway-impl-candidate-selection.stderr similarity index 100% rename from tests/ui/traits/new-solver/runaway-impl-candidate-selection.stderr rename to tests/ui/traits/new-solver/assembly/runaway-impl-candidate-selection.stderr diff --git a/tests/ui/traits/new-solver/coinduction/fixpoint-exponential-growth.rs b/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.rs similarity index 100% rename from tests/ui/traits/new-solver/coinduction/fixpoint-exponential-growth.rs rename to tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.rs diff --git a/tests/ui/traits/new-solver/coinduction/fixpoint-exponential-growth.stderr b/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.stderr similarity index 100% rename from tests/ui/traits/new-solver/coinduction/fixpoint-exponential-growth.stderr rename to tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.stderr diff --git a/tests/ui/traits/new-solver/coinduction/incompleteness-unstable-result.rs b/tests/ui/traits/new-solver/cycles/coinduction/incompleteness-unstable-result.rs similarity index 100% rename from tests/ui/traits/new-solver/coinduction/incompleteness-unstable-result.rs rename to tests/ui/traits/new-solver/cycles/coinduction/incompleteness-unstable-result.rs diff --git a/tests/ui/traits/new-solver/coinduction/incompleteness-unstable-result.stderr b/tests/ui/traits/new-solver/cycles/coinduction/incompleteness-unstable-result.stderr similarity index 100% rename from tests/ui/traits/new-solver/coinduction/incompleteness-unstable-result.stderr rename to tests/ui/traits/new-solver/cycles/coinduction/incompleteness-unstable-result.stderr diff --git a/tests/ui/traits/new-solver/cycles/double-cycle-inductive-coinductive.rs b/tests/ui/traits/new-solver/cycles/double-cycle-inductive-coinductive.rs new file mode 100644 index 0000000000000..5617e45adf6ab --- /dev/null +++ b/tests/ui/traits/new-solver/cycles/double-cycle-inductive-coinductive.rs @@ -0,0 +1,37 @@ +// compile-flags: -Ztrait-solver=next +#![feature(rustc_attrs)] + +// Test that having both an inductive and a coinductive cycle +// is handled correctly. + +#[rustc_coinductive] +trait Trait {} +impl Trait for T {} + +trait Inductive {} +impl Inductive for T {} +#[rustc_coinductive] +trait Coinductive {} +impl Coinductive for T {} + +fn impls_trait() {} + +#[rustc_coinductive] +trait TraitRev {} +impl TraitRev for T {} + +trait InductiveRev {} +impl InductiveRev for T {} +#[rustc_coinductive] +trait CoinductiveRev {} +impl CoinductiveRev for T {} + +fn impls_trait_rev() {} + +fn main() { + impls_trait::<()>(); + //~^ ERROR overflow evaluating the requirement + + impls_trait_rev::<()>(); + //~^ ERROR overflow evaluating the requirement +} diff --git a/tests/ui/traits/new-solver/cycles/double-cycle-inductive-coinductive.stderr b/tests/ui/traits/new-solver/cycles/double-cycle-inductive-coinductive.stderr new file mode 100644 index 0000000000000..4b8846da535f2 --- /dev/null +++ b/tests/ui/traits/new-solver/cycles/double-cycle-inductive-coinductive.stderr @@ -0,0 +1,29 @@ +error[E0275]: overflow evaluating the requirement `(): Trait` + --> $DIR/double-cycle-inductive-coinductive.rs:32:5 + | +LL | impls_trait::<()>(); + | ^^^^^^^^^^^^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`double_cycle_inductive_coinductive`) +note: required by a bound in `impls_trait` + --> $DIR/double-cycle-inductive-coinductive.rs:17:19 + | +LL | fn impls_trait() {} + | ^^^^^ required by this bound in `impls_trait` + +error[E0275]: overflow evaluating the requirement `(): TraitRev` + --> $DIR/double-cycle-inductive-coinductive.rs:35:5 + | +LL | impls_trait_rev::<()>(); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`double_cycle_inductive_coinductive`) +note: required by a bound in `impls_trait_rev` + --> $DIR/double-cycle-inductive-coinductive.rs:29:23 + | +LL | fn impls_trait_rev() {} + | ^^^^^^^^ required by this bound in `impls_trait_rev` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/new-solver/cycles/inductive-cycle-but-err.rs b/tests/ui/traits/new-solver/cycles/inductive-cycle-but-err.rs new file mode 100644 index 0000000000000..cda98789886c2 --- /dev/null +++ b/tests/ui/traits/new-solver/cycles/inductive-cycle-but-err.rs @@ -0,0 +1,48 @@ +// compile-flags: -Ztrait-solver=next +#![feature(trivial_bounds, marker_trait_attr)] +#![allow(trivial_bounds)] +// This previously triggered a bug in the provisional cache. +// +// This has the proof tree +// - `MultipleCandidates: Trait` proven via impl-one +// - `MultipleNested: Trait` via impl +// - `MultipleCandidates: Trait` (inductive cycle ~> OVERFLOW) +// - `DoesNotImpl: Trait` (ERR) +// - `MultipleCandidates: Trait` proven via impl-two +// - `MultipleNested: Trait` (in provisional cache ~> OVERFLOW) +// +// We previously incorrectly treated the `MultipleCandidates: Trait` as +// overflow because it was in the cache and reached via an inductive cycle. +// It should be `NoSolution`. + +struct MultipleCandidates; +struct MultipleNested; +struct DoesNotImpl; + +#[marker] +trait Trait {} + +// impl-one +impl Trait for MultipleCandidates +where + MultipleNested: Trait +{} + +// impl-two +impl Trait for MultipleCandidates +where + MultipleNested: Trait, +{} + +impl Trait for MultipleNested +where + MultipleCandidates: Trait, + DoesNotImpl: Trait, +{} + +fn impls_trait() {} + +fn main() { + impls_trait::(); + //~^ ERROR the trait bound `MultipleCandidates: Trait` is not satisfied +} diff --git a/tests/ui/traits/new-solver/cycles/inductive-cycle-but-err.stderr b/tests/ui/traits/new-solver/cycles/inductive-cycle-but-err.stderr new file mode 100644 index 0000000000000..57227321a6dbc --- /dev/null +++ b/tests/ui/traits/new-solver/cycles/inductive-cycle-but-err.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `MultipleCandidates: Trait` is not satisfied + --> $DIR/inductive-cycle-but-err.rs:46:19 + | +LL | impls_trait::(); + | ^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `MultipleCandidates` + | + = help: the trait `Trait` is implemented for `MultipleCandidates` +note: required by a bound in `impls_trait` + --> $DIR/inductive-cycle-but-err.rs:43:19 + | +LL | fn impls_trait() {} + | ^^^^^ required by this bound in `impls_trait` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/new-solver/cycles/inductive-cycle-but-ok.rs b/tests/ui/traits/new-solver/cycles/inductive-cycle-but-ok.rs new file mode 100644 index 0000000000000..d4851eb694bef --- /dev/null +++ b/tests/ui/traits/new-solver/cycles/inductive-cycle-but-ok.rs @@ -0,0 +1,44 @@ +// compile-flags: -Ztrait-solver=next +// check-pass +#![feature(trivial_bounds, marker_trait_attr)] +#![allow(trivial_bounds)] + +// This previously triggered a bug in the provisional cache. +// +// This has the proof tree +// - `Root: Trait` proven via impl +// - `MultipleCandidates: Trait` +// - candidate: overflow-impl +// - `Root: Trait` (inductive cycle ~> OVERFLOW) +// - candidate: trivial-impl ~> YES +// - merge respones ~> YES +// - `MultipleCandidates: Trait` (in provisional cache ~> OVERFLOW) +// +// We previously incorrectly treated the `MultipleCandidates: Trait` as +// overflow because it was in the cache and reached via an inductive cycle. +// It should be `YES`. + +struct Root; +struct MultipleCandidates; + +#[marker] +trait Trait {} +impl Trait for Root +where + MultipleCandidates: Trait, + MultipleCandidates: Trait, +{} + +// overflow-impl +impl Trait for MultipleCandidates +where + Root: Trait, +{} +// trivial-impl +impl Trait for MultipleCandidates {} + +fn impls_trait() {} + +fn main() { + impls_trait::(); +} diff --git a/tests/ui/traits/new-solver/cycles/inductive-cycle-discarded-coinductive-constraints.rs b/tests/ui/traits/new-solver/cycles/inductive-cycle-discarded-coinductive-constraints.rs new file mode 100644 index 0000000000000..530e6d0ecf322 --- /dev/null +++ b/tests/ui/traits/new-solver/cycles/inductive-cycle-discarded-coinductive-constraints.rs @@ -0,0 +1,36 @@ +// check-pass +// compile-flags: -Ztrait-solver=next +#![feature(rustc_attrs, marker_trait_attr)] +#[rustc_coinductive] +trait Trait {} + +impl Trait for (T, U) +where + (U, T): Trait, + (T, U): Inductive, + (): ConstrainToU32, +{} + +trait ConstrainToU32 {} +impl ConstrainToU32 for () {} + +// We only prefer the candidate without an inductive cycle +// once the inductive cycle has the same constraints as the +// other goal. +#[marker] +trait Inductive {} +impl Inductive for (T, U) +where + (T, U): Trait, +{} + +impl Inductive for (u32, u32) {} + +fn impls_trait() +where + (T, U): Trait, +{} + +fn main() { + impls_trait::<_, _>(); +} diff --git a/tests/ui/traits/new-solver/leak-check-coinductive-cycle.rs b/tests/ui/traits/new-solver/cycles/leak-check-coinductive-cycle.rs similarity index 100% rename from tests/ui/traits/new-solver/leak-check-coinductive-cycle.rs rename to tests/ui/traits/new-solver/cycles/leak-check-coinductive-cycle.rs index 1f7d4a49c9018..a6d3187267303 100644 --- a/tests/ui/traits/new-solver/leak-check-coinductive-cycle.rs +++ b/tests/ui/traits/new-solver/cycles/leak-check-coinductive-cycle.rs @@ -1,5 +1,5 @@ -// check-pass // compile-flags: -Ztrait-solver=next +// check-pass #![feature(rustc_attrs)] #[rustc_coinductive] diff --git a/tests/ui/traits/new-solver/provisional-result-done.rs b/tests/ui/traits/new-solver/cycles/provisional-result-done.rs similarity index 100% rename from tests/ui/traits/new-solver/provisional-result-done.rs rename to tests/ui/traits/new-solver/cycles/provisional-result-done.rs diff --git a/tests/ui/traits/new-solver/dyn-any-dont-prefer-impl.rs b/tests/ui/traits/new-solver/dyn-any-dont-prefer-impl.rs index 7d15b8c639250..af35a6195e007 100644 --- a/tests/ui/traits/new-solver/dyn-any-dont-prefer-impl.rs +++ b/tests/ui/traits/new-solver/dyn-any-dont-prefer-impl.rs @@ -1,6 +1,10 @@ // compile-flags: -Ztrait-solver=next // check-pass +// Test that selection prefers the builtin trait object impl for `Any` +// instead of the user defined impl. Both impls apply to the trait +// object. + use std::any::Any; fn needs_usize(_: &usize) {} diff --git a/tests/ui/traits/new-solver/exponential-trait-goals.rs b/tests/ui/traits/new-solver/overflow/exponential-trait-goals.rs similarity index 100% rename from tests/ui/traits/new-solver/exponential-trait-goals.rs rename to tests/ui/traits/new-solver/overflow/exponential-trait-goals.rs diff --git a/tests/ui/traits/new-solver/exponential-trait-goals.stderr b/tests/ui/traits/new-solver/overflow/exponential-trait-goals.stderr similarity index 100% rename from tests/ui/traits/new-solver/exponential-trait-goals.stderr rename to tests/ui/traits/new-solver/overflow/exponential-trait-goals.stderr diff --git a/tests/ui/traits/new-solver/recursive-self-normalization-2.rs b/tests/ui/traits/new-solver/overflow/recursive-self-normalization-2.rs similarity index 100% rename from tests/ui/traits/new-solver/recursive-self-normalization-2.rs rename to tests/ui/traits/new-solver/overflow/recursive-self-normalization-2.rs diff --git a/tests/ui/traits/new-solver/recursive-self-normalization-2.stderr b/tests/ui/traits/new-solver/overflow/recursive-self-normalization-2.stderr similarity index 100% rename from tests/ui/traits/new-solver/recursive-self-normalization-2.stderr rename to tests/ui/traits/new-solver/overflow/recursive-self-normalization-2.stderr diff --git a/tests/ui/traits/new-solver/recursive-self-normalization.rs b/tests/ui/traits/new-solver/overflow/recursive-self-normalization.rs similarity index 100% rename from tests/ui/traits/new-solver/recursive-self-normalization.rs rename to tests/ui/traits/new-solver/overflow/recursive-self-normalization.rs diff --git a/tests/ui/traits/new-solver/recursive-self-normalization.stderr b/tests/ui/traits/new-solver/overflow/recursive-self-normalization.stderr similarity index 100% rename from tests/ui/traits/new-solver/recursive-self-normalization.stderr rename to tests/ui/traits/new-solver/overflow/recursive-self-normalization.stderr From 051eb7ca7cfe439c2155005937b80219a5e81c49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 9 Aug 2023 16:44:06 +0200 Subject: [PATCH 07/11] Unlock trailing where-clauses for lazy type aliases --- compiler/rustc_ast_passes/messages.ftl | 7 +- .../rustc_ast_passes/src/ast_validation.rs | 99 ++++++++++--------- compiler/rustc_ast_passes/src/errors.rs | 30 +++++- .../leading-where-clause.fixed | 15 +++ .../lazy-type-alias/leading-where-clause.rs | 16 +++ .../leading-where-clause.stderr | 16 +++ .../lazy-type-alias/trailing-where-clause.rs | 13 +++ .../trailing-where-clause.stderr | 22 +++++ .../where-clause-placement-type-alias.stderr | 6 +- 9 files changed, 175 insertions(+), 49 deletions(-) create mode 100644 tests/ui/lazy-type-alias/leading-where-clause.fixed create mode 100644 tests/ui/lazy-type-alias/leading-where-clause.rs create mode 100644 tests/ui/lazy-type-alias/leading-where-clause.stderr create mode 100644 tests/ui/lazy-type-alias/trailing-where-clause.rs create mode 100644 tests/ui/lazy-type-alias/trailing-where-clause.stderr diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index 2f0ac0c2b1987..f323bb4c254e0 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -239,5 +239,10 @@ ast_passes_visibility_not_permitted = .individual_impl_items = place qualifiers on individual impl items instead .individual_foreign_items = place qualifiers on individual foreign items instead -ast_passes_where_after_type_alias = where clauses are not allowed after the type for type aliases +ast_passes_where_clause_after_type_alias = where clauses are not allowed after the type for type aliases + .note = see issue #112792 for more information + .help = add `#![feature(lazy_type_alias)]` to the crate attributes to enable + +ast_passes_where_clause_before_type_alias = where clauses are not allowed before the type for type aliases .note = see issue #89122 for more information + .suggestion = move it to the end of the type declaration diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index af594a00705f5..79fc9e4382fa3 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -136,40 +136,42 @@ impl<'a> AstValidator<'a> { } } - fn check_gat_where( + fn check_type_alias_where_clause_location( &mut self, - id: NodeId, - before_predicates: &[WherePredicate], - where_clauses: (ast::TyAliasWhereClause, ast::TyAliasWhereClause), - ) { - if !before_predicates.is_empty() { - let mut state = State::new(); - if !where_clauses.1.0 { - state.space(); - state.word_space("where"); - } else { + ty_alias: &TyAlias, + ) -> Result<(), errors::WhereClauseBeforeTypeAlias> { + let before_predicates = + ty_alias.generics.where_clause.predicates.split_at(ty_alias.where_predicates_split).0; + + if ty_alias.ty.is_none() || before_predicates.is_empty() { + return Ok(()); + } + + let mut state = State::new(); + if !ty_alias.where_clauses.1.0 { + state.space(); + state.word_space("where"); + } else { + state.word_space(","); + } + let mut first = true; + for p in before_predicates { + if !first { state.word_space(","); } - let mut first = true; - for p in before_predicates.iter() { - if !first { - state.word_space(","); - } - first = false; - state.print_where_predicate(p); - } - let suggestion = state.s.eof(); - self.lint_buffer.buffer_lint_with_diagnostic( - DEPRECATED_WHERE_CLAUSE_LOCATION, - id, - where_clauses.0.1, - fluent::ast_passes_deprecated_where_clause_location, - BuiltinLintDiagnostics::DeprecatedWhereclauseLocation( - where_clauses.1.1.shrink_to_hi(), - suggestion, - ), - ); + first = false; + state.print_where_predicate(p); } + + let span = ty_alias.where_clauses.0.1; + Err(errors::WhereClauseBeforeTypeAlias { + span, + sugg: errors::WhereClauseBeforeTypeAliasSugg { + left: span, + snippet: state.s.eof(), + right: ty_alias.where_clauses.1.1.shrink_to_hi(), + }, + }) } fn with_impl_trait(&mut self, outer: Option, f: impl FnOnce(&mut Self)) { @@ -1009,7 +1011,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> { replace_span: self.ending_semi_or_hi(item.span), }); } - ItemKind::TyAlias(box TyAlias { defaultness, where_clauses, bounds, ty, .. }) => { + ItemKind::TyAlias( + ty_alias @ box TyAlias { defaultness, bounds, where_clauses, ty, .. }, + ) => { self.check_defaultness(item.span, *defaultness); if ty.is_none() { self.session.emit_err(errors::TyAliasWithoutBody { @@ -1018,9 +1022,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> { }); } self.check_type_no_bounds(bounds, "this context"); - if where_clauses.1.0 { - self.err_handler() - .emit_err(errors::WhereAfterTypeAlias { span: where_clauses.1.1 }); + + if self.session.features_untracked().lazy_type_alias { + if let Err(err) = self.check_type_alias_where_clause_location(ty_alias) { + self.err_handler().emit_err(err); + } + } else if where_clauses.1.0 { + self.err_handler().emit_err(errors::WhereClauseAfterTypeAlias { + span: where_clauses.1.1, + help: self.session.is_nightly_build().then_some(()), + }); } } _ => {} @@ -1313,18 +1324,18 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } - if let AssocItemKind::Type(box TyAlias { - generics, - where_clauses, - where_predicates_split, - ty: Some(_), - .. - }) = &item.kind + if let AssocItemKind::Type(ty_alias) = &item.kind + && let Err(err) = self.check_type_alias_where_clause_location(ty_alias) { - self.check_gat_where( + self.lint_buffer.buffer_lint_with_diagnostic( + DEPRECATED_WHERE_CLAUSE_LOCATION, item.id, - generics.where_clause.predicates.split_at(*where_predicates_split).0, - *where_clauses, + err.span, + fluent::ast_passes_deprecated_where_clause_location, + BuiltinLintDiagnostics::DeprecatedWhereclauseLocation( + err.sugg.right, + err.sugg.snippet, + ), ); } diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index ab8015c4a43b6..a6f217d4780fd 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -496,11 +496,37 @@ pub struct FieldlessUnion { } #[derive(Diagnostic)] -#[diag(ast_passes_where_after_type_alias)] +#[diag(ast_passes_where_clause_after_type_alias)] #[note] -pub struct WhereAfterTypeAlias { +pub struct WhereClauseAfterTypeAlias { #[primary_span] pub span: Span, + #[help] + pub help: Option<()>, +} + +#[derive(Diagnostic)] +#[diag(ast_passes_where_clause_before_type_alias)] +#[note] +pub struct WhereClauseBeforeTypeAlias { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub sugg: WhereClauseBeforeTypeAliasSugg, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + ast_passes_suggestion, + applicability = "machine-applicable", + style = "verbose" +)] +pub struct WhereClauseBeforeTypeAliasSugg { + #[suggestion_part(code = "")] + pub left: Span, + pub snippet: String, + #[suggestion_part(code = "{snippet}")] + pub right: Span, } #[derive(Diagnostic)] diff --git a/tests/ui/lazy-type-alias/leading-where-clause.fixed b/tests/ui/lazy-type-alias/leading-where-clause.fixed new file mode 100644 index 0000000000000..07ebc09b30ee6 --- /dev/null +++ b/tests/ui/lazy-type-alias/leading-where-clause.fixed @@ -0,0 +1,15 @@ +// run-rustfix + +#![feature(lazy_type_alias)] +#![allow(incomplete_features)] + +// Check that we *reject* leading where-clauses on lazy type aliases. + +type Alias + += T where String: From; +//~^^^ ERROR where clauses are not allowed before the type for type aliases + +fn main() { + let _: Alias<&str>; +} diff --git a/tests/ui/lazy-type-alias/leading-where-clause.rs b/tests/ui/lazy-type-alias/leading-where-clause.rs new file mode 100644 index 0000000000000..4a6542934720d --- /dev/null +++ b/tests/ui/lazy-type-alias/leading-where-clause.rs @@ -0,0 +1,16 @@ +// run-rustfix + +#![feature(lazy_type_alias)] +#![allow(incomplete_features)] + +// Check that we *reject* leading where-clauses on lazy type aliases. + +type Alias +where + String: From, += T; +//~^^^ ERROR where clauses are not allowed before the type for type aliases + +fn main() { + let _: Alias<&str>; +} diff --git a/tests/ui/lazy-type-alias/leading-where-clause.stderr b/tests/ui/lazy-type-alias/leading-where-clause.stderr new file mode 100644 index 0000000000000..8ddf0ce6c6558 --- /dev/null +++ b/tests/ui/lazy-type-alias/leading-where-clause.stderr @@ -0,0 +1,16 @@ +error: where clauses are not allowed before the type for type aliases + --> $DIR/leading-where-clause.rs:9:1 + | +LL | / where +LL | | String: From, + | |____________________^ + | + = note: see issue #89122 for more information +help: move it to the end of the type declaration + | +LL + +LL ~ = T where String: From; + | + +error: aborting due to previous error + diff --git a/tests/ui/lazy-type-alias/trailing-where-clause.rs b/tests/ui/lazy-type-alias/trailing-where-clause.rs new file mode 100644 index 0000000000000..ac9598fe5f6aa --- /dev/null +++ b/tests/ui/lazy-type-alias/trailing-where-clause.rs @@ -0,0 +1,13 @@ +#![feature(lazy_type_alias)] +#![allow(incomplete_features)] + +// Check that we allow & respect trailing where-clauses on lazy type aliases. + +type Alias = T +where + String: From; + +fn main() { + let _: Alias<&str>; + let _: Alias<()>; //~ ERROR the trait bound `String: From<()>` is not satisfied +} diff --git a/tests/ui/lazy-type-alias/trailing-where-clause.stderr b/tests/ui/lazy-type-alias/trailing-where-clause.stderr new file mode 100644 index 0000000000000..d7606ba6b2a9c --- /dev/null +++ b/tests/ui/lazy-type-alias/trailing-where-clause.stderr @@ -0,0 +1,22 @@ +error[E0277]: the trait bound `String: From<()>` is not satisfied + --> $DIR/trailing-where-clause.rs:12:12 + | +LL | let _: Alias<()>; + | ^^^^^^^^^ the trait `From<()>` is not implemented for `String` + | + = help: the following other types implement trait `From`: + > + >> + >> + > + > + > +note: required by a bound on the type alias `Alias` + --> $DIR/trailing-where-clause.rs:8:13 + | +LL | String: From; + | ^^^^^^^ required by this bound + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/where-clauses/where-clause-placement-type-alias.stderr b/tests/ui/where-clauses/where-clause-placement-type-alias.stderr index b3c155a48ddbc..d341148b04cb5 100644 --- a/tests/ui/where-clauses/where-clause-placement-type-alias.stderr +++ b/tests/ui/where-clauses/where-clause-placement-type-alias.stderr @@ -4,7 +4,8 @@ error: where clauses are not allowed after the type for type aliases LL | type Bar = () where u32: Copy; | ^^^^^^^^^^^^^^^ | - = note: see issue #89122 for more information + = note: see issue #112792 for more information + = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable error: where clauses are not allowed after the type for type aliases --> $DIR/where-clause-placement-type-alias.rs:8:15 @@ -12,7 +13,8 @@ error: where clauses are not allowed after the type for type aliases LL | type Baz = () where; | ^^^^^ | - = note: see issue #89122 for more information + = note: see issue #112792 for more information + = help: add `#![feature(lazy_type_alias)]` to the crate attributes to enable error: aborting due to 2 previous errors From 8b29ad721589de1e757ca92f654f0fee39c4e427 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 7 Aug 2023 19:02:56 -0300 Subject: [PATCH 08/11] Fix copy & paste doc error --- compiler/rustc_smir/src/stable_mir/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_smir/src/stable_mir/mod.rs b/compiler/rustc_smir/src/stable_mir/mod.rs index d93f25249b9ef..b242468547c94 100644 --- a/compiler/rustc_smir/src/stable_mir/mod.rs +++ b/compiler/rustc_smir/src/stable_mir/mod.rs @@ -32,7 +32,7 @@ pub type DefId = usize; /// A list of crate items. pub type CrateItems = Vec; -/// A list of crate items. +/// A list of trait decls. pub type TraitDecls = Vec; /// Holds information about a crate. From 5f0e662523c3bb37c6a3891a28e61775f4fb5dfb Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 7 Aug 2023 19:03:05 -0300 Subject: [PATCH 09/11] Add impl trait declarations to SMIR --- compiler/rustc_smir/src/rustc_internal/mod.rs | 12 +++++++ compiler/rustc_smir/src/rustc_smir/mod.rs | 36 +++++++++++++++++++ compiler/rustc_smir/src/stable_mir/mod.rs | 7 +++- compiler/rustc_smir/src/stable_mir/ty.rs | 21 +++++++++++ 4 files changed, 75 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 0d9157940f827..078ff67446f6e 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -63,6 +63,10 @@ pub fn trait_def(did: DefId) -> stable_mir::ty::TraitDef { with_tables(|t| t.trait_def(did)) } +pub fn impl_def(did: DefId) -> stable_mir::ty::ImplDef { + with_tables(|t| t.impl_def(did)) +} + impl<'tcx> Tables<'tcx> { pub fn item_def_id(&self, item: &stable_mir::CrateItem) -> DefId { self.def_ids[item.0] @@ -72,6 +76,10 @@ impl<'tcx> Tables<'tcx> { self.def_ids[trait_def.0] } + pub fn impl_trait_def_id(&self, impl_def: &stable_mir::ty::ImplDef) -> DefId { + self.def_ids[impl_def.0] + } + pub fn crate_item(&mut self, did: DefId) -> stable_mir::CrateItem { stable_mir::CrateItem(self.create_def_id(did)) } @@ -116,6 +124,10 @@ impl<'tcx> Tables<'tcx> { stable_mir::ty::ConstDef(self.create_def_id(did)) } + pub fn impl_def(&mut self, did: DefId) -> stable_mir::ty::ImplDef { + stable_mir::ty::ImplDef(self.create_def_id(did)) + } + fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId { // FIXME: this becomes inefficient when we have too many ids for (i, &d) in self.def_ids.iter().enumerate() { diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index f782138f87056..6ab473c3b54c5 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -59,6 +59,20 @@ impl<'tcx> Context for Tables<'tcx> { trait_def.stable(self) } + fn all_trait_impls(&mut self) -> stable_mir::ImplTraitDecls { + self.tcx + .trait_impls_in_crate(LOCAL_CRATE) + .iter() + .map(|impl_def_id| self.impl_def(*impl_def_id)) + .collect() + } + + fn trait_impl(&mut self, impl_def: &stable_mir::ty::ImplDef) -> stable_mir::ty::ImplTrait { + let def_id = self.impl_trait_def_id(impl_def); + let impl_trait = self.tcx.impl_trait_ref(def_id).unwrap(); + impl_trait.stable(self) + } + fn mir_body(&mut self, item: &stable_mir::CrateItem) -> stable_mir::mir::Body { let def_id = self.item_def_id(item); let mir = self.tcx.optimized_mir(def_id); @@ -840,6 +854,19 @@ where } } +impl<'tcx, S, V> Stable<'tcx> for ty::EarlyBinder +where + S: Stable<'tcx, T = V>, +{ + type T = stable_mir::ty::EarlyBinder; + + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + use stable_mir::ty::EarlyBinder; + + EarlyBinder { value: self.as_ref().skip_binder().stable(tables) } + } +} + impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> { type T = stable_mir::ty::FnSig; fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { @@ -1154,3 +1181,12 @@ impl<'tcx> Stable<'tcx> for rustc_middle::mir::ConstantKind<'tcx> { } } } + +impl<'tcx> Stable<'tcx> for ty::TraitRef<'tcx> { + type T = stable_mir::ty::TraitRef; + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + use stable_mir::ty::TraitRef; + + TraitRef { def_id: rustc_internal::trait_def(self.def_id), args: self.args.stable(tables) } + } +} diff --git a/compiler/rustc_smir/src/stable_mir/mod.rs b/compiler/rustc_smir/src/stable_mir/mod.rs index b242468547c94..a74975cefc2cd 100644 --- a/compiler/rustc_smir/src/stable_mir/mod.rs +++ b/compiler/rustc_smir/src/stable_mir/mod.rs @@ -15,7 +15,7 @@ use std::cell::Cell; use crate::rustc_smir::Tables; -use self::ty::{TraitDecl, TraitDef, Ty, TyKind}; +use self::ty::{ImplDef, ImplTrait, TraitDecl, TraitDef, Ty, TyKind}; pub mod mir; pub mod ty; @@ -35,6 +35,9 @@ pub type CrateItems = Vec; /// A list of trait decls. pub type TraitDecls = Vec; +/// A list of impl trait decls. +pub type ImplTraitDecls = Vec; + /// Holds information about a crate. #[derive(Clone, PartialEq, Eq, Debug)] pub struct Crate { @@ -89,6 +92,8 @@ pub trait Context { fn mir_body(&mut self, item: &CrateItem) -> mir::Body; fn all_trait_decls(&mut self) -> TraitDecls; fn trait_decl(&mut self, trait_def: &TraitDef) -> TraitDecl; + fn all_trait_impls(&mut self) -> ImplTraitDecls; + fn trait_impl(&mut self, trait_impl: &ImplDef) -> ImplTrait; /// Get information about the local crate. fn local_crate(&self) -> Crate; /// Retrieve a list of all external crates. diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index e83ca88da1b69..8a23af75749ac 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -119,6 +119,15 @@ impl TraitDef { } } +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct ImplDef(pub(crate) DefId); + +impl ImplDef { + pub fn trait_impl(&self) -> ImplTrait { + with(|cx| cx.trait_impl(self)) + } +} + #[derive(Clone, Debug)] pub struct GenericArgs(pub Vec); @@ -196,6 +205,11 @@ pub struct Binder { pub bound_vars: Vec, } +#[derive(Clone, Debug)] +pub struct EarlyBinder { + pub value: T, +} + #[derive(Clone, Debug)] pub enum BoundVariableKind { Ty(BoundTyKind), @@ -432,3 +446,10 @@ pub struct TraitDecl { pub implement_via_object: bool, pub deny_explicit_impl: bool, } + +pub type ImplTrait = EarlyBinder; + +pub struct TraitRef { + pub def_id: TraitDef, + pub args: GenericArgs, +} From fad7c4dcaad361bd589c2cd817c75271bbb5117b Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 10 Aug 2023 16:00:30 -0300 Subject: [PATCH 10/11] Add spastorino to mailmap --- .mailmap | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.mailmap b/.mailmap index 601064b77d438..a7957efededcf 100644 --- a/.mailmap +++ b/.mailmap @@ -495,6 +495,8 @@ Ryan Wiedemann S Pradeep Kumar Sam Radhakrishnan Samuel Tardieu +Santiago Pastorino +Santiago Pastorino Scott McMurray Scott Olson Scott Olson Sean Gillespie swgillespie From 540afe202ff26668907c3b4954f4dcfefac1b628 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 10 Aug 2023 21:15:19 +0000 Subject: [PATCH 11/11] Comment nits --- compiler/rustc_hir_typeck/src/coercion.rs | 8 +++++--- compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs | 4 ---- compiler/rustc_trait_selection/src/traits/select/mod.rs | 2 +- compiler/rustc_type_ir/src/sty.rs | 4 +++- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 8a7d411ffc845..1cfdc5b9e7f57 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -510,9 +510,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { success(adjustments, ty, obligations) } - // &[T; n] or &mut [T; n] -> &[T] - // or &mut [T; n] -> &mut [T] - // or &Concrete -> &Trait, etc. + /// Performs [unsized coercion] by emulating a fulfillment loop on a + /// `CoerceUnsized` goal until all `CoerceUnsized` and `Unsize` goals + /// are successfully selected. + /// + /// [unsized coercion](https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions) #[instrument(skip(self), level = "debug")] fn coerce_unsized(&self, mut source: Ty<'tcx>, mut target: Ty<'tcx>) -> CoerceResult<'tcx> { source = self.shallow_resolve(source); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index bc4448fe57034..28fe2e062e589 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -618,8 +618,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match *self_ty.kind() { ty::Infer(ty::TyVar(found_vid)) => { - // FIXME: consider using `sub_root_var` here so we - // can see through subtyping. let found_vid = self.root_var(found_vid); debug!("self_type_matches_expected_vid - found_vid={:?}", found_vid); expected_vid == found_vid @@ -634,8 +632,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self_ty: ty::TyVid, ) -> impl DoubleEndedIterator> + Captures<'tcx> + 'b { - // FIXME: consider using `sub_root_var` here so we - // can see through subtyping. let ty_var_root = self.root_var(self_ty); trace!("pending_obligations = {:#?}", self.fulfillment_cx.borrow().pending_obligations()); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index f1bd9f8b71a71..4371b6c1239ee 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2394,7 +2394,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { Ok(args) => args, Err(()) => { // FIXME: A rematch may fail when a candidate cache hit occurs - // on thefreshened form of the trait predicate, but the match + // on the freshened form of the trait predicate, but the match // fails for some reason that is not captured in the freshened // cache key. For example, equating an impl trait ref against // the placeholder trait ref may fail due the Generalizer relation diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs index ec0dbffc22f26..72bd50ace6de8 100644 --- a/compiler/rustc_type_ir/src/sty.rs +++ b/compiler/rustc_type_ir/src/sty.rs @@ -200,7 +200,9 @@ pub enum TyKind { /// A tuple type. For example, `(i32, bool)`. Tuple(I::ListTy), - /// A projection or opaque type. Both of these types + /// A projection, opaque type, weak type alias, or inherent associated type. + /// All of these types are represented as pairs of def-id and args, and can + /// be normalized, so they are grouped conceptually. Alias(AliasKind, I::AliasTy), /// A type parameter; for example, `T` in `fn f(x: T) {}`.