From eb10db0a76fdacdbe6747431aea90f17ce4ec7c1 Mon Sep 17 00:00:00 2001 From: Will Crichton Date: Wed, 11 Dec 2024 16:40:54 -0800 Subject: [PATCH 01/14] Make some types and methods related to Polonius + Miri public. --- compiler/rustc_borrowck/src/borrow_set.rs | 24 +++++++++---------- compiler/rustc_borrowck/src/consumers.rs | 4 ++-- .../rustc_const_eval/src/interpret/operand.rs | 24 +++++++++++++------ .../rustc_const_eval/src/interpret/stack.rs | 4 +++- 4 files changed, 34 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs index 16b3d901956cc..d66f613c71e0b 100644 --- a/compiler/rustc_borrowck/src/borrow_set.rs +++ b/compiler/rustc_borrowck/src/borrow_set.rs @@ -20,18 +20,18 @@ pub struct BorrowSet<'tcx> { /// by the `Location` of the assignment statement in which it /// appears on the right hand side. Thus the location is the map /// key, and its position in the map corresponds to `BorrowIndex`. - pub(crate) location_map: FxIndexMap>, + pub location_map: FxIndexMap>, /// Locations which activate borrows. /// NOTE: a given location may activate more than one borrow in the future /// when more general two-phase borrow support is introduced, but for now we /// only need to store one borrow index. - pub(crate) activation_map: FxIndexMap>, + pub activation_map: FxIndexMap>, /// Map from local to all the borrows on that local. - pub(crate) local_map: FxIndexMap>, + pub local_map: FxIndexMap>, - pub(crate) locals_state_at_exit: LocalsStateAtExit, + pub locals_state_at_exit: LocalsStateAtExit, } impl<'tcx> Index for BorrowSet<'tcx> { @@ -45,7 +45,7 @@ impl<'tcx> Index for BorrowSet<'tcx> { /// Location where a two-phase borrow is activated, if a borrow /// is in fact a two-phase borrow. #[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub(crate) enum TwoPhaseActivation { +pub enum TwoPhaseActivation { NotTwoPhase, NotActivated, ActivatedAt(Location), @@ -55,17 +55,17 @@ pub(crate) enum TwoPhaseActivation { pub struct BorrowData<'tcx> { /// Location where the borrow reservation starts. /// In many cases, this will be equal to the activation location but not always. - pub(crate) reserve_location: Location, + pub reserve_location: Location, /// Location where the borrow is activated. - pub(crate) activation_location: TwoPhaseActivation, + pub activation_location: TwoPhaseActivation, /// What kind of borrow this is - pub(crate) kind: mir::BorrowKind, + pub kind: mir::BorrowKind, /// The region for which this borrow is live - pub(crate) region: RegionVid, + pub region: RegionVid, /// Place from which we are borrowing - pub(crate) borrowed_place: mir::Place<'tcx>, + pub borrowed_place: mir::Place<'tcx>, /// Place to which the borrow was stored - pub(crate) assigned_place: mir::Place<'tcx>, + pub assigned_place: mir::Place<'tcx>, } impl<'tcx> fmt::Display for BorrowData<'tcx> { @@ -120,7 +120,7 @@ impl LocalsStateAtExit { } impl<'tcx> BorrowSet<'tcx> { - pub(crate) fn build( + pub fn build( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, locals_are_invalidated_at_exit: bool, diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs index 7ace38c3e85ff..74de766ba2317 100644 --- a/compiler/rustc_borrowck/src/consumers.rs +++ b/compiler/rustc_borrowck/src/consumers.rs @@ -5,15 +5,15 @@ use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::mir::{Body, Promoted}; use rustc_middle::ty::TyCtxt; +pub use super::borrow_set::{BorrowData, BorrowSet, TwoPhaseActivation}; pub use super::constraints::OutlivesConstraint; pub use super::dataflow::{BorrowIndex, Borrows, calculate_borrows_out_of_scope_at_location}; -pub use super::facts::{AllFacts as PoloniusInput, RustcFacts}; +pub use super::facts::{AllFacts as PoloniusInput, PoloniusRegionVid, RustcFacts}; pub use super::location::{LocationTable, RichLocation}; pub use super::nll::PoloniusOutput; pub use super::place_ext::PlaceExt; pub use super::places_conflict::{PlaceConflictBias, places_conflict}; pub use super::region_infer::RegionInferenceContext; -use crate::borrow_set::BorrowSet; /// Options determining the output behavior of [`get_body_with_borrowck_facts`]. /// diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 0157e6c2125e5..bd33e8d20c09b 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -15,9 +15,9 @@ use rustc_middle::{bug, mir, span_bug, ty}; use tracing::trace; use super::{ - CtfeProvenance, InterpCx, InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta, OffsetMode, - PlaceTy, Pointer, Projectable, Provenance, Scalar, alloc_range, err_ub, from_known_layout, - interp_ok, mir_assign_valid_types, throw_ub, + CtfeProvenance, Frame, InterpCx, InterpResult, MPlaceTy, Machine, MemPlace, MemPlaceMeta, + OffsetMode, PlaceTy, Pointer, Projectable, Provenance, Scalar, alloc_range, err_ub, + from_known_layout, interp_ok, mir_assign_valid_types, throw_ub, }; /// An `Immediate` represents a single immediate self-contained Rust value. @@ -706,17 +706,27 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { interp_ok(str) } - /// Read from a local of the current frame. + /// Read from a local of the current frame. Convenience method for [`InterpCx::local_at_frame_to_op`]. + pub fn local_to_op( + &self, + local: mir::Local, + layout: Option>, + ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { + self.local_at_frame_to_op(self.frame(), local, layout) + } + + /// Read from a local of a given frame. /// Will not access memory, instead an indirect `Operand` is returned. /// - /// This is public because it is used by [priroda](https://github.com/oli-obk/priroda) to get an + /// This is public because it is used by [priroda](https://github.com/oli-obk/priroda) and + /// [Aquascope](https://github.com/cognitive-engineering-lab/aquascope/) to get an /// OpTy from a local. - pub fn local_to_op( + pub fn local_at_frame_to_op( &self, + frame: &Frame<'tcx, M::Provenance, M::FrameExtra>, local: mir::Local, layout: Option>, ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { - let frame = self.frame(); let layout = self.layout_of_local(frame, local, layout)?; let op = *frame.locals[local].access()?; if matches!(op, Operand::Immediate(_)) { diff --git a/compiler/rustc_const_eval/src/interpret/stack.rs b/compiler/rustc_const_eval/src/interpret/stack.rs index a9ebf38661703..6512675530a45 100644 --- a/compiler/rustc_const_eval/src/interpret/stack.rs +++ b/compiler/rustc_const_eval/src/interpret/stack.rs @@ -584,8 +584,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { interp_ok(()) } + /// This is public because it is used by [Aquascope](https://github.com/cognitive-engineering-lab/aquascope/) + /// to analyze all the locals in a stack frame. #[inline(always)] - pub(super) fn layout_of_local( + pub fn layout_of_local( &self, frame: &Frame<'tcx, M::Provenance, M::FrameExtra>, local: mir::Local, From de53fe245d7f937640bef68a4eb3622b43c39674 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 12 Dec 2024 18:33:33 +1100 Subject: [PATCH 02/14] coverage: Tidy up creation of covmap records --- .../src/coverageinfo/mapgen.rs | 60 +++++++++---------- 1 file changed, 27 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index a573a37beb3fa..7c7903ce84290 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -75,9 +75,6 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { // Encode all filenames referenced by coverage mappings in this CGU. let filenames_buffer = global_file_table.make_filenames_buffer(tcx); - - let filenames_size = filenames_buffer.len(); - let filenames_val = cx.const_bytes(&filenames_buffer); let filenames_ref = llvm_cov::hash_bytes(&filenames_buffer); let mut unused_function_names = Vec::new(); @@ -126,7 +123,7 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { // Generate the coverage map header, which contains the filenames used by // this CGU's coverage mappings, and store it in a well-known global. // (This is skipped if we returned early due to having no covfun records.) - generate_covmap_record(cx, covmap_version, filenames_size, filenames_val); + generate_covmap_record(cx, covmap_version, &filenames_buffer); } /// Maps "global" (per-CGU) file ID numbers to their underlying filenames. @@ -225,38 +222,35 @@ fn span_file_name(tcx: TyCtxt<'_>, span: Span) -> Symbol { /// Generates the contents of the covmap record for this CGU, which mostly /// consists of a header and a list of filenames. The record is then stored /// as a global variable in the `__llvm_covmap` section. -fn generate_covmap_record<'ll>( - cx: &CodegenCx<'ll, '_>, - version: u32, - filenames_size: usize, - filenames_val: &'ll llvm::Value, -) { - debug!("cov map: filenames_size = {}, 0-based version = {}", filenames_size, version); - - // Create the coverage data header (Note, fields 0 and 2 are now always zero, - // as of `llvm::coverage::CovMapVersion::Version4`.) - let zero_was_n_records_val = cx.const_u32(0); - let filenames_size_val = cx.const_u32(filenames_size as u32); - let zero_was_coverage_size_val = cx.const_u32(0); - let version_val = cx.const_u32(version); - let cov_data_header_val = cx.const_struct( - &[zero_was_n_records_val, filenames_size_val, zero_was_coverage_size_val, version_val], - /*packed=*/ false, +fn generate_covmap_record<'ll>(cx: &CodegenCx<'ll, '_>, version: u32, filenames_buffer: &[u8]) { + // A covmap record consists of four target-endian u32 values, followed by + // the encoded filenames table. Two of the header fields are unused in + // modern versions of the LLVM coverage mapping format, and are always 0. + // + // See also `src/llvm-project/clang/lib/CodeGen/CoverageMappingGen.cpp`. + let covmap_header = cx.const_struct( + &[ + cx.const_u32(0), // (unused) + cx.const_u32(filenames_buffer.len() as u32), + cx.const_u32(0), // (unused) + cx.const_u32(version), + ], + /* packed */ false, ); - - // Create the complete LLVM coverage data value to add to the LLVM IR - let covmap_data = - cx.const_struct(&[cov_data_header_val, filenames_val], /*packed=*/ false); - - let llglobal = llvm::add_global(cx.llmod, cx.val_ty(covmap_data), &llvm_cov::covmap_var_name()); - llvm::set_initializer(llglobal, covmap_data); - llvm::set_global_constant(llglobal, true); - llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage); - llvm::set_section(llglobal, &llvm_cov::covmap_section_name(cx.llmod)); + let covmap_record = cx + .const_struct(&[covmap_header, cx.const_bytes(filenames_buffer)], /* packed */ false); + + let covmap_global = + llvm::add_global(cx.llmod, cx.val_ty(covmap_record), &llvm_cov::covmap_var_name()); + llvm::set_initializer(covmap_global, covmap_record); + llvm::set_global_constant(covmap_global, true); + llvm::set_linkage(covmap_global, llvm::Linkage::PrivateLinkage); + llvm::set_section(covmap_global, &llvm_cov::covmap_section_name(cx.llmod)); // LLVM's coverage mapping format specifies 8-byte alignment for items in this section. // - llvm::set_alignment(llglobal, Align::EIGHT); - cx.add_used_global(llglobal); + llvm::set_alignment(covmap_global, Align::EIGHT); + + cx.add_used_global(covmap_global); } /// Each CGU will normally only emit coverage metadata for the functions that it actually generates. From 5f5745beb06cac3f0d0cabf1d8edd1ffa53a9b55 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 12 Dec 2024 20:28:10 +1100 Subject: [PATCH 03/14] coverage: Tidy up creation of covfun records --- .../src/coverageinfo/mapgen.rs | 7 ++- .../src/coverageinfo/mapgen/covfun.rs | 59 +++++++++---------- 2 files changed, 34 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 7c7903ce84290..4f2af73252751 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -75,7 +75,10 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { // Encode all filenames referenced by coverage mappings in this CGU. let filenames_buffer = global_file_table.make_filenames_buffer(tcx); - let filenames_ref = llvm_cov::hash_bytes(&filenames_buffer); + // The `llvm-cov` tool uses this hash to associate each covfun record with + // its corresponding filenames table, since the final binary will typically + // contain multiple covmap records from different compilation units. + let filenames_hash = llvm_cov::hash_bytes(&filenames_buffer); let mut unused_function_names = Vec::new(); @@ -98,7 +101,7 @@ pub(crate) fn finalize(cx: &CodegenCx<'_, '_>) { for covfun in &covfun_records { unused_function_names.extend(covfun.mangled_function_name_if_unused()); - covfun::generate_covfun_record(cx, filenames_ref, covfun) + covfun::generate_covfun_record(cx, filenames_hash, covfun) } // For unused functions, we need to take their mangled names and store them diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs index 530e6827f55d3..33e7a0f2f201b 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs @@ -136,7 +136,7 @@ fn fill_region_tables<'tcx>( /// as a global variable in the `__llvm_covfun` section. pub(crate) fn generate_covfun_record<'tcx>( cx: &CodegenCx<'_, 'tcx>, - filenames_ref: u64, + filenames_hash: u64, covfun: &CovfunRecord<'tcx>, ) { let &CovfunRecord { @@ -155,46 +155,45 @@ pub(crate) fn generate_covfun_record<'tcx>( regions, ); - // Concatenate the encoded coverage mappings - let coverage_mapping_size = coverage_mapping_buffer.len(); - let coverage_mapping_val = cx.const_bytes(&coverage_mapping_buffer); - + // A covfun record consists of four target-endian integers, followed by the + // encoded mapping data in bytes. Note that the length field is 32 bits. + // + // See also `src/llvm-project/clang/lib/CodeGen/CoverageMappingGen.cpp` and + // `COVMAP_V3` in `src/llvm-project/llvm/include/llvm/ProfileData/InstrProfData.inc`. let func_name_hash = llvm_cov::hash_bytes(mangled_function_name.as_bytes()); - let func_name_hash_val = cx.const_u64(func_name_hash); - let coverage_mapping_size_val = cx.const_u32(coverage_mapping_size as u32); - let source_hash_val = cx.const_u64(source_hash); - let filenames_ref_val = cx.const_u64(filenames_ref); - let func_record_val = cx.const_struct( + let covfun_record = cx.const_struct( &[ - func_name_hash_val, - coverage_mapping_size_val, - source_hash_val, - filenames_ref_val, - coverage_mapping_val, + cx.const_u64(func_name_hash), + cx.const_u32(coverage_mapping_buffer.len() as u32), + cx.const_u64(source_hash), + cx.const_u64(filenames_hash), + cx.const_bytes(&coverage_mapping_buffer), ], - /*packed=*/ true, + // This struct needs to be packed, so that the 32-bit length field + // doesn't have unexpected padding. + true, ); // Choose a variable name to hold this function's covfun data. // Functions that are used have a suffix ("u") to distinguish them from // unused copies of the same function (from different CGUs), so that if a // linker sees both it won't discard the used copy's data. - let func_record_var_name = - CString::new(format!("__covrec_{:X}{}", func_name_hash, if is_used { "u" } else { "" })) - .unwrap(); - debug!("function record var name: {:?}", func_record_var_name); - - let llglobal = llvm::add_global(cx.llmod, cx.val_ty(func_record_val), &func_record_var_name); - llvm::set_initializer(llglobal, func_record_val); - llvm::set_global_constant(llglobal, true); - llvm::set_linkage(llglobal, llvm::Linkage::LinkOnceODRLinkage); - llvm::set_visibility(llglobal, llvm::Visibility::Hidden); - llvm::set_section(llglobal, cx.covfun_section_name()); + let u = if is_used { "u" } else { "" }; + let covfun_var_name = CString::new(format!("__covrec_{func_name_hash:X}{u}")).unwrap(); + debug!("function record var name: {covfun_var_name:?}"); + + let covfun_global = llvm::add_global(cx.llmod, cx.val_ty(covfun_record), &covfun_var_name); + llvm::set_initializer(covfun_global, covfun_record); + llvm::set_global_constant(covfun_global, true); + llvm::set_linkage(covfun_global, llvm::Linkage::LinkOnceODRLinkage); + llvm::set_visibility(covfun_global, llvm::Visibility::Hidden); + llvm::set_section(covfun_global, cx.covfun_section_name()); // LLVM's coverage mapping format specifies 8-byte alignment for items in this section. // - llvm::set_alignment(llglobal, Align::EIGHT); + llvm::set_alignment(covfun_global, Align::EIGHT); if cx.target_spec().supports_comdat() { - llvm::set_comdat(cx.llmod, llglobal, &func_record_var_name); + llvm::set_comdat(cx.llmod, covfun_global, &covfun_var_name); } - cx.add_used_global(llglobal); + + cx.add_used_global(covfun_global); } From 8200c1e52e1f67cee0546b288a72154407cf1c0a Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 12 Dec 2024 13:26:09 -0700 Subject: [PATCH 04/14] rustdoc-search: fix mismatched path when parent re-exported twice --- src/librustdoc/html/render/search_index.rs | 8 ++++++++ tests/rustdoc-js/reexport.js | 9 +++++++++ tests/rustdoc-js/reexport.rs | 9 +++++++++ 3 files changed, 26 insertions(+) diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index cfb62c3ca1640..134438efa5ec2 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -423,6 +423,14 @@ pub(crate) fn build_index( } Some(path) }); + } else if let Some(parent_idx) = item.parent_idx { + let i = >::try_into(parent_idx).unwrap(); + item.path = { + let p = &crate_paths[i].1; + join_with_double_colon(&p[..p.len() - 1]) + }; + item.exact_path = + crate_paths[i].2.as_ref().map(|xp| join_with_double_colon(&xp[..xp.len() - 1])); } // Omit the parent path if it is same to that of the prior item. diff --git a/tests/rustdoc-js/reexport.js b/tests/rustdoc-js/reexport.js index 9021cc2e90fe0..0b9415dd3e480 100644 --- a/tests/rustdoc-js/reexport.js +++ b/tests/rustdoc-js/reexport.js @@ -14,4 +14,13 @@ const EXPECTED = [ { 'path': 'reexport', 'name': 'AnotherOne' }, ], }, + { + 'query': 'fn:Equivalent::equivalent', + 'others': [ + // These results must never contain `reexport::equivalent::NotEquivalent`, + // since that path does not exist. + { 'path': 'equivalent::Equivalent', 'name': 'equivalent' }, + { 'path': 'reexport::NotEquivalent', 'name': 'equivalent' }, + ], + }, ]; diff --git a/tests/rustdoc-js/reexport.rs b/tests/rustdoc-js/reexport.rs index 0b3718cd9a3e8..ecbbeca5ea89d 100644 --- a/tests/rustdoc-js/reexport.rs +++ b/tests/rustdoc-js/reexport.rs @@ -2,6 +2,15 @@ // This is a DWIM case, since renaming the export probably means the intent is also different. // For the de-duplication case of exactly the same name, see reexport-dedup +//@ aux-crate:equivalent=equivalent.rs +//@ compile-flags: --extern equivalent +//@ aux-build:equivalent.rs +//@ build-aux-docs +#[doc(inline)] +pub extern crate equivalent; +#[doc(inline)] +pub use equivalent::Equivalent as NotEquivalent; + pub mod fmt { pub struct Subscriber; } From 4d5d4700f3c7fa5151560d27f389c15a7a3047a0 Mon Sep 17 00:00:00 2001 From: Will Crichton Date: Thu, 12 Dec 2024 12:34:43 -0800 Subject: [PATCH 05/14] Make BorrowSet/BorrowData fields accessible via public getters --- compiler/rustc_borrowck/src/borrow_set.rs | 66 ++++++++++++++++--- .../rustc_const_eval/src/interpret/machine.rs | 8 ++- .../rustc_const_eval/src/interpret/operand.rs | 7 +- src/tools/miri/src/machine.rs | 8 ++- 4 files changed, 71 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs index d66f613c71e0b..ff838fbbb8868 100644 --- a/compiler/rustc_borrowck/src/borrow_set.rs +++ b/compiler/rustc_borrowck/src/borrow_set.rs @@ -20,18 +20,37 @@ pub struct BorrowSet<'tcx> { /// by the `Location` of the assignment statement in which it /// appears on the right hand side. Thus the location is the map /// key, and its position in the map corresponds to `BorrowIndex`. - pub location_map: FxIndexMap>, + pub(crate) location_map: FxIndexMap>, /// Locations which activate borrows. /// NOTE: a given location may activate more than one borrow in the future /// when more general two-phase borrow support is introduced, but for now we /// only need to store one borrow index. - pub activation_map: FxIndexMap>, + pub(crate) activation_map: FxIndexMap>, /// Map from local to all the borrows on that local. - pub local_map: FxIndexMap>, + pub(crate) local_map: FxIndexMap>, - pub locals_state_at_exit: LocalsStateAtExit, + pub(crate) locals_state_at_exit: LocalsStateAtExit, +} + +// These methods are public to support borrowck consumers. +impl<'tcx> BorrowSet<'tcx> { + pub fn location_map(&self) -> &FxIndexMap> { + &self.location_map + } + + pub fn activation_map(&self) -> &FxIndexMap> { + &self.activation_map + } + + pub fn local_map(&self) -> &FxIndexMap> { + &self.local_map + } + + pub fn locals_state_at_exit(&self) -> &LocalsStateAtExit { + &self.locals_state_at_exit + } } impl<'tcx> Index for BorrowSet<'tcx> { @@ -55,17 +74,44 @@ pub enum TwoPhaseActivation { pub struct BorrowData<'tcx> { /// Location where the borrow reservation starts. /// In many cases, this will be equal to the activation location but not always. - pub reserve_location: Location, + pub(crate) reserve_location: Location, /// Location where the borrow is activated. - pub activation_location: TwoPhaseActivation, + pub(crate) activation_location: TwoPhaseActivation, /// What kind of borrow this is - pub kind: mir::BorrowKind, + pub(crate) kind: mir::BorrowKind, /// The region for which this borrow is live - pub region: RegionVid, + pub(crate) region: RegionVid, /// Place from which we are borrowing - pub borrowed_place: mir::Place<'tcx>, + pub(crate) borrowed_place: mir::Place<'tcx>, /// Place to which the borrow was stored - pub assigned_place: mir::Place<'tcx>, + pub(crate) assigned_place: mir::Place<'tcx>, +} + +// These methods are public to support borrowck consumers. +impl<'tcx> BorrowData<'tcx> { + pub fn reserve_location(&self) -> Location { + self.reserve_location + } + + pub fn activation_location(&self) -> TwoPhaseActivation { + self.activation_location + } + + pub fn kind(&self) -> mir::BorrowKind { + self.kind + } + + pub fn region(&self) -> RegionVid { + self.region + } + + pub fn borrowed_place(&self) -> mir::Place<'tcx> { + self.borrowed_place + } + + pub fn assigned_place(&self) -> mir::Place<'tcx> { + self.assigned_place + } } impl<'tcx> fmt::Display for BorrowData<'tcx> { diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index a180d5da9418b..9ac2a024ccf37 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -540,10 +540,14 @@ pub trait Machine<'tcx>: Sized { interp_ok(ReturnAction::Normal) } - /// Called immediately after an "immediate" local variable is read + /// Called immediately after an "immediate" local variable is read in a given frame /// (i.e., this is called for reads that do not end up accessing addressable memory). #[inline(always)] - fn after_local_read(_ecx: &InterpCx<'tcx, Self>, _local: mir::Local) -> InterpResult<'tcx> { + fn after_local_read( + _ecx: &InterpCx<'tcx, Self>, + _frame: &Frame<'tcx, Self::Provenance, Self::FrameExtra>, + _local: mir::Local, + ) -> InterpResult<'tcx> { interp_ok(()) } diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index bd33e8d20c09b..9d2a7125f5105 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -718,9 +718,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// Read from a local of a given frame. /// Will not access memory, instead an indirect `Operand` is returned. /// - /// This is public because it is used by [priroda](https://github.com/oli-obk/priroda) and - /// [Aquascope](https://github.com/cognitive-engineering-lab/aquascope/) to get an - /// OpTy from a local. + /// This is public because it is used by [Aquascope](https://github.com/cognitive-engineering-lab/aquascope/) + /// to get an OpTy from a local. pub fn local_at_frame_to_op( &self, frame: &Frame<'tcx, M::Provenance, M::FrameExtra>, @@ -732,7 +731,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { if matches!(op, Operand::Immediate(_)) { assert!(!layout.is_unsized()); } - M::after_local_read(self, local)?; + M::after_local_read(self, frame, local)?; interp_ok(OpTy { op, layout }) } diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 7cc22f83a24a6..ac26feb345c18 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1571,8 +1571,12 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { res } - fn after_local_read(ecx: &InterpCx<'tcx, Self>, local: mir::Local) -> InterpResult<'tcx> { - if let Some(data_race) = &ecx.frame().extra.data_race { + fn after_local_read( + ecx: &InterpCx<'tcx, Self>, + frame: &Frame<'tcx, Provenance, FrameExtra<'tcx>>, + local: mir::Local, + ) -> InterpResult<'tcx> { + if let Some(data_race) = &frame.extra.data_race { data_race.local_read(local, &ecx.machine); } interp_ok(()) From ead78fdfdf6692b2ecef7f47dfc934011c51fe4c Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 12 Dec 2024 11:40:36 +0000 Subject: [PATCH 06/14] Remove jobserver from Session It is effectively a global resource and the jobserver::Client in Session was a clone of GLOBAL_CLIENT anyway. --- Cargo.lock | 1 - .../rustc_codegen_cranelift/src/concurrency_limiter.rs | 10 ++++------ compiler/rustc_codegen_cranelift/src/driver/aot.rs | 4 ++-- compiler/rustc_codegen_cranelift/src/lib.rs | 1 - compiler/rustc_codegen_ssa/Cargo.toml | 1 - compiler/rustc_codegen_ssa/src/back/write.rs | 7 ++----- compiler/rustc_data_structures/src/jobserver.rs | 2 +- compiler/rustc_session/src/session.rs | 6 ------ 8 files changed, 9 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 38b009bfc7000..923d4017c0cad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3507,7 +3507,6 @@ dependencies = [ "cc", "either", "itertools", - "jobserver", "libc", "object 0.36.5", "pathdiff", diff --git a/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs b/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs index 2093b49ff31a7..b5a81fc11d57b 100644 --- a/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs +++ b/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs @@ -1,8 +1,7 @@ use std::sync::{Arc, Condvar, Mutex}; -use jobserver::HelperThread; +use rustc_data_structures::jobserver::{self, HelperThread}; use rustc_errors::DiagCtxtHandle; -use rustc_session::Session; // FIXME don't panic when a worker thread panics @@ -14,14 +13,13 @@ pub(super) struct ConcurrencyLimiter { } impl ConcurrencyLimiter { - pub(super) fn new(sess: &Session, pending_jobs: usize) -> Self { + pub(super) fn new(pending_jobs: usize) -> Self { let state = Arc::new(Mutex::new(state::ConcurrencyLimiterState::new(pending_jobs))); let available_token_condvar = Arc::new(Condvar::new()); let state_helper = state.clone(); let available_token_condvar_helper = available_token_condvar.clone(); - let helper_thread = sess - .jobserver + let helper_thread = jobserver::client() .clone() .into_helper_thread(move |token| { let mut state = state_helper.lock().unwrap(); @@ -113,7 +111,7 @@ impl Drop for ConcurrencyLimiterToken { } mod state { - use jobserver::Acquired; + use rustc_data_structures::jobserver::Acquired; #[derive(Debug)] pub(super) struct ConcurrencyLimiterState { diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index 5bbcfc2cda7d7..4fc30b69123dd 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -679,7 +679,7 @@ pub(crate) fn run_aot( metadata_module: None, metadata, crate_info: CrateInfo::new(tcx, target_cpu), - concurrency_limiter: ConcurrencyLimiter::new(tcx.sess, 0), + concurrency_limiter: ConcurrencyLimiter::new(0), }); }; @@ -711,7 +711,7 @@ pub(crate) fn run_aot( CguReuse::PreLto | CguReuse::PostLto => false, }); - let concurrency_limiter = IntoDynSyncSend(ConcurrencyLimiter::new(tcx.sess, todo_cgus.len())); + let concurrency_limiter = IntoDynSyncSend(ConcurrencyLimiter::new(todo_cgus.len())); let modules = tcx.sess.time("codegen mono items", || { let mut modules: Vec<_> = par_map(todo_cgus, |(_, cgu)| { diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 9f552b3feb950..c3a1617b49500 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -12,7 +12,6 @@ #![warn(unused_lifetimes)] // tidy-alphabetical-end -extern crate jobserver; #[macro_use] extern crate rustc_middle; extern crate rustc_abi; diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index c81e36dfc8d0a..450a95ae20cdd 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -11,7 +11,6 @@ bitflags = "2.4.1" cc = "1.1.23" either = "1.5.0" itertools = "0.12" -jobserver = "0.1.28" pathdiff = "0.2.0" regex = "1.4" rustc_abi = { path = "../rustc_abi" } diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 501f751791936..683defcafee24 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -6,9 +6,9 @@ use std::sync::Arc; use std::sync::mpsc::{Receiver, Sender, channel}; use std::{fs, io, mem, str, thread}; -use jobserver::{Acquired, Client}; use rustc_ast::attr; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; +use rustc_data_structures::jobserver::{self, Acquired}; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::profiling::{SelfProfilerRef, VerboseTimingGuard}; use rustc_errors::emitter::Emitter; @@ -456,7 +456,6 @@ pub(crate) fn start_async_codegen( metadata_module: Option, ) -> OngoingCodegen { let (coordinator_send, coordinator_receive) = channel(); - let sess = tcx.sess; let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID); let no_builtins = attr::contains_name(crate_attrs, sym::no_builtins); @@ -477,7 +476,6 @@ pub(crate) fn start_async_codegen( shared_emitter, codegen_worker_send, coordinator_receive, - sess.jobserver.clone(), Arc::new(regular_config), Arc::new(metadata_config), Arc::new(allocator_config), @@ -1093,7 +1091,6 @@ fn start_executing_work( shared_emitter: SharedEmitter, codegen_worker_send: Sender, coordinator_receive: Receiver>, - jobserver: Client, regular_config: Arc, metadata_config: Arc, allocator_config: Arc, @@ -1145,7 +1142,7 @@ fn start_executing_work( // get tokens on `coordinator_receive` which will // get managed in the main loop below. let coordinator_send2 = coordinator_send.clone(); - let helper = jobserver + let helper = jobserver::client() .into_helper_thread(move |token| { drop(coordinator_send2.send(Box::new(Message::Token::(token)))); }) diff --git a/compiler/rustc_data_structures/src/jobserver.rs b/compiler/rustc_data_structures/src/jobserver.rs index d09f7efc8ffff..1204f2d692d6c 100644 --- a/compiler/rustc_data_structures/src/jobserver.rs +++ b/compiler/rustc_data_structures/src/jobserver.rs @@ -1,6 +1,6 @@ use std::sync::{LazyLock, OnceLock}; -pub use jobserver_crate::Client; +pub use jobserver_crate::{Acquired, Client, HelperThread}; use jobserver_crate::{FromEnv, FromEnvErrorKind}; // We can only call `from_env_ext` once per process diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 993d111466bed..160525cead032 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -8,7 +8,6 @@ use std::{env, fmt, io}; use rustc_data_structures::flock; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; -use rustc_data_structures::jobserver::{self, Client}; use rustc_data_structures::profiling::{SelfProfiler, SelfProfilerRef}; use rustc_data_structures::sync::{ DynSend, DynSync, Lock, Lrc, MappedReadGuard, ReadGuard, RwLock, @@ -154,10 +153,6 @@ pub struct Session { /// Data about code being compiled, gathered during compilation. pub code_stats: CodeStats, - /// Loaded up early on in the initialization of this `Session` to avoid - /// false positives about a job server in our environment. - pub jobserver: Client, - /// This only ever stores a `LintStore` but we don't want a dependency on that type here. pub lint_store: Option>, @@ -1072,7 +1067,6 @@ pub fn build_session( incr_comp_session: RwLock::new(IncrCompSession::NotInitialized), prof, code_stats: Default::default(), - jobserver: jobserver::client(), lint_store: None, registered_lints: false, driver_lint_caps, From 981f625ba7c8e8ddcf6e470eb54d822eaf9fb300 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 12 Dec 2024 11:45:10 +0000 Subject: [PATCH 07/14] Remove registered_lints field from Session It only exists to pass some information from one part of the driver to another part. We can directly pass this information to the function that needs it to reduce the amount of mutation of the Session. --- compiler/rustc_driver_impl/src/lib.rs | 8 +++++--- compiler/rustc_interface/src/interface.rs | 1 - compiler/rustc_session/src/session.rs | 4 ---- src/librustdoc/lib.rs | 4 +++- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 2e01c385a6670..b8d5281087efa 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -350,6 +350,8 @@ fn run_compiler( callbacks.config(&mut config); + let registered_lints = config.register_lints.is_some(); + interface::run_compiler(config, |compiler| { let sess = &compiler.sess; let codegen_backend = &*compiler.codegen_backend; @@ -365,7 +367,7 @@ fn run_compiler( // `--help`/`-Zhelp`/`-Chelp`. This is the earliest it can run, because // it must happen after lints are registered, during session creation. if sess.opts.describe_lints { - describe_lints(sess); + describe_lints(sess, registered_lints); return early_exit(); } @@ -982,7 +984,7 @@ the command line flag directly. } /// Write to stdout lint command options, together with a list of all available lints -pub fn describe_lints(sess: &Session) { +pub fn describe_lints(sess: &Session, registered_lints: bool) { safe_println!( " Available lint options: @@ -1086,7 +1088,7 @@ Available lint options: print_lint_groups(builtin_groups, true); - match (sess.registered_lints, loaded.len(), loaded_groups.len()) { + match (registered_lints, loaded.len(), loaded_groups.len()) { (false, 0, _) | (false, _, 0) => { safe_println!("Lint tools like Clippy can load additional lints and lint groups."); } diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 07ae24ee6d32b..7ad893f61ab5e 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -479,7 +479,6 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se let mut lint_store = rustc_lint::new_lint_store(sess.enable_internal_lints()); if let Some(register_lints) = config.register_lints.as_deref() { register_lints(&sess, &mut lint_store); - sess.registered_lints = true; } sess.lint_store = Some(Lrc::new(lint_store)); diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 160525cead032..9f6106f9cfb7e 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -156,9 +156,6 @@ pub struct Session { /// This only ever stores a `LintStore` but we don't want a dependency on that type here. pub lint_store: Option>, - /// Should be set if any lints are registered in `lint_store`. - pub registered_lints: bool, - /// Cap lint level specified by a driver specifically. pub driver_lint_caps: FxHashMap, @@ -1068,7 +1065,6 @@ pub fn build_session( prof, code_stats: Default::default(), lint_store: None, - registered_lints: false, driver_lint_caps, ctfe_backtrace, miri_unleashed_features: Lock::new(Default::default()), diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index a384c286039d2..5d82b8e309a6a 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -846,11 +846,13 @@ fn main_args( let config = core::create_config(input, options, &render_options, using_internal_features); + let registered_lints = config.register_lints.is_some(); + interface::run_compiler(config, |compiler| { let sess = &compiler.sess; if sess.opts.describe_lints { - rustc_driver::describe_lints(sess); + rustc_driver::describe_lints(sess, registered_lints); return; } From ea9e8c13dc94949ab38370c39559110da33c878f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 12 Dec 2024 13:46:16 +0000 Subject: [PATCH 08/14] Explain why an untranslatable_diagnostic occurs --- compiler/rustc_interface/src/interface.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 7ad893f61ab5e..91f190c6a28de 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -371,7 +371,6 @@ pub(crate) fn initialize_checked_jobserver(early_dcx: &EarlyDiagCtxt) { // JUSTIFICATION: before session exists, only config #[allow(rustc::bad_opt_access)] -#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Send) -> R { trace!("run_compiler"); @@ -425,7 +424,11 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se config.opts.unstable_opts.translate_directionality_markers, ) { Ok(bundle) => bundle, - Err(e) => early_dcx.early_fatal(format!("failed to load fluent bundle: {e}")), + Err(e) => { + // We can't translate anything if we failed to load translations + #[allow(rustc::untranslatable_diagnostic)] + early_dcx.early_fatal(format!("failed to load fluent bundle: {e}")) + } }; let mut locale_resources = config.locale_resources; From 4e8359c7e0469a86297053a6fbba5afe38602cb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Fri, 13 Dec 2024 12:17:46 +0100 Subject: [PATCH 09/14] Fix building `std` for Hermit after `c_char` change --- library/std/src/sys/pal/hermit/fs.rs | 6 +++--- library/std/src/sys/pal/hermit/mod.rs | 2 +- library/std/src/sys/pal/hermit/os.rs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/library/std/src/sys/pal/hermit/fs.rs b/library/std/src/sys/pal/hermit/fs.rs index 11862a076082d..88fc40687195d 100644 --- a/library/std/src/sys/pal/hermit/fs.rs +++ b/library/std/src/sys/pal/hermit/fs.rs @@ -3,7 +3,7 @@ use super::hermit_abi::{ self, DT_DIR, DT_LNK, DT_REG, DT_UNKNOWN, O_APPEND, O_CREAT, O_DIRECTORY, O_EXCL, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY, S_IFDIR, S_IFLNK, S_IFMT, S_IFREG, dirent64, stat as stat_struct, }; -use crate::ffi::{CStr, OsStr, OsString}; +use crate::ffi::{CStr, OsStr, OsString, c_char}; use crate::io::{self, BorrowedCursor, Error, ErrorKind, IoSlice, IoSliceMut, SeekFrom}; use crate::os::hermit::ffi::OsStringExt; use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd}; @@ -204,7 +204,7 @@ impl Iterator for ReadDir { // the size of dirent64. The file name is always a C string and terminated by `\0`. // Consequently, we are able to ignore the last byte. let name_bytes = - unsafe { CStr::from_ptr(&dir.d_name as *const _ as *const i8).to_bytes() }; + unsafe { CStr::from_ptr(&dir.d_name as *const _ as *const c_char).to_bytes() }; let entry = DirEntry { root: self.inner.root.clone(), ino: dir.d_ino, @@ -445,7 +445,7 @@ impl DirBuilder { pub fn mkdir(&self, path: &Path) -> io::Result<()> { run_path_with_cstr(path, &|path| { - cvt(unsafe { hermit_abi::mkdir(path.as_ptr(), self.mode.into()) }).map(|_| ()) + cvt(unsafe { hermit_abi::mkdir(path.as_ptr().cast(), self.mode.into()) }).map(|_| ()) }) } diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs index f03fca603441d..d833c9d632c6d 100644 --- a/library/std/src/sys/pal/hermit/mod.rs +++ b/library/std/src/sys/pal/hermit/mod.rs @@ -85,7 +85,7 @@ pub unsafe extern "C" fn runtime_entry( } // initialize environment - os::init_environment(env as *const *const i8); + os::init_environment(env); let result = unsafe { main(argc as isize, argv) }; diff --git a/library/std/src/sys/pal/hermit/os.rs b/library/std/src/sys/pal/hermit/os.rs index f8ea80afa43f1..791cdb1e57e7d 100644 --- a/library/std/src/sys/pal/hermit/os.rs +++ b/library/std/src/sys/pal/hermit/os.rs @@ -3,7 +3,7 @@ use core::slice::memchr; use super::hermit_abi; use crate::collections::HashMap; use crate::error::Error as StdError; -use crate::ffi::{CStr, OsStr, OsString}; +use crate::ffi::{CStr, OsStr, OsString, c_char}; use crate::marker::PhantomData; use crate::os::hermit::ffi::OsStringExt; use crate::path::{self, PathBuf}; @@ -70,7 +70,7 @@ pub fn current_exe() -> io::Result { static ENV: Mutex>> = Mutex::new(None); -pub fn init_environment(env: *const *const i8) { +pub fn init_environment(env: *const *const c_char) { let mut guard = ENV.lock().unwrap(); let map = guard.insert(HashMap::new()); From 3198496385cd8fdd89818e0bf14bacd8db6292d9 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 12 Dec 2024 14:44:18 +0000 Subject: [PATCH 10/14] Make dependency_formats an FxIndexMap rather than a list of tuples It is treated as a map already. This is using FxIndexMap rather than UnordMap because the latter doesn't provide an api to pick a single value iff all values are equal, which each_linked_rlib depends on. --- .../rustc_codegen_cranelift/src/driver/jit.rs | 7 +--- compiler/rustc_codegen_ssa/src/back/link.rs | 34 +++++++------------ compiler/rustc_codegen_ssa/src/back/linker.rs | 2 +- .../rustc_metadata/src/dependency_format.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 5 +-- .../src/middle/dependency_format.rs | 3 +- src/tools/miri/src/helpers.rs | 5 ++- 7 files changed, 21 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs index d68948966eaeb..4be4291021dfa 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs @@ -287,12 +287,7 @@ fn dep_symbol_lookup_fn( let mut dylib_paths = Vec::new(); - let data = &crate_info - .dependency_formats - .iter() - .find(|(crate_type, _data)| *crate_type == rustc_session::config::CrateType::Executable) - .unwrap() - .1; + let data = &crate_info.dependency_formats[&rustc_session::config::CrateType::Executable].1; // `used_crates` is in reverse postorder in terms of dependencies. Reverse the order here to // get a postorder which ensures that all dependencies of a dylib are loaded before the dylib // itself. This helps the dynamic linker to find dylibs not in the regular dynamic library diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 35d18d0206dbb..31ac8c6e66aae 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -236,7 +236,13 @@ pub fn each_linked_rlib( ) -> Result<(), errors::LinkRlibError> { let crates = info.used_crates.iter(); - let fmts = if crate_type.is_none() { + let fmts = if let Some(crate_type) = crate_type { + let Some(fmts) = info.dependency_formats.get(&crate_type) else { + return Err(errors::LinkRlibError::MissingFormat); + }; + + fmts + } else { for combination in info.dependency_formats.iter().combinations(2) { let (ty1, list1) = &combination[0]; let (ty2, list2) = &combination[1]; @@ -252,18 +258,7 @@ pub fn each_linked_rlib( if info.dependency_formats.is_empty() { return Err(errors::LinkRlibError::MissingFormat); } - &info.dependency_formats[0].1 - } else { - let fmts = info - .dependency_formats - .iter() - .find_map(|&(ty, ref list)| if Some(ty) == crate_type { Some(list) } else { None }); - - let Some(fmts) = fmts else { - return Err(errors::LinkRlibError::MissingFormat); - }; - - fmts + info.dependency_formats.first().unwrap().1 }; for &cnum in crates { @@ -624,8 +619,7 @@ fn link_staticlib( let fmts = codegen_results .crate_info .dependency_formats - .iter() - .find_map(|&(ty, ref list)| if ty == CrateType::Staticlib { Some(list) } else { None }) + .get(&CrateType::Staticlib) .expect("no dependency formats for staticlib"); let mut all_rust_dylibs = vec![]; @@ -2355,11 +2349,10 @@ fn linker_with_args( // they are used within inlined functions or instantiated generic functions. We do this *after* // handling the raw-dylib symbols in the current crate to make sure that those are chosen first // by the linker. - let (_, dependency_linkage) = codegen_results + let dependency_linkage = codegen_results .crate_info .dependency_formats - .iter() - .find(|(ty, _)| *ty == crate_type) + .get(&crate_type) .expect("failed to find crate type in dependency format list"); // We sort the libraries below @@ -2738,11 +2731,10 @@ fn add_upstream_rust_crates( // Linking to a rlib involves just passing it to the linker (the linker // will slurp up the object files inside), and linking to a dynamic library // involves just passing the right -l flag. - let (_, data) = codegen_results + let data = codegen_results .crate_info .dependency_formats - .iter() - .find(|(ty, _)| *ty == crate_type) + .get(&crate_type) .expect("failed to find crate type in dependency format list"); if sess.target.is_like_aix { diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 4c5eb98e890e8..301b22f2be4f8 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -1749,7 +1749,7 @@ fn for_each_exported_symbols_include_dep<'tcx>( } let formats = tcx.dependency_formats(()); - let deps = formats.iter().find_map(|(t, list)| (*t == crate_type).then_some(list)).unwrap(); + let deps = &formats[&crate_type]; for (index, dep_format) in deps.iter().enumerate() { let cnum = CrateNum::new(index + 1); diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs index 641d1d8e79819..e8de0acb7c9fe 100644 --- a/compiler/rustc_metadata/src/dependency_format.rs +++ b/compiler/rustc_metadata/src/dependency_format.rs @@ -77,7 +77,7 @@ pub(crate) fn calculate(tcx: TyCtxt<'_>) -> Dependencies { verify_ok(tcx, &linkage); (ty, linkage) }) - .collect::>() + .collect() } fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 5c80d24f502d1..5548406502b4e 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -2164,10 +2164,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_dylib_dependency_formats(&mut self) -> LazyArray> { empty_proc_macro!(self); let formats = self.tcx.dependency_formats(()); - for (ty, arr) in formats.iter() { - if *ty != CrateType::Dylib { - continue; - } + if let Some(arr) = formats.get(&CrateType::Dylib) { return self.lazy_array(arr.iter().map(|slot| match *slot { Linkage::NotLinked | Linkage::IncludedFromDylib => None, diff --git a/compiler/rustc_middle/src/middle/dependency_format.rs b/compiler/rustc_middle/src/middle/dependency_format.rs index a3aff9a110130..e3b40b6415784 100644 --- a/compiler/rustc_middle/src/middle/dependency_format.rs +++ b/compiler/rustc_middle/src/middle/dependency_format.rs @@ -7,6 +7,7 @@ // FIXME: move this file to rustc_metadata::dependency_format, but // this will introduce circular dependency between rustc_metadata and rustc_middle +use rustc_data_structures::fx::FxIndexMap; use rustc_macros::{Decodable, Encodable, HashStable}; use rustc_session::config::CrateType; @@ -18,7 +19,7 @@ pub type DependencyList = Vec; /// A mapping of all required dependencies for a particular flavor of output. /// /// This is local to the tcx, and is generally relevant to one session. -pub type Dependencies = Vec<(CrateType, DependencyList)>; +pub type Dependencies = FxIndexMap; #[derive(Copy, Clone, PartialEq, Debug, HashStable, Encodable, Decodable)] pub enum Linkage { diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index b57ce4e070c38..1f7c60ad1bdfe 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -149,10 +149,9 @@ pub fn iter_exported_symbols<'tcx>( let dependency_formats = tcx.dependency_formats(()); // Find the dependencies of the executable we are running. let dependency_format = dependency_formats - .iter() - .find(|(crate_type, _)| *crate_type == CrateType::Executable) + .get(&CrateType::Executable) .expect("interpreting a non-executable crate"); - for cnum in dependency_format.1.iter().enumerate().filter_map(|(num, &linkage)| { + for cnum in dependency_format.iter().enumerate().filter_map(|(num, &linkage)| { // We add 1 to the number because that's what rustc also does everywhere it // calls `CrateNum::new`... #[expect(clippy::arithmetic_side_effects)] From af530c4927d4b6018662c092ebcf629f17eb7191 Mon Sep 17 00:00:00 2001 From: Arthur Carcano Date: Fri, 13 Dec 2024 12:32:35 +0100 Subject: [PATCH 11/14] Use a more precise span in placeholder_type_error_diag Closes: https://github.com/rust-lang/rust/issues/123861 --- compiler/rustc_hir_analysis/src/collect.rs | 7 +-- tests/crashes/123861.rs | 5 -- .../overlapping-errors-span-issue-123861.rs | 8 +++ ...verlapping-errors-span-issue-123861.stderr | 52 +++++++++++++++++++ 4 files changed, 64 insertions(+), 8 deletions(-) delete mode 100644 tests/crashes/123861.rs create mode 100644 tests/ui/generics/overlapping-errors-span-issue-123861.rs create mode 100644 tests/ui/generics/overlapping-errors-span-issue-123861.stderr diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 96d2714252af9..0bbf6aa5116e0 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -201,12 +201,13 @@ pub(crate) fn placeholder_type_error_diag<'cx, 'tcx>( placeholder_types.iter().map(|sp| (*sp, (*type_name).to_string())).collect(); if let Some(generics) = generics { - if let Some(arg) = params.iter().find(|arg| { - matches!(arg.name, hir::ParamName::Plain(Ident { name: kw::Underscore, .. })) + if let Some(span) = params.iter().find_map(|arg| match arg.name { + hir::ParamName::Plain(Ident { name: kw::Underscore, span }) => Some(span), + _ => None, }) { // Account for `_` already present in cases like `struct S<_>(_);` and suggest // `struct S(T);` instead of `struct S<_, T>(T);`. - sugg.push((arg.span, (*type_name).to_string())); + sugg.push((span, (*type_name).to_string())); } else if let Some(span) = generics.span_for_param_suggestion() { // Account for bounds, we want `fn foo(_: K)` not `fn foo(_: K)`. sugg.push((span, format!(", {type_name}"))); diff --git a/tests/crashes/123861.rs b/tests/crashes/123861.rs deleted file mode 100644 index 60245960af0d6..0000000000000 --- a/tests/crashes/123861.rs +++ /dev/null @@ -1,5 +0,0 @@ -//@ known-bug: #123861 -//@ needs-rustc-debug-assertions - -struct _; -fn mainIterator<_ = _> {} diff --git a/tests/ui/generics/overlapping-errors-span-issue-123861.rs b/tests/ui/generics/overlapping-errors-span-issue-123861.rs new file mode 100644 index 0000000000000..e0a27f6874874 --- /dev/null +++ b/tests/ui/generics/overlapping-errors-span-issue-123861.rs @@ -0,0 +1,8 @@ +fn mainIterator<_ = _> {} +//~^ ERROR expected identifier, found reserved identifier `_` +//~| ERROR missing parameters for function definition +//~| ERROR defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions [invalid_type_param_default] +//~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +//~| ERROR the placeholder `_` is not allowed within types on item signatures for functions [E0121] + +fn main() {} diff --git a/tests/ui/generics/overlapping-errors-span-issue-123861.stderr b/tests/ui/generics/overlapping-errors-span-issue-123861.stderr new file mode 100644 index 0000000000000..e0a49343b0e0d --- /dev/null +++ b/tests/ui/generics/overlapping-errors-span-issue-123861.stderr @@ -0,0 +1,52 @@ +error: expected identifier, found reserved identifier `_` + --> $DIR/overlapping-errors-span-issue-123861.rs:1:17 + | +LL | fn mainIterator<_ = _> {} + | ^ expected identifier, found reserved identifier + +error: missing parameters for function definition + --> $DIR/overlapping-errors-span-issue-123861.rs:1:23 + | +LL | fn mainIterator<_ = _> {} + | ^ + | +help: add a parameter list + | +LL | fn mainIterator<_ = _>() {} + | ++ + +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/overlapping-errors-span-issue-123861.rs:1:17 + | +LL | fn mainIterator<_ = _> {} + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 + = note: `#[deny(invalid_type_param_default)]` on by default + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/overlapping-errors-span-issue-123861.rs:1:21 + | +LL | fn mainIterator<_ = _> {} + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn mainIterator {} + | ~ ~ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0121`. +Future incompatibility report: Future breakage diagnostic: +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/overlapping-errors-span-issue-123861.rs:1:17 + | +LL | fn mainIterator<_ = _> {} + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 + = note: `#[deny(invalid_type_param_default)]` on by default + From 174dae607c40ca65f5589b22062775a95846f12d Mon Sep 17 00:00:00 2001 From: Adrian Taylor Date: Fri, 13 Dec 2024 15:40:37 +0000 Subject: [PATCH 12/14] Arbitrary self types v2: adjust diagnostic. The recently landed PR to adjust arbitrary self types was a bit overenthusiastic, advising folks to use the new Receiver trait even before it's been stabilized. Revert to the older wording of the lint in such cases. --- compiler/rustc_hir_analysis/messages.ftl | 6 ++++++ compiler/rustc_hir_analysis/src/check/wfcheck.rs | 8 +++++++- compiler/rustc_hir_analysis/src/errors.rs | 10 ++++++++++ .../async-await/inference_var_self_argument.stderr | 4 ++-- tests/ui/async-await/issue-66312.stderr | 4 ++-- .../feature-gate-dispatch-from-dyn-cell.stderr | 4 ++-- tests/ui/issues/issue-56806.stderr | 4 ++-- tests/ui/self/arbitrary-self-opaque.stderr | 4 ++-- tests/ui/span/issue-27522.stderr | 4 ++-- ...-incompatible-trait-should-use-where-sized.stderr | 4 ++-- tests/ui/traits/issue-78372.stderr | 4 ++-- tests/ui/ufcs/ufcs-explicit-self-bad.stderr | 12 ++++++------ 12 files changed, 45 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 25feb95d5dfeb..a2df0ba265c0e 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -246,6 +246,12 @@ hir_analysis_invalid_receiver_ty = invalid `self` parameter type: `{$receiver_ty hir_analysis_invalid_receiver_ty_help = consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` +hir_analysis_invalid_receiver_ty_help_no_arbitrary_self_types = + consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + +hir_analysis_invalid_receiver_ty_no_arbitrary_self_types = invalid `self` parameter type: `{$receiver_ty}` + .note = type of `self` must be `Self` or a type that dereferences to it + hir_analysis_invalid_union_field = field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union .note = union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 57264d0bd2afc..e6ef29de965a9 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1748,9 +1748,15 @@ fn check_method_receiver<'tcx>( // Report error; would not have worked with `arbitrary_self_types[_pointers]`. { match receiver_validity_err { - ReceiverValidityError::DoesNotDeref => { + ReceiverValidityError::DoesNotDeref if arbitrary_self_types_level.is_some() => { tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty }) } + ReceiverValidityError::DoesNotDeref => { + tcx.dcx().emit_err(errors::InvalidReceiverTyNoArbitrarySelfTypes { + span, + receiver_ty, + }) + } ReceiverValidityError::MethodGenericParamUsed => { tcx.dcx().emit_err(errors::InvalidGenericReceiverTy { span, receiver_ty }) } diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 7f62ccc91f09a..5ab6faf3b7cea 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1655,6 +1655,16 @@ pub(crate) struct NonConstRange { pub span: Span, } +#[derive(Diagnostic)] +#[diag(hir_analysis_invalid_receiver_ty_no_arbitrary_self_types, code = E0307)] +#[note] +#[help(hir_analysis_invalid_receiver_ty_help_no_arbitrary_self_types)] +pub(crate) struct InvalidReceiverTyNoArbitrarySelfTypes<'tcx> { + #[primary_span] + pub span: Span, + pub receiver_ty: Ty<'tcx>, +} + #[derive(Diagnostic)] #[diag(hir_analysis_invalid_receiver_ty, code = E0307)] #[note] diff --git a/tests/ui/async-await/inference_var_self_argument.stderr b/tests/ui/async-await/inference_var_self_argument.stderr index a33c5f7b07dca..7b7b3dbc757f1 100644 --- a/tests/ui/async-await/inference_var_self_argument.stderr +++ b/tests/ui/async-await/inference_var_self_argument.stderr @@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `&dyn Foo` LL | async fn foo(self: &dyn Foo) { | ^^^^^^^^ | - = note: type of `self` must be `Self` or some type implementing `Receiver` - = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) error[E0038]: the trait `Foo` cannot be made into an object --> $DIR/inference_var_self_argument.rs:5:5 diff --git a/tests/ui/async-await/issue-66312.stderr b/tests/ui/async-await/issue-66312.stderr index f4db949a5f430..c95ae1147df36 100644 --- a/tests/ui/async-await/issue-66312.stderr +++ b/tests/ui/async-await/issue-66312.stderr @@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `T` LL | fn is_some(self: T); | ^ | - = note: type of `self` must be `Self` or some type implementing `Receiver` - = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) error[E0308]: mismatched types --> $DIR/issue-66312.rs:9:8 diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr index eb9e51a04c394..2150effc3b74d 100644 --- a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr +++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr @@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `Cell<&Self>` LL | fn cell(self: Cell<&Self>); | ^^^^^^^^^^^ | - = note: type of `self` must be `Self` or some type implementing `Receiver` - = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-56806.stderr b/tests/ui/issues/issue-56806.stderr index 4b0a59fe12def..ec50d863758db 100644 --- a/tests/ui/issues/issue-56806.stderr +++ b/tests/ui/issues/issue-56806.stderr @@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `Box<(dyn Trait + 'static)>` LL | fn dyn_instead_of_self(self: Box); | ^^^^^^^^^^^^^^ | - = note: type of `self` must be `Self` or some type implementing `Receiver` - = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) error: aborting due to 1 previous error diff --git a/tests/ui/self/arbitrary-self-opaque.stderr b/tests/ui/self/arbitrary-self-opaque.stderr index 0469aca27dc81..c75165d9f8e27 100644 --- a/tests/ui/self/arbitrary-self-opaque.stderr +++ b/tests/ui/self/arbitrary-self-opaque.stderr @@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `Bar` LL | fn foo(self: Bar) {} | ^^^ | - = note: type of `self` must be `Self` or some type implementing `Receiver` - = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) error: item does not constrain `Bar::{opaque#0}`, but has it in its signature --> $DIR/arbitrary-self-opaque.rs:7:8 diff --git a/tests/ui/span/issue-27522.stderr b/tests/ui/span/issue-27522.stderr index 04904b0ddc1c5..c57a100bbe227 100644 --- a/tests/ui/span/issue-27522.stderr +++ b/tests/ui/span/issue-27522.stderr @@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `&SomeType` LL | fn handler(self: &SomeType); | ^^^^^^^^^ | - = note: type of `self` must be `Self` or some type implementing `Receiver` - = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr index eb9f9196a7234..beafd7c2ab00f 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr @@ -32,8 +32,8 @@ error[E0307]: invalid `self` parameter type: `()` LL | fn bar(self: ()) {} | ^^ | - = note: type of `self` must be `Self` or some type implementing `Receiver` - = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) error: aborting due to 2 previous errors diff --git a/tests/ui/traits/issue-78372.stderr b/tests/ui/traits/issue-78372.stderr index 1c58915111f2c..86234d15a5d4b 100644 --- a/tests/ui/traits/issue-78372.stderr +++ b/tests/ui/traits/issue-78372.stderr @@ -61,8 +61,8 @@ error[E0307]: invalid `self` parameter type: `Smaht` LL | fn foo(self: Smaht); | ^^^^^^^^^^^^^^ | - = note: type of `self` must be `Self` or some type implementing `Receiver` - = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures --> $DIR/issue-78372.rs:3:1 diff --git a/tests/ui/ufcs/ufcs-explicit-self-bad.stderr b/tests/ui/ufcs/ufcs-explicit-self-bad.stderr index 36bdc714e050b..2a8c4edbdb5f3 100644 --- a/tests/ui/ufcs/ufcs-explicit-self-bad.stderr +++ b/tests/ui/ufcs/ufcs-explicit-self-bad.stderr @@ -22,8 +22,8 @@ error[E0307]: invalid `self` parameter type: `isize` LL | fn foo(self: isize, x: isize) -> isize { | ^^^^^ | - = note: type of `self` must be `Self` or some type implementing `Receiver` - = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) error[E0307]: invalid `self` parameter type: `Bar` --> $DIR/ufcs-explicit-self-bad.rs:19:18 @@ -31,8 +31,8 @@ error[E0307]: invalid `self` parameter type: `Bar` LL | fn foo(self: Bar, x: isize) -> isize { | ^^^^^^^^^^ | - = note: type of `self` must be `Self` or some type implementing `Receiver` - = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) error[E0307]: invalid `self` parameter type: `&Bar` --> $DIR/ufcs-explicit-self-bad.rs:23:18 @@ -40,8 +40,8 @@ error[E0307]: invalid `self` parameter type: `&Bar` LL | fn bar(self: &Bar, x: isize) -> isize { | ^^^^^^^^^^^ | - = note: type of `self` must be `Self` or some type implementing `Receiver` - = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) error[E0308]: mismatched `self` parameter type --> $DIR/ufcs-explicit-self-bad.rs:37:21 From 98318c5e66d5a56d8741186a876a84ffe33ea814 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 13 Dec 2024 09:08:44 -0700 Subject: [PATCH 13/14] rustdoc-search: update test with now-shorter function path Both paths are correct. This one's better. --- tests/rustdoc-js-std/osstring-to-string.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/rustdoc-js-std/osstring-to-string.js b/tests/rustdoc-js-std/osstring-to-string.js index 3fdc0b9f24a3c..17bb602a502af 100644 --- a/tests/rustdoc-js-std/osstring-to-string.js +++ b/tests/rustdoc-js-std/osstring-to-string.js @@ -4,6 +4,6 @@ const EXPECTED = { 'query': 'OsString -> String', 'others': [ - { 'path': 'std::ffi::os_str::OsString', 'name': 'into_string' }, + { 'path': 'std::ffi::OsString', 'name': 'into_string' }, ] }; From efb66e7e385da37015925b23c199efdf3b246d35 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 13 Dec 2024 16:18:37 +0000 Subject: [PATCH 14/14] Rename ty_def_id so people will stop using it by accident --- .../rustc_hir_analysis/src/hir_ty_lowering/errors.rs | 5 ++--- compiler/rustc_middle/src/query/keys.rs | 11 ++++++----- compiler/rustc_middle/src/values.rs | 6 +++--- compiler/rustc_query_impl/src/plumbing.rs | 4 ++-- compiler/rustc_query_system/src/query/mod.rs | 6 +++--- .../src/methods/unnecessary_filter_map.rs | 4 +--- 6 files changed, 17 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 2e227ead14a93..6e10450313cb4 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -9,7 +9,6 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_middle::bug; -use rustc_middle::query::Key; use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _}; use rustc_middle::ty::{ self, AdtDef, Binder, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeVisitableExt, @@ -1007,8 +1006,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { )), .. }) = node - && let Some(ty_def_id) = qself_ty.ty_def_id() - && let [inherent_impl] = tcx.inherent_impls(ty_def_id) + && let Some(adt_def) = qself_ty.ty_adt_def() + && let [inherent_impl] = tcx.inherent_impls(adt_def.did()) && let name = format!("{ident2}_{ident3}") && let Some(ty::AssocItem { kind: ty::AssocKind::Fn, .. }) = tcx .associated_items(inherent_impl) diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index 970dc72e1ff61..66fec2dd0f7e8 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -41,7 +41,8 @@ pub trait Key: Sized { None } - fn ty_def_id(&self) -> Option { + /// Used to detect when ADT def ids are used as keys in a cycle for better error reporting. + fn def_id_for_ty_in_cycle(&self) -> Option { None } } @@ -423,7 +424,7 @@ impl<'tcx> Key for Ty<'tcx> { DUMMY_SP } - fn ty_def_id(&self) -> Option { + fn def_id_for_ty_in_cycle(&self) -> Option { match *self.kind() { ty::Adt(adt, _) => Some(adt.did()), ty::Coroutine(def_id, ..) => Some(def_id), @@ -471,8 +472,8 @@ impl<'tcx, T: Key> Key for ty::PseudoCanonicalInput<'tcx, T> { self.value.default_span(tcx) } - fn ty_def_id(&self) -> Option { - self.value.ty_def_id() + fn def_id_for_ty_in_cycle(&self) -> Option { + self.value.def_id_for_ty_in_cycle() } } @@ -593,7 +594,7 @@ impl<'tcx> Key for (ValidityRequirement, ty::PseudoCanonicalInput<'tcx, Ty<'tcx> DUMMY_SP } - fn ty_def_id(&self) -> Option { + fn def_id_for_ty_in_cycle(&self) -> Option { match self.1.value.kind() { ty::Adt(adt, _) => Some(adt.did()), _ => None, diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs index 48d744a9ef6cd..390909bb0ab0c 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -100,7 +100,7 @@ impl<'tcx> Value> for Representability { } for info in &cycle_error.cycle { if info.query.dep_kind == dep_kinds::representability_adt_ty - && let Some(def_id) = info.query.ty_def_id + && let Some(def_id) = info.query.def_id_for_ty_in_cycle && let Some(def_id) = def_id.as_local() && !item_and_field_ids.iter().any(|&(id, _)| id == def_id) { @@ -182,7 +182,7 @@ impl<'tcx, T> Value> for Result> &cycle_error.cycle, |cycle| { if cycle[0].query.dep_kind == dep_kinds::layout_of - && let Some(def_id) = cycle[0].query.ty_def_id + && let Some(def_id) = cycle[0].query.def_id_for_ty_in_cycle && let Some(def_id) = def_id.as_local() && let def_kind = tcx.def_kind(def_id) && matches!(def_kind, DefKind::Closure) @@ -209,7 +209,7 @@ impl<'tcx, T> Value> for Result> if frame.query.dep_kind != dep_kinds::layout_of { continue; } - let Some(frame_def_id) = frame.query.ty_def_id else { + let Some(frame_def_id) = frame.query.def_id_for_ty_in_cycle else { continue; }; let Some(frame_coroutine_kind) = tcx.coroutine_kind(frame_def_id) else { diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index f72f656b2f8f9..1b12af62ea5a9 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -349,9 +349,9 @@ pub(crate) fn create_query_frame< hasher.finish::() }) }; - let ty_def_id = key.ty_def_id(); + let def_id_for_ty_in_cycle = key.def_id_for_ty_in_cycle(); - QueryStackFrame::new(description, span, def_id, def_kind, kind, ty_def_id, hash) + QueryStackFrame::new(description, span, def_id, def_kind, kind, def_id_for_ty_in_cycle, hash) } pub(crate) fn encode_query_results<'a, 'tcx, Q>( diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index b81386f06ec7a..82c51193a19d3 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -33,7 +33,7 @@ pub struct QueryStackFrame { pub def_id: Option, pub def_kind: Option, /// A def-id that is extracted from a `Ty` in a query key - pub ty_def_id: Option, + pub def_id_for_ty_in_cycle: Option, pub dep_kind: DepKind, /// This hash is used to deterministically pick /// a query to remove cycles in the parallel compiler. @@ -48,10 +48,10 @@ impl QueryStackFrame { def_id: Option, def_kind: Option, dep_kind: DepKind, - ty_def_id: Option, + def_id_for_ty_in_cycle: Option, hash: impl FnOnce() -> Hash64, ) -> Self { - Self { description, span, def_id, def_kind, ty_def_id, dep_kind, hash: hash() } + Self { description, span, def_id, def_kind, def_id_for_ty_in_cycle, dep_kind, hash: hash() } } // FIXME(eddyb) Get more valid `Span`s on queries. diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs index 3de51bc661eb7..5b9e9e70e4770 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs @@ -3,13 +3,12 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::ty::is_copy; use clippy_utils::usage::mutated_variables; use clippy_utils::visitors::{Descend, for_each_expr_without_closures}; -use clippy_utils::{MaybePath, is_res_lang_ctor, is_trait_method, path_res, path_to_local_id}; +use clippy_utils::{is_res_lang_ctor, is_trait_method, path_res, path_to_local_id}; use core::ops::ControlFlow; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::LangItem::{OptionNone, OptionSome}; use rustc_lint::LateContext; -use rustc_middle::query::Key; use rustc_middle::ty; use rustc_span::sym; @@ -44,7 +43,6 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>, a if name == "filter_map" && let hir::ExprKind::Call(expr, args) = body.value.kind && is_res_lang_ctor(cx, path_res(cx, expr), OptionSome) - && arg_id.ty_def_id() == args[0].hir_id().ty_def_id() && let hir::ExprKind::Path(_) = args[0].kind { span_lint_and_sugg(