From 7a3a98d8949dcfd98c9509b0869b6bca00bf5017 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Wed, 2 Oct 2024 19:57:59 +0200 Subject: [PATCH 01/15] Fix target_vendor in QNX Neutrino targets The `x86_64-pc-nto-qnx710` and `i586-pc-nto-qnx700` targets have `pc` in their target triple names, but the vendor was set to the default `"unknown"`. --- compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs | 1 + compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs b/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs index 2519b935c03a7..7648f81fd4d9a 100644 --- a/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs +++ b/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs @@ -21,6 +21,7 @@ pub(crate) fn target() -> Target { "-Vgcc_ntox86_cxx", ]), env: "nto70".into(), + vendor: "pc".into(), stack_probes: StackProbeType::Inline, ..base::nto_qnx::opts() }, diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs index 1aa82494a499e..245a5f0676547 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs @@ -21,6 +21,7 @@ pub(crate) fn target() -> Target { "-Vgcc_ntox86_64_cxx", ]), env: "nto71".into(), + vendor: "pc".into(), ..base::nto_qnx::opts() }, } From b89751b8f42d9c627ea65a0c2ea2d6f89eb9b461 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Fri, 18 Oct 2024 16:06:57 +0200 Subject: [PATCH 02/15] clean up `*dyn` casts (with principals) - remove a redundant check, because we always emit the "better diagnostic" now - clean up the comments a bit --- compiler/rustc_hir_typeck/src/cast.rs | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 8fa6ab8503d08..7341d3fa3c4e2 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -876,20 +876,14 @@ impl<'a, 'tcx> CastCheck<'tcx> { // A + SrcAuto> -> B + DstAuto>. need to make sure // - `Src` and `Dst` traits are the same // - traits have the same generic arguments - // - `SrcAuto` is a superset of `DstAuto` - (Some(src_principal), Some(dst_principal)) => { + // - projections are the same + // - `SrcAuto` (+auto traits implied by `Src`) is a superset of `DstAuto` + // + // Note that trait upcasting goes through a different mechanism (`coerce_unsized`) + // and is unaffected by this check. + (Some(src_principal), Some(_)) => { let tcx = fcx.tcx; - // Check that the traits are actually the same. - // The `dyn Src = dyn Dst` check below would suffice, - // but this may produce a better diagnostic. - // - // Note that trait upcasting goes through a different mechanism (`coerce_unsized`) - // and is unaffected by this check. - if src_principal.def_id() != dst_principal.def_id() { - return Err(CastError::DifferingKinds { src_kind, dst_kind }); - } - // We need to reconstruct trait object types. // `m_src` and `m_dst` won't work for us here because they will potentially // contain wrappers, which we do not care about. @@ -912,8 +906,8 @@ impl<'a, 'tcx> CastCheck<'tcx> { ty::Dyn, )); - // `dyn Src = dyn Dst`, this checks for matching traits/generics - // This is `demand_eqtype`, but inlined to give a better error. + // `dyn Src = dyn Dst`, this checks for matching traits/generics/projections + // This is `fcx.demand_eqtype`, but inlined to give a better error. let cause = fcx.misc(self.span); if fcx .at(&cause, fcx.param_env) From ab4222ad97808dc00ee0476dcbffba3ea584e0aa Mon Sep 17 00:00:00 2001 From: clubby789 Date: Fri, 18 Oct 2024 22:05:31 +0000 Subject: [PATCH 03/15] Prevent overflowing enum cast from ICEing --- compiler/rustc_mir_build/src/thir/cx/expr.rs | 9 ++++- tests/ui/error-codes/E0081.rs | 42 ++++++++++++++++++++ tests/ui/error-codes/E0081.stderr | 28 ++++++++++++- 3 files changed, 76 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 5995d60e7e073..50ad533870760 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -281,7 +281,14 @@ impl<'tcx> Cx<'tcx> { .unwrap_or_else(|e| panic!("could not compute layout for {param_env_ty:?}: {e:?}")) .size; - let lit = ScalarInt::try_from_uint(discr_offset as u128, size).unwrap(); + let (lit, overflowing) = ScalarInt::truncate_from_uint(discr_offset as u128, size); + if overflowing { + // An erroneous enum with too many variants for its repr will emit E0081 and E0370 + self.tcx.dcx().span_delayed_bug( + source.span, + "overflowing enum wasn't rejected by hir analysis", + ); + } let kind = ExprKind::NonHirLiteral { lit, user_ty: None }; let offset = self.thir.exprs.push(Expr { temp_lifetime, ty: discr_ty, span, kind }); diff --git a/tests/ui/error-codes/E0081.rs b/tests/ui/error-codes/E0081.rs index f53fda864d655..8fdb27c36e35e 100644 --- a/tests/ui/error-codes/E0081.rs +++ b/tests/ui/error-codes/E0081.rs @@ -50,5 +50,47 @@ enum MultipleDuplicates { //~^ NOTE `-2` assigned here } +// Test for #131902 +// Ensure that casting an enum with too many variants for its repr +// does not ICE +#[repr(u8)] +enum TooManyVariants { + //~^ ERROR discriminant value `0` assigned more than once + X000, X001, X002, X003, X004, X005, X006, X007, X008, X009, + //~^ NOTE `0` assigned here + //~| NOTE discriminant for `X256` incremented from this startpoint + X010, X011, X012, X013, X014, X015, X016, X017, X018, X019, + X020, X021, X022, X023, X024, X025, X026, X027, X028, X029, + X030, X031, X032, X033, X034, X035, X036, X037, X038, X039, + X040, X041, X042, X043, X044, X045, X046, X047, X048, X049, + X050, X051, X052, X053, X054, X055, X056, X057, X058, X059, + X060, X061, X062, X063, X064, X065, X066, X067, X068, X069, + X070, X071, X072, X073, X074, X075, X076, X077, X078, X079, + X080, X081, X082, X083, X084, X085, X086, X087, X088, X089, + X090, X091, X092, X093, X094, X095, X096, X097, X098, X099, + X100, X101, X102, X103, X104, X105, X106, X107, X108, X109, + X110, X111, X112, X113, X114, X115, X116, X117, X118, X119, + X120, X121, X122, X123, X124, X125, X126, X127, X128, X129, + X130, X131, X132, X133, X134, X135, X136, X137, X138, X139, + X140, X141, X142, X143, X144, X145, X146, X147, X148, X149, + X150, X151, X152, X153, X154, X155, X156, X157, X158, X159, + X160, X161, X162, X163, X164, X165, X166, X167, X168, X169, + X170, X171, X172, X173, X174, X175, X176, X177, X178, X179, + X180, X181, X182, X183, X184, X185, X186, X187, X188, X189, + X190, X191, X192, X193, X194, X195, X196, X197, X198, X199, + X200, X201, X202, X203, X204, X205, X206, X207, X208, X209, + X210, X211, X212, X213, X214, X215, X216, X217, X218, X219, + X220, X221, X222, X223, X224, X225, X226, X227, X228, X229, + X230, X231, X232, X233, X234, X235, X236, X237, X238, X239, + X240, X241, X242, X243, X244, X245, X246, X247, X248, X249, + X250, X251, X252, X253, X254, X255, + X256, + //~^ ERROR enum discriminant overflowed + //~| NOTE overflowed on value after 255 + //~| NOTE explicitly set `X256 = 0` + //~| NOTE `0` assigned here +} + fn main() { + TooManyVariants::X256 as u8; } diff --git a/tests/ui/error-codes/E0081.stderr b/tests/ui/error-codes/E0081.stderr index d4b21f6893b43..91445eedf4da9 100644 --- a/tests/ui/error-codes/E0081.stderr +++ b/tests/ui/error-codes/E0081.stderr @@ -73,6 +73,30 @@ LL | LL | V9, | -- `-2` assigned here -error: aborting due to 5 previous errors +error[E0370]: enum discriminant overflowed + --> $DIR/E0081.rs:87:5 + | +LL | X256, + | ^^^^ overflowed on value after 255 + | + = note: explicitly set `X256 = 0` if that is desired outcome + +error[E0081]: discriminant value `0` assigned more than once + --> $DIR/E0081.rs:57:1 + | +LL | enum TooManyVariants { + | ^^^^^^^^^^^^^^^^^^^^ +LL | +LL | X000, X001, X002, X003, X004, X005, X006, X007, X008, X009, + | ---- + | | + | `0` assigned here + | discriminant for `X256` incremented from this startpoint (`X000` + 256 variants later => `X256` = 0) +... +LL | X256, + | ---- `0` assigned here + +error: aborting due to 7 previous errors -For more information about this error, try `rustc --explain E0081`. +Some errors have detailed explanations: E0081, E0370. +For more information about an error, try `rustc --explain E0081`. From 98c4d9695718b309fe790f7b2da2e886ccd042c6 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 19 Oct 2024 21:47:42 +1100 Subject: [PATCH 04/15] Reduce visibility of coverage FFI functions/types --- .../src/coverageinfo/ffi.rs | 20 +++++++++---------- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 16 +++++++-------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs index 90f7dd733ca18..2a35b4adbcda1 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs @@ -5,7 +5,7 @@ use rustc_middle::mir::coverage::{ /// Must match the layout of `LLVMRustCounterKind`. #[derive(Copy, Clone, Debug)] #[repr(C)] -pub enum CounterKind { +pub(crate) enum CounterKind { Zero = 0, CounterValueReference = 1, Expression = 2, @@ -25,9 +25,9 @@ pub enum CounterKind { /// Must match the layout of `LLVMRustCounter`. #[derive(Copy, Clone, Debug)] #[repr(C)] -pub struct Counter { +pub(crate) struct Counter { // Important: The layout (order and types of fields) must match its C++ counterpart. - pub kind: CounterKind, + pub(crate) kind: CounterKind, id: u32, } @@ -36,7 +36,7 @@ impl Counter { pub(crate) const ZERO: Self = Self { kind: CounterKind::Zero, id: 0 }; /// Constructs a new `Counter` of kind `CounterValueReference`. - pub fn counter_value_reference(counter_id: CounterId) -> Self { + pub(crate) fn counter_value_reference(counter_id: CounterId) -> Self { Self { kind: CounterKind::CounterValueReference, id: counter_id.as_u32() } } @@ -59,7 +59,7 @@ impl Counter { /// Must match the layout of `LLVMRustCounterExprKind`. #[derive(Copy, Clone, Debug)] #[repr(C)] -pub enum ExprKind { +pub(crate) enum ExprKind { Subtract = 0, Add = 1, } @@ -69,10 +69,10 @@ pub enum ExprKind { /// Must match the layout of `LLVMRustCounterExpression`. #[derive(Copy, Clone, Debug)] #[repr(C)] -pub struct CounterExpression { - pub kind: ExprKind, - pub lhs: Counter, - pub rhs: Counter, +pub(crate) struct CounterExpression { + pub(crate) kind: ExprKind, + pub(crate) lhs: Counter, + pub(crate) rhs: Counter, } /// Corresponds to enum `llvm::coverage::CounterMappingRegion::RegionKind`. @@ -199,7 +199,7 @@ mod mcdc { /// Must match the layout of `LLVMRustCounterMappingRegion`. #[derive(Copy, Clone, Debug)] #[repr(C)] -pub struct CounterMappingRegion { +pub(crate) struct CounterMappingRegion { /// The counter type and type-dependent counter data, if any. counter: Counter, diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 661debbb9f126..c41961fb39465 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1740,7 +1740,7 @@ unsafe extern "C" { ) -> bool; #[allow(improper_ctypes)] - pub fn LLVMRustCoverageWriteFilenamesSectionToBuffer( + pub(crate) fn LLVMRustCoverageWriteFilenamesSectionToBuffer( Filenames: *const *const c_char, FilenamesLen: size_t, Lengths: *const size_t, @@ -1749,7 +1749,7 @@ unsafe extern "C" { ); #[allow(improper_ctypes)] - pub fn LLVMRustCoverageWriteMappingToBuffer( + pub(crate) fn LLVMRustCoverageWriteMappingToBuffer( VirtualFileMappingIDs: *const c_uint, NumVirtualFileMappingIDs: c_uint, Expressions: *const crate::coverageinfo::ffi::CounterExpression, @@ -1759,23 +1759,23 @@ unsafe extern "C" { BufferOut: &RustString, ); - pub fn LLVMRustCoverageCreatePGOFuncNameVar( + pub(crate) fn LLVMRustCoverageCreatePGOFuncNameVar( F: &Value, FuncName: *const c_char, FuncNameLen: size_t, ) -> &Value; - pub fn LLVMRustCoverageHashByteArray(Bytes: *const c_char, NumBytes: size_t) -> u64; + pub(crate) fn LLVMRustCoverageHashByteArray(Bytes: *const c_char, NumBytes: size_t) -> u64; #[allow(improper_ctypes)] - pub fn LLVMRustCoverageWriteMapSectionNameToString(M: &Module, Str: &RustString); + pub(crate) fn LLVMRustCoverageWriteMapSectionNameToString(M: &Module, Str: &RustString); #[allow(improper_ctypes)] - pub fn LLVMRustCoverageWriteFuncSectionNameToString(M: &Module, Str: &RustString); + pub(crate) fn LLVMRustCoverageWriteFuncSectionNameToString(M: &Module, Str: &RustString); #[allow(improper_ctypes)] - pub fn LLVMRustCoverageWriteMappingVarNameToString(Str: &RustString); + pub(crate) fn LLVMRustCoverageWriteMappingVarNameToString(Str: &RustString); - pub fn LLVMRustCoverageMappingVersion() -> u32; + pub(crate) fn LLVMRustCoverageMappingVersion() -> u32; pub fn LLVMRustDebugMetadataVersion() -> u32; pub fn LLVMRustVersionMajor() -> u32; pub fn LLVMRustVersionMinor() -> u32; From d1bf77eb3404bf1e46f4c81eebf6cc83508b0de7 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 19 Oct 2024 22:22:43 +1100 Subject: [PATCH 05/15] Pass coverage mappings to LLVM as separate structs --- .../src/coverageinfo/ffi.rs | 372 +++--------------- .../src/coverageinfo/mapgen.rs | 48 ++- .../src/coverageinfo/mod.rs | 18 +- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 10 +- .../llvm-wrapper/CoverageMappingWrapper.cpp | 182 ++++----- 5 files changed, 203 insertions(+), 427 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs index 2a35b4adbcda1..feac97f3e2b62 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs @@ -1,6 +1,4 @@ -use rustc_middle::mir::coverage::{ - ConditionInfo, CounterId, CovTerm, DecisionInfo, ExpressionId, MappingKind, SourceRegion, -}; +use rustc_middle::mir::coverage::{CounterId, CovTerm, ExpressionId, SourceRegion}; /// Must match the layout of `LLVMRustCounterKind`. #[derive(Copy, Clone, Debug)] @@ -75,42 +73,7 @@ pub(crate) struct CounterExpression { pub(crate) rhs: Counter, } -/// Corresponds to enum `llvm::coverage::CounterMappingRegion::RegionKind`. -/// -/// Must match the layout of `LLVMRustCounterMappingRegionKind`. -#[derive(Copy, Clone, Debug)] -#[repr(C)] -enum RegionKind { - /// A CodeRegion associates some code with a counter - CodeRegion = 0, - - /// An ExpansionRegion represents a file expansion region that associates - /// a source range with the expansion of a virtual source file, such as - /// for a macro instantiation or #include file. - ExpansionRegion = 1, - - /// A SkippedRegion represents a source range with code that was skipped - /// by a preprocessor or similar means. - SkippedRegion = 2, - - /// A GapRegion is like a CodeRegion, but its count is only set as the - /// line execution count when its the only region in the line. - GapRegion = 3, - - /// A BranchRegion represents leaf-level boolean expressions and is - /// associated with two counters, each representing the number of times the - /// expression evaluates to true or false. - BranchRegion = 4, - - /// A DecisionRegion represents a top-level boolean expression and is - /// associated with a variable length bitmap index and condition number. - MCDCDecisionRegion = 5, - - /// A Branch Region can be extended to include IDs to facilitate MC/DC. - MCDCBranchRegion = 6, -} - -mod mcdc { +pub(crate) mod mcdc { use rustc_middle::mir::coverage::{ConditionId, ConditionInfo, DecisionInfo}; /// Must match the layout of `LLVMRustMCDCDecisionParameters`. @@ -121,8 +84,6 @@ mod mcdc { num_conditions: u16, } - // ConditionId in llvm is `unsigned int` at 18 while `int16_t` at - // [19](https://github.com/llvm/llvm-project/pull/81257). type LLVMConditionId = i16; /// Must match the layout of `LLVMRustMCDCBranchParameters`. @@ -133,38 +94,6 @@ mod mcdc { condition_ids: [LLVMConditionId; 2], } - #[repr(C)] - #[derive(Clone, Copy, Debug)] - enum ParameterTag { - None = 0, - Decision = 1, - Branch = 2, - } - /// Same layout with `LLVMRustMCDCParameters` - #[repr(C)] - #[derive(Clone, Copy, Debug)] - pub(crate) struct Parameters { - tag: ParameterTag, - decision_params: DecisionParameters, - branch_params: BranchParameters, - } - - impl Parameters { - pub(crate) fn none() -> Self { - Self { - tag: ParameterTag::None, - decision_params: Default::default(), - branch_params: Default::default(), - } - } - pub(crate) fn decision(decision_params: DecisionParameters) -> Self { - Self { tag: ParameterTag::Decision, decision_params, branch_params: Default::default() } - } - pub(crate) fn branch(branch_params: BranchParameters) -> Self { - Self { tag: ParameterTag::Branch, decision_params: Default::default(), branch_params } - } - } - impl From for BranchParameters { fn from(value: ConditionInfo) -> Self { let to_llvm_cond_id = |cond_id: Option| { @@ -186,267 +115,68 @@ mod mcdc { } } -/// This struct provides LLVM's representation of a "CoverageMappingRegion", encoded into the -/// coverage map, in accordance with the -/// [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format). -/// The struct composes fields representing the `Counter` type and value(s) (injected counter -/// ID, or expression type and operands), the source file (an indirect index into a "filenames -/// array", encoded separately), and source location (start and end positions of the represented -/// code region). +/// A span of source code coordinates to be embedded in coverage metadata. /// -/// Corresponds to struct `llvm::coverage::CounterMappingRegion`. -/// -/// Must match the layout of `LLVMRustCounterMappingRegion`. -#[derive(Copy, Clone, Debug)] +/// Must match the layout of `LLVMRustCoverageSpan`. +#[derive(Clone, Debug)] #[repr(C)] -pub(crate) struct CounterMappingRegion { - /// The counter type and type-dependent counter data, if any. - counter: Counter, - - /// If the `RegionKind` is a `BranchRegion`, this represents the counter - /// for the false branch of the region. - false_counter: Counter, - - mcdc_params: mcdc::Parameters, - /// An indirect reference to the source filename. In the LLVM Coverage Mapping Format, the - /// file_id is an index into a function-specific `virtual_file_mapping` array of indexes - /// that, in turn, are used to look up the filename for this region. +pub(crate) struct CoverageSpan { + /// Local index into the function's local-to-global file ID table. + /// The value at that index is itself an index into the coverage filename + /// table in the CGU's `__llvm_covmap` section. file_id: u32, - /// If the `RegionKind` is an `ExpansionRegion`, the `expanded_file_id` can be used to find - /// the mapping regions created as a result of macro expansion, by checking if their file id - /// matches the expanded file id. - expanded_file_id: u32, - - /// 1-based starting line of the mapping region. + /// 1-based starting line of the source code span. start_line: u32, - - /// 1-based starting column of the mapping region. + /// 1-based starting column of the source code span. start_col: u32, - - /// 1-based ending line of the mapping region. + /// 1-based ending line of the source code span. end_line: u32, - - /// 1-based ending column of the mapping region. If the high bit is set, the current - /// mapping region is a gap area. + /// 1-based ending column of the source code span. High bit must be unset. end_col: u32, - - kind: RegionKind, } -impl CounterMappingRegion { - pub(crate) fn from_mapping( - mapping_kind: &MappingKind, - local_file_id: u32, - source_region: &SourceRegion, - ) -> Self { - let &SourceRegion { file_name: _, start_line, start_col, end_line, end_col } = - source_region; - match *mapping_kind { - MappingKind::Code(term) => Self::code_region( - Counter::from_term(term), - local_file_id, - start_line, - start_col, - end_line, - end_col, - ), - MappingKind::Branch { true_term, false_term } => Self::branch_region( - Counter::from_term(true_term), - Counter::from_term(false_term), - local_file_id, - start_line, - start_col, - end_line, - end_col, - ), - MappingKind::MCDCBranch { true_term, false_term, mcdc_params } => { - Self::mcdc_branch_region( - Counter::from_term(true_term), - Counter::from_term(false_term), - mcdc_params, - local_file_id, - start_line, - start_col, - end_line, - end_col, - ) - } - MappingKind::MCDCDecision(decision_info) => Self::decision_region( - decision_info, - local_file_id, - start_line, - start_col, - end_line, - end_col, - ), - } - } - - pub(crate) fn code_region( - counter: Counter, - file_id: u32, - start_line: u32, - start_col: u32, - end_line: u32, - end_col: u32, - ) -> Self { - Self { - counter, - false_counter: Counter::ZERO, - mcdc_params: mcdc::Parameters::none(), - file_id, - expanded_file_id: 0, - start_line, - start_col, - end_line, - end_col, - kind: RegionKind::CodeRegion, - } +impl CoverageSpan { + pub(crate) fn from_source_region(file_id: u32, code_region: &SourceRegion) -> Self { + let &SourceRegion { file_name: _, start_line, start_col, end_line, end_col } = code_region; + // Internally, LLVM uses the high bit of `end_col` to distinguish between + // code regions and gap regions, so it can't be used by the column number. + assert!(end_col & (1u32 << 31) == 0, "high bit of `end_col` must be unset: {end_col:#X}"); + Self { file_id, start_line, start_col, end_line, end_col } } +} - pub(crate) fn branch_region( - counter: Counter, - false_counter: Counter, - file_id: u32, - start_line: u32, - start_col: u32, - end_line: u32, - end_col: u32, - ) -> Self { - Self { - counter, - false_counter, - mcdc_params: mcdc::Parameters::none(), - file_id, - expanded_file_id: 0, - start_line, - start_col, - end_line, - end_col, - kind: RegionKind::BranchRegion, - } - } - - pub(crate) fn mcdc_branch_region( - counter: Counter, - false_counter: Counter, - condition_info: ConditionInfo, - file_id: u32, - start_line: u32, - start_col: u32, - end_line: u32, - end_col: u32, - ) -> Self { - Self { - counter, - false_counter, - mcdc_params: mcdc::Parameters::branch(condition_info.into()), - file_id, - expanded_file_id: 0, - start_line, - start_col, - end_line, - end_col, - kind: RegionKind::MCDCBranchRegion, - } - } - - pub(crate) fn decision_region( - decision_info: DecisionInfo, - file_id: u32, - start_line: u32, - start_col: u32, - end_line: u32, - end_col: u32, - ) -> Self { - let mcdc_params = mcdc::Parameters::decision(decision_info.into()); - - Self { - counter: Counter::ZERO, - false_counter: Counter::ZERO, - mcdc_params, - file_id, - expanded_file_id: 0, - start_line, - start_col, - end_line, - end_col, - kind: RegionKind::MCDCDecisionRegion, - } - } +/// Must match the layout of `LLVMRustCoverageCodeRegion`. +#[derive(Clone, Debug)] +#[repr(C)] +pub(crate) struct CodeRegion { + pub(crate) span: CoverageSpan, + pub(crate) counter: Counter, +} - // This function might be used in the future; the LLVM API is still evolving, as is coverage - // support. - #[allow(dead_code)] - pub(crate) fn expansion_region( - file_id: u32, - expanded_file_id: u32, - start_line: u32, - start_col: u32, - end_line: u32, - end_col: u32, - ) -> Self { - Self { - counter: Counter::ZERO, - false_counter: Counter::ZERO, - mcdc_params: mcdc::Parameters::none(), - file_id, - expanded_file_id, - start_line, - start_col, - end_line, - end_col, - kind: RegionKind::ExpansionRegion, - } - } +/// Must match the layout of `LLVMRustCoverageBranchRegion`. +#[derive(Clone, Debug)] +#[repr(C)] +pub(crate) struct BranchRegion { + pub(crate) span: CoverageSpan, + pub(crate) true_counter: Counter, + pub(crate) false_counter: Counter, +} - // This function might be used in the future; the LLVM API is still evolving, as is coverage - // support. - #[allow(dead_code)] - pub(crate) fn skipped_region( - file_id: u32, - start_line: u32, - start_col: u32, - end_line: u32, - end_col: u32, - ) -> Self { - Self { - counter: Counter::ZERO, - false_counter: Counter::ZERO, - mcdc_params: mcdc::Parameters::none(), - file_id, - expanded_file_id: 0, - start_line, - start_col, - end_line, - end_col, - kind: RegionKind::SkippedRegion, - } - } +/// Must match the layout of `LLVMRustCoverageMCDCBranchRegion`. +#[derive(Clone, Debug)] +#[repr(C)] +pub(crate) struct MCDCBranchRegion { + pub(crate) span: CoverageSpan, + pub(crate) true_counter: Counter, + pub(crate) false_counter: Counter, + pub(crate) mcdc_branch_params: mcdc::BranchParameters, +} - // This function might be used in the future; the LLVM API is still evolving, as is coverage - // support. - #[allow(dead_code)] - pub(crate) fn gap_region( - counter: Counter, - file_id: u32, - start_line: u32, - start_col: u32, - end_line: u32, - end_col: u32, - ) -> Self { - Self { - counter, - false_counter: Counter::ZERO, - mcdc_params: mcdc::Parameters::none(), - file_id, - expanded_file_id: 0, - start_line, - start_col, - end_line, - end_col: (1_u32 << 31) | end_col, - kind: RegionKind::GapRegion, - } - } +/// Must match the layout of `LLVMRustCoverageMCDCDecisionRegion`. +#[derive(Clone, Debug)] +#[repr(C)] +pub(crate) struct MCDCDecisionRegion { + pub(crate) span: CoverageSpan, + pub(crate) mcdc_decision_params: mcdc::DecisionParameters, } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index c2c261da79b68..cc366ba4b2c2c 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -3,6 +3,7 @@ use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, ConstCodegenMethods}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_index::IndexVec; +use rustc_middle::mir::coverage::MappingKind; use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::{bug, mir}; use rustc_span::Symbol; @@ -10,7 +11,7 @@ use rustc_span::def_id::DefIdSet; use tracing::debug; use crate::common::CodegenCx; -use crate::coverageinfo::ffi::CounterMappingRegion; +use crate::coverageinfo::ffi; use crate::coverageinfo::map_data::{FunctionCoverage, FunctionCoverageCollector}; use crate::{coverageinfo, llvm}; @@ -235,7 +236,10 @@ fn encode_mappings_for_function( let expressions = function_coverage.counter_expressions().collect::>(); let mut virtual_file_mapping = VirtualFileMapping::default(); - let mut mapping_regions = Vec::with_capacity(counter_regions.len()); + let mut code_regions = vec![]; + let mut branch_regions = vec![]; + let mut mcdc_branch_regions = vec![]; + let mut mcdc_decision_regions = vec![]; // Group mappings into runs with the same filename, preserving the order // yielded by `FunctionCoverage`. @@ -255,11 +259,36 @@ fn encode_mappings_for_function( // form suitable for FFI. for (mapping_kind, region) in counter_regions_for_file { debug!("Adding counter {mapping_kind:?} to map for {region:?}"); - mapping_regions.push(CounterMappingRegion::from_mapping( - &mapping_kind, - local_file_id.as_u32(), - region, - )); + let span = ffi::CoverageSpan::from_source_region(local_file_id.as_u32(), region); + match mapping_kind { + MappingKind::Code(term) => { + code_regions + .push(ffi::CodeRegion { span, counter: ffi::Counter::from_term(term) }); + } + MappingKind::Branch { true_term, false_term } => { + branch_regions.push(ffi::BranchRegion { + span, + true_counter: ffi::Counter::from_term(true_term), + false_counter: ffi::Counter::from_term(false_term), + }); + } + MappingKind::MCDCBranch { true_term, false_term, mcdc_params } => { + mcdc_branch_regions.push(ffi::MCDCBranchRegion { + span, + true_counter: ffi::Counter::from_term(true_term), + false_counter: ffi::Counter::from_term(false_term), + mcdc_branch_params: ffi::mcdc::BranchParameters::from(mcdc_params), + }); + } + MappingKind::MCDCDecision(mcdc_decision_params) => { + mcdc_decision_regions.push(ffi::MCDCDecisionRegion { + span, + mcdc_decision_params: ffi::mcdc::DecisionParameters::from( + mcdc_decision_params, + ), + }); + } + } } } @@ -268,7 +297,10 @@ fn encode_mappings_for_function( coverageinfo::write_mapping_to_buffer( virtual_file_mapping.into_vec(), expressions, - mapping_regions, + &code_regions, + &branch_regions, + &mcdc_branch_regions, + &mcdc_decision_regions, buffer, ); }) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index d7d29eebf8593..7f08659e5a229 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -16,7 +16,6 @@ use tracing::{debug, instrument}; use crate::builder::Builder; use crate::common::CodegenCx; -use crate::coverageinfo::ffi::{CounterExpression, CounterMappingRegion}; use crate::coverageinfo::map_data::FunctionCoverageCollector; use crate::llvm; @@ -255,8 +254,11 @@ pub(crate) fn write_filenames_section_to_buffer<'a>( pub(crate) fn write_mapping_to_buffer( virtual_file_mapping: Vec, - expressions: Vec, - mapping_regions: Vec, + expressions: Vec, + code_regions: &[ffi::CodeRegion], + branch_regions: &[ffi::BranchRegion], + mcdc_branch_regions: &[ffi::MCDCBranchRegion], + mcdc_decision_regions: &[ffi::MCDCDecisionRegion], buffer: &RustString, ) { unsafe { @@ -265,8 +267,14 @@ pub(crate) fn write_mapping_to_buffer( virtual_file_mapping.len() as c_uint, expressions.as_ptr(), expressions.len() as c_uint, - mapping_regions.as_ptr(), - mapping_regions.len() as c_uint, + code_regions.as_ptr(), + code_regions.len() as c_uint, + branch_regions.as_ptr(), + branch_regions.len() as c_uint, + mcdc_branch_regions.as_ptr(), + mcdc_branch_regions.len() as c_uint, + mcdc_decision_regions.as_ptr(), + mcdc_decision_regions.len() as c_uint, buffer, ); } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index c41961fb39465..73e977da2e3ae 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1754,8 +1754,14 @@ unsafe extern "C" { NumVirtualFileMappingIDs: c_uint, Expressions: *const crate::coverageinfo::ffi::CounterExpression, NumExpressions: c_uint, - MappingRegions: *const crate::coverageinfo::ffi::CounterMappingRegion, - NumMappingRegions: c_uint, + CodeRegions: *const crate::coverageinfo::ffi::CodeRegion, + NumCodeRegions: c_uint, + BranchRegions: *const crate::coverageinfo::ffi::BranchRegion, + NumBranchRegions: c_uint, + MCDCBranchRegions: *const crate::coverageinfo::ffi::MCDCBranchRegion, + NumMCDCBranchRegions: c_uint, + MCDCDecisionRegions: *const crate::coverageinfo::ffi::MCDCDecisionRegion, + NumMCDCDecisionRegions: c_uint, BufferOut: &RustString, ); diff --git a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp index cda81d4a9b5b2..b32af5e5e75cc 100644 --- a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp @@ -33,45 +33,6 @@ static coverage::Counter fromRust(LLVMRustCounter Counter) { report_fatal_error("Bad LLVMRustCounterKind!"); } -// FFI equivalent of enum `llvm::coverage::CounterMappingRegion::RegionKind` -// https://github.com/rust-lang/llvm-project/blob/ea6fa9c2/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L213-L234 -enum class LLVMRustCounterMappingRegionKind { - CodeRegion = 0, - ExpansionRegion = 1, - SkippedRegion = 2, - GapRegion = 3, - BranchRegion = 4, - MCDCDecisionRegion = 5, - MCDCBranchRegion = 6 -}; - -static coverage::CounterMappingRegion::RegionKind -fromRust(LLVMRustCounterMappingRegionKind Kind) { - switch (Kind) { - case LLVMRustCounterMappingRegionKind::CodeRegion: - return coverage::CounterMappingRegion::CodeRegion; - case LLVMRustCounterMappingRegionKind::ExpansionRegion: - return coverage::CounterMappingRegion::ExpansionRegion; - case LLVMRustCounterMappingRegionKind::SkippedRegion: - return coverage::CounterMappingRegion::SkippedRegion; - case LLVMRustCounterMappingRegionKind::GapRegion: - return coverage::CounterMappingRegion::GapRegion; - case LLVMRustCounterMappingRegionKind::BranchRegion: - return coverage::CounterMappingRegion::BranchRegion; - case LLVMRustCounterMappingRegionKind::MCDCDecisionRegion: - return coverage::CounterMappingRegion::MCDCDecisionRegion; - case LLVMRustCounterMappingRegionKind::MCDCBranchRegion: - return coverage::CounterMappingRegion::MCDCBranchRegion; - } - report_fatal_error("Bad LLVMRustCounterMappingRegionKind!"); -} - -enum LLVMRustMCDCParametersTag { - None = 0, - Decision = 1, - Branch = 2, -}; - struct LLVMRustMCDCDecisionParameters { uint32_t BitmapIdx; uint16_t NumConditions; @@ -82,47 +43,58 @@ struct LLVMRustMCDCBranchParameters { int16_t ConditionIDs[2]; }; -struct LLVMRustMCDCParameters { - LLVMRustMCDCParametersTag Tag; - LLVMRustMCDCDecisionParameters DecisionParameters; - LLVMRustMCDCBranchParameters BranchParameters; -}; - #if LLVM_VERSION_GE(19, 0) -static coverage::mcdc::Parameters fromRust(LLVMRustMCDCParameters Params) { - switch (Params.Tag) { - case LLVMRustMCDCParametersTag::None: - return std::monostate(); - case LLVMRustMCDCParametersTag::Decision: - return coverage::mcdc::DecisionParameters( - Params.DecisionParameters.BitmapIdx, - Params.DecisionParameters.NumConditions); - case LLVMRustMCDCParametersTag::Branch: - return coverage::mcdc::BranchParameters( - static_cast( - Params.BranchParameters.ConditionID), - {static_cast( - Params.BranchParameters.ConditionIDs[0]), - static_cast( - Params.BranchParameters.ConditionIDs[1])}); - } - report_fatal_error("Bad LLVMRustMCDCParametersTag!"); +static coverage::mcdc::BranchParameters +fromRust(LLVMRustMCDCBranchParameters Params) { + return coverage::mcdc::BranchParameters( + Params.ConditionID, {Params.ConditionIDs[0], Params.ConditionIDs[1]}); +} + +static coverage::mcdc::DecisionParameters +fromRust(LLVMRustMCDCDecisionParameters Params) { + return coverage::mcdc::DecisionParameters(Params.BitmapIdx, + Params.NumConditions); } #endif -// FFI equivalent of struct `llvm::coverage::CounterMappingRegion` -// https://github.com/rust-lang/llvm-project/blob/ea6fa9c2/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L211-L304 -struct LLVMRustCounterMappingRegion { - LLVMRustCounter Count; - LLVMRustCounter FalseCount; - LLVMRustMCDCParameters MCDCParameters; +// Must match the layout of +// `rustc_codegen_llvm::coverageinfo::ffi::CoverageSpan`. +struct LLVMRustCoverageSpan { uint32_t FileID; - uint32_t ExpandedFileID; uint32_t LineStart; uint32_t ColumnStart; uint32_t LineEnd; uint32_t ColumnEnd; - LLVMRustCounterMappingRegionKind Kind; +}; + +// Must match the layout of `rustc_codegen_llvm::coverageinfo::ffi::CodeRegion`. +struct LLVMRustCoverageCodeRegion { + LLVMRustCoverageSpan Span; + LLVMRustCounter Count; +}; + +// Must match the layout of +// `rustc_codegen_llvm::coverageinfo::ffi::BranchRegion`. +struct LLVMRustCoverageBranchRegion { + LLVMRustCoverageSpan Span; + LLVMRustCounter TrueCount; + LLVMRustCounter FalseCount; +}; + +// Must match the layout of +// `rustc_codegen_llvm::coverageinfo::ffi::MCDCBranchRegion`. +struct LLVMRustCoverageMCDCBranchRegion { + LLVMRustCoverageSpan Span; + LLVMRustCounter TrueCount; + LLVMRustCounter FalseCount; + LLVMRustMCDCBranchParameters MCDCBranchParams; +}; + +// Must match the layout of +// `rustc_codegen_llvm::coverageinfo::ffi::MCDCDecisionRegion`. +struct LLVMRustCoverageMCDCDecisionRegion { + LLVMRustCoverageSpan Span; + LLVMRustMCDCDecisionParameters MCDCDecisionParams; }; // FFI equivalent of enum `llvm::coverage::CounterExpression::ExprKind` @@ -174,28 +146,16 @@ extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer( extern "C" void LLVMRustCoverageWriteMappingToBuffer( const unsigned *VirtualFileMappingIDs, unsigned NumVirtualFileMappingIDs, const LLVMRustCounterExpression *RustExpressions, unsigned NumExpressions, - const LLVMRustCounterMappingRegion *RustMappingRegions, - unsigned NumMappingRegions, RustStringRef BufferOut) { + const LLVMRustCoverageCodeRegion *CodeRegions, unsigned NumCodeRegions, + const LLVMRustCoverageBranchRegion *BranchRegions, + unsigned NumBranchRegions, + const LLVMRustCoverageMCDCBranchRegion *MCDCBranchRegions, + unsigned NumMCDCBranchRegions, + const LLVMRustCoverageMCDCDecisionRegion *MCDCDecisionRegions, + unsigned NumMCDCDecisionRegions, RustStringRef BufferOut) { // Convert from FFI representation to LLVM representation. - SmallVector MappingRegions; - MappingRegions.reserve(NumMappingRegions); - for (const auto &Region : ArrayRef( - RustMappingRegions, NumMappingRegions)) { - MappingRegions.emplace_back( - fromRust(Region.Count), fromRust(Region.FalseCount), -#if LLVM_VERSION_LT(19, 0) - coverage::CounterMappingRegion::MCDCParameters{}, -#endif - Region.FileID, Region.ExpandedFileID, // File IDs, then region info. - Region.LineStart, Region.ColumnStart, Region.LineEnd, Region.ColumnEnd, - fromRust(Region.Kind) -#if LLVM_VERSION_GE(19, 0) - , - fromRust(Region.MCDCParameters) -#endif - ); - } + // Expressions: std::vector Expressions; Expressions.reserve(NumExpressions); for (const auto &Expression : @@ -205,6 +165,46 @@ extern "C" void LLVMRustCoverageWriteMappingToBuffer( fromRust(Expression.RHS)); } + std::vector MappingRegions; + MappingRegions.reserve(NumCodeRegions + NumBranchRegions + + NumMCDCBranchRegions + NumMCDCDecisionRegions); + + // Code regions: + for (const auto &Region : ArrayRef(CodeRegions, NumCodeRegions)) { + MappingRegions.push_back(coverage::CounterMappingRegion::makeRegion( + fromRust(Region.Count), Region.Span.FileID, Region.Span.LineStart, + Region.Span.ColumnStart, Region.Span.LineEnd, Region.Span.ColumnEnd)); + } + + // Branch regions: + for (const auto &Region : ArrayRef(BranchRegions, NumBranchRegions)) { + MappingRegions.push_back(coverage::CounterMappingRegion::makeBranchRegion( + fromRust(Region.TrueCount), fromRust(Region.FalseCount), + Region.Span.FileID, Region.Span.LineStart, Region.Span.ColumnStart, + Region.Span.LineEnd, Region.Span.ColumnEnd)); + } + +#if LLVM_VERSION_GE(19, 0) + // MC/DC branch regions: + for (const auto &Region : ArrayRef(MCDCBranchRegions, NumMCDCBranchRegions)) { + MappingRegions.push_back(coverage::CounterMappingRegion::makeBranchRegion( + fromRust(Region.TrueCount), fromRust(Region.FalseCount), + Region.Span.FileID, Region.Span.LineStart, Region.Span.ColumnStart, + Region.Span.LineEnd, Region.Span.ColumnEnd, + fromRust(Region.MCDCBranchParams))); + } + + // MC/DC decision regions: + for (const auto &Region : + ArrayRef(MCDCDecisionRegions, NumMCDCDecisionRegions)) { + MappingRegions.push_back(coverage::CounterMappingRegion::makeDecisionRegion( + fromRust(Region.MCDCDecisionParams), Region.Span.FileID, + Region.Span.LineStart, Region.Span.ColumnStart, Region.Span.LineEnd, + Region.Span.ColumnEnd)); + } +#endif + + // Write the converted expressions and mappings to a byte buffer. auto CoverageMappingWriter = coverage::CoverageMappingWriter( ArrayRef(VirtualFileMappingIDs, NumVirtualFileMappingIDs), Expressions, MappingRegions); From 46cc5e9e962fda2f99d4956ef539bf4b79fead26 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Fri, 18 Oct 2024 16:47:19 +0200 Subject: [PATCH 06/15] elaborate why dropping principal in `*dyn` casts is non-trivial --- compiler/rustc_hir_typeck/src/cast.rs | 31 +++++++++++++++++-- .../cast/ptr-to-trait-obj-drop-principal.rs | 21 +++++++++++++ .../ptr-to-trait-obj-drop-principal.stderr | 11 +++++++ 3 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 tests/ui/cast/ptr-to-trait-obj-drop-principal.rs create mode 100644 tests/ui/cast/ptr-to-trait-obj-drop-principal.stderr diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 7341d3fa3c4e2..86af6c97af574 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -959,8 +959,35 @@ impl<'a, 'tcx> CastCheck<'tcx> { // dyn Auto -> dyn Auto'? ok. (None, None) => Ok(CastKind::PtrPtrCast), - // dyn Trait -> dyn Auto? should be ok, but we used to not allow it. - // FIXME: allow this + // dyn Trait -> dyn Auto? not ok (for now). + // + // Although dropping the principal is already allowed for unsizing coercions + // (e.g. `*const (dyn Trait + Auto)` to `*const dyn Auto`), dropping it is + // currently **NOT** allowed for (non-coercion) ptr-to-ptr casts (e.g + // `*const Foo` to `*const Bar` where `Foo` has a `dyn Trait + Auto` tail + // and `Bar` has a `dyn Auto` tail), because the underlying MIR operations + // currently work very differently: + // + // * A MIR unsizing coercion on raw pointers to trait objects (`*const dyn Src` + // to `*const dyn Dst`) is currently equivalent to downcasting the source to + // the concrete sized type that it was originally unsized from first (via a + // ptr-to-ptr cast from `*const Src` to `*const T` with `T: Sized`) and then + // unsizing this thin pointer to the target type (unsizing `*const T` to + // `*const Dst`). In particular, this means that the pointer's metadata + // (vtable) will semantically change, e.g. for const eval and miri, even + // though the vtables will always be merged for codegen. + // + // * A MIR ptr-to-ptr cast is currently equivalent to a transmute and does not + // change the pointer metadata (vtable) at all. + // + // In addition to this potentially surprising difference between coercion and + // non-coercion casts, casting away the principal with a MIR ptr-to-ptr cast + // is currently considered undefined behavior: + // + // As a validity invariant of pointers to trait objects, we currently require + // that the principal of the vtable in the pointer metadata exactly matches + // the principal of the pointee type, where "no principal" is also considered + // a kind of principal. (Some(_), None) => Err(CastError::DifferingKinds { src_kind, dst_kind }), // dyn Auto -> dyn Trait? not ok. diff --git a/tests/ui/cast/ptr-to-trait-obj-drop-principal.rs b/tests/ui/cast/ptr-to-trait-obj-drop-principal.rs new file mode 100644 index 0000000000000..01dd91fc77dd7 --- /dev/null +++ b/tests/ui/cast/ptr-to-trait-obj-drop-principal.rs @@ -0,0 +1,21 @@ +//! Test that non-coercion casts aren't allowed to drop the principal, +//! because they cannot modify the pointer metadata. +//! +//! We test this in a const context to guard against UB if this is allowed +//! in the future. + +trait Trait {} +impl Trait for () {} + +struct Wrapper(T); + +const OBJECT: *const (dyn Trait + Send) = &(); + +// coercions are allowed +const _: *const dyn Send = OBJECT as _; + +// casts are **not** allowed +const _: *const Wrapper = OBJECT as _; +//~^ ERROR casting `*const (dyn Trait + Send + 'static)` as `*const Wrapper` is invalid + +fn main() {} diff --git a/tests/ui/cast/ptr-to-trait-obj-drop-principal.stderr b/tests/ui/cast/ptr-to-trait-obj-drop-principal.stderr new file mode 100644 index 0000000000000..719e0711f5b9b --- /dev/null +++ b/tests/ui/cast/ptr-to-trait-obj-drop-principal.stderr @@ -0,0 +1,11 @@ +error[E0606]: casting `*const (dyn Trait + Send + 'static)` as `*const Wrapper` is invalid + --> $DIR/ptr-to-trait-obj-drop-principal.rs:18:37 + | +LL | const _: *const Wrapper = OBJECT as _; + | ^^^^^^^^^^^ + | + = note: the trait objects may have different vtables + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0606`. From 8f85b90ca6d57459eb19accb6aaf781dd1c7bf6c Mon Sep 17 00:00:00 2001 From: Adrian Taylor Date: Wed, 11 Sep 2024 12:27:08 +0000 Subject: [PATCH 07/15] Rename Receiver -> LegacyReceiver As part of the "arbitrary self types v2" project, we are going to replace the current `Receiver` trait with a new mechanism based on a new, different `Receiver` trait. This PR renames the old trait to get it out the way. Naming is hard. Options considered included: * HardCodedReceiver (because it should only be used for things in the standard library, and hence is sort-of hard coded) * LegacyReceiver * TargetLessReceiver * OldReceiver These are all bad names, but fortunately this will be temporary. Assuming the new mechanism proceeds to stabilization as intended, the legacy trait will be removed altogether. Although we expect this trait to be used only in the standard library, we suspect it may be in use elsehwere, so we're landing this change separately to identify any surprising breakages. It's known that this trait is used within the Rust for Linux project; a patch is in progress to remove their dependency. This is a part of the arbitrary self types v2 project, https://github.com/rust-lang/rfcs/pull/3519 https://github.com/rust-lang/rust/issues/44874 r? @wesleywiser --- .../example/mini_core.rs | 10 +++++----- .../rustc_codegen_gcc/example/mini_core.rs | 10 +++++----- compiler/rustc_hir/src/lang_items.rs | 2 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 2 +- compiler/rustc_span/src/symbol.rs | 2 +- library/alloc/src/boxed.rs | 6 +++--- library/alloc/src/lib.rs | 2 +- library/alloc/src/rc.rs | 6 +++--- library/alloc/src/sync.rs | 6 +++--- library/core/src/ops/deref.rs | 20 ++++++++++++------- library/core/src/ops/mod.rs | 4 ++-- library/core/src/pin.rs | 6 +++--- tests/codegen/avr/avr-func-addrspace.rs | 4 ++-- .../kcfi/emit-type-metadata-trait-objects.rs | 4 ++-- tests/rustdoc-json/impls/auto.rs | 4 ++-- tests/ui/abi/compatibility.rs | 8 ++++---- tests/ui/privacy/privacy1.rs | 6 +++--- .../const-traits/const-fns-are-early-bound.rs | 8 ++++---- .../traits/const-traits/effects/minicore.rs | 10 +++++----- 19 files changed, 63 insertions(+), 57 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/example/mini_core.rs b/compiler/rustc_codegen_cranelift/example/mini_core.rs index 9fc0318df5dc0..42c7f5f0dc692 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core.rs @@ -47,12 +47,12 @@ impl, U: ?Sized> DispatchFromDyn<*const U> for *const T {} impl, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {} impl, U: ?Sized> DispatchFromDyn> for Box {} -#[lang = "receiver"] -pub trait Receiver {} +#[lang = "legacy_receiver"] +pub trait LegacyReceiver {} -impl Receiver for &T {} -impl Receiver for &mut T {} -impl Receiver for Box {} +impl LegacyReceiver for &T {} +impl LegacyReceiver for &mut T {} +impl LegacyReceiver for Box {} #[lang = "copy"] pub unsafe trait Copy {} diff --git a/compiler/rustc_codegen_gcc/example/mini_core.rs b/compiler/rustc_codegen_gcc/example/mini_core.rs index f47bfdad13128..0576b64ef6fa5 100644 --- a/compiler/rustc_codegen_gcc/example/mini_core.rs +++ b/compiler/rustc_codegen_gcc/example/mini_core.rs @@ -44,12 +44,12 @@ impl, U: ?Sized> DispatchFromDyn<*const U> for *const T {} impl, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {} impl, U: ?Sized> DispatchFromDyn> for Box {} -#[lang = "receiver"] -pub trait Receiver {} +#[lang = "legacy_receiver"] +pub trait LegacyReceiver {} -impl Receiver for &T {} -impl Receiver for &mut T {} -impl Receiver for Box {} +impl LegacyReceiver for &T {} +impl LegacyReceiver for &mut T {} +impl LegacyReceiver for Box {} #[lang = "copy"] pub unsafe trait Copy {} diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index b161e6ba0fa51..ae046c09ebea3 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -241,7 +241,7 @@ language_item_table! { DerefMut, sym::deref_mut, deref_mut_trait, Target::Trait, GenericRequirement::Exact(0); DerefPure, sym::deref_pure, deref_pure_trait, Target::Trait, GenericRequirement::Exact(0); DerefTarget, sym::deref_target, deref_target, Target::AssocTy, GenericRequirement::None; - Receiver, sym::receiver, receiver_trait, Target::Trait, GenericRequirement::None; + LegacyReceiver, sym::legacy_receiver, legacy_receiver_trait, Target::Trait, GenericRequirement::None; Fn, kw::Fn, fn_trait, Target::Trait, GenericRequirement::Exact(1); FnMut, sym::fn_mut, fn_mut_trait, Target::Trait, GenericRequirement::Exact(1); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index f788456d4e9eb..ee46a1ffc7b8a 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1801,7 +1801,7 @@ fn receiver_is_valid<'tcx>( autoderef = autoderef.include_raw_pointers(); } - let receiver_trait_def_id = tcx.require_lang_item(LangItem::Receiver, Some(span)); + let receiver_trait_def_id = tcx.require_lang_item(LangItem::LegacyReceiver, Some(span)); // Keep dereferencing `receiver_ty` until we get to `self_ty`. while let Some((potential_self_ty, _)) = autoderef.next() { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 3ab482072b8f4..aa05b88ea0c40 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1133,6 +1133,7 @@ symbols! { lazy_normalization_consts, lazy_type_alias, le, + legacy_receiver, len, let_chains, let_else, @@ -1573,7 +1574,6 @@ symbols! { readonly, realloc, reason, - receiver, recursion_limit, reexport_test_harness_main, ref_pat_eat_one_layer_2024, diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 3e791416820ef..bc354650a8ebc 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -196,7 +196,7 @@ use core::marker::{Tuple, Unsize}; use core::mem::{self, SizedTypeProperties}; use core::ops::{ AsyncFn, AsyncFnMut, AsyncFnOnce, CoerceUnsized, Coroutine, CoroutineState, Deref, DerefMut, - DerefPure, DispatchFromDyn, Receiver, + DerefPure, DispatchFromDyn, LegacyReceiver, }; use core::pin::{Pin, PinCoerceUnsized}; use core::ptr::{self, NonNull, Unique}; @@ -2378,8 +2378,8 @@ impl DerefMut for Box { #[unstable(feature = "deref_pure_trait", issue = "87121")] unsafe impl DerefPure for Box {} -#[unstable(feature = "receiver_trait", issue = "none")] -impl Receiver for Box {} +#[unstable(feature = "legacy_receiver_trait", issue = "none")] +impl LegacyReceiver for Box {} #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for Box { diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 50a5f3c5b1e04..dd9dfa3f5e26d 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -129,6 +129,7 @@ #![feature(iter_advance_by)] #![feature(iter_next_chunk)] #![feature(layout_for_ptr)] +#![feature(legacy_receiver_trait)] #![feature(local_waker)] #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_uninit_array_transpose)] @@ -138,7 +139,6 @@ #![feature(ptr_internals)] #![feature(ptr_metadata)] #![feature(ptr_sub_ptr)] -#![feature(receiver_trait)] #![feature(set_ptr_value)] #![feature(sized_type_properties)] #![feature(slice_from_ptr_range)] diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index e98ae7c31ad06..686a93bf93789 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -252,7 +252,7 @@ use core::intrinsics::abort; use core::iter; use core::marker::{PhantomData, Unsize}; use core::mem::{self, ManuallyDrop, align_of_val_raw}; -use core::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, Receiver}; +use core::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, LegacyReceiver}; use core::panic::{RefUnwindSafe, UnwindSafe}; #[cfg(not(no_global_oom_handling))] use core::pin::Pin; @@ -2222,8 +2222,8 @@ unsafe impl PinCoerceUnsized for Weak {} #[unstable(feature = "deref_pure_trait", issue = "87121")] unsafe impl DerefPure for Rc {} -#[unstable(feature = "receiver_trait", issue = "none")] -impl Receiver for Rc {} +#[unstable(feature = "legacy_receiver_trait", issue = "none")] +impl LegacyReceiver for Rc {} #[stable(feature = "rust1", since = "1.0.0")] unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Rc { diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index acbc325a51415..a15d7c2a4423b 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -18,7 +18,7 @@ use core::intrinsics::abort; use core::iter; use core::marker::{PhantomData, Unsize}; use core::mem::{self, ManuallyDrop, align_of_val_raw}; -use core::ops::{CoerceUnsized, Deref, DerefPure, DispatchFromDyn, Receiver}; +use core::ops::{CoerceUnsized, Deref, DerefPure, DispatchFromDyn, LegacyReceiver}; use core::panic::{RefUnwindSafe, UnwindSafe}; use core::pin::{Pin, PinCoerceUnsized}; use core::ptr::{self, NonNull}; @@ -2189,8 +2189,8 @@ unsafe impl PinCoerceUnsized for Weak {} #[unstable(feature = "deref_pure_trait", issue = "87121")] unsafe impl DerefPure for Arc {} -#[unstable(feature = "receiver_trait", issue = "none")] -impl Receiver for Arc {} +#[unstable(feature = "legacy_receiver_trait", issue = "none")] +impl LegacyReceiver for Arc {} #[cfg(not(no_global_oom_handling))] impl Arc { diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs index f0d2c761ef35b..49b380e45749b 100644 --- a/library/core/src/ops/deref.rs +++ b/library/core/src/ops/deref.rs @@ -297,15 +297,21 @@ unsafe impl DerefPure for &mut T {} /// Indicates that a struct can be used as a method receiver, without the /// `arbitrary_self_types` feature. This is implemented by stdlib pointer types like `Box`, /// `Rc`, `&T`, and `Pin

`. -#[lang = "receiver"] -#[unstable(feature = "receiver_trait", issue = "none")] +/// +/// This trait will shortly be removed and replaced with a more generic +/// facility based around the current "arbitrary self types" unstable feature. +/// That new facility will use a replacement trait called `Receiver` which is +/// why this is now named `LegacyReceiver`. +#[cfg_attr(bootstrap, lang = "receiver")] +#[cfg_attr(not(bootstrap), lang = "legacy_receiver")] +#[unstable(feature = "legacy_receiver_trait", issue = "none")] #[doc(hidden)] -pub trait Receiver { +pub trait LegacyReceiver { // Empty. } -#[unstable(feature = "receiver_trait", issue = "none")] -impl Receiver for &T {} +#[unstable(feature = "legacy_receiver_trait", issue = "none")] +impl LegacyReceiver for &T {} -#[unstable(feature = "receiver_trait", issue = "none")] -impl Receiver for &mut T {} +#[unstable(feature = "legacy_receiver_trait", issue = "none")] +impl LegacyReceiver for &mut T {} diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs index 5464bf645d978..c9f47e5daadd6 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -168,8 +168,8 @@ pub use self::control_flow::ControlFlow; pub use self::coroutine::{Coroutine, CoroutineState}; #[unstable(feature = "deref_pure_trait", issue = "87121")] pub use self::deref::DerefPure; -#[unstable(feature = "receiver_trait", issue = "none")] -pub use self::deref::Receiver; +#[unstable(feature = "legacy_receiver_trait", issue = "none")] +pub use self::deref::LegacyReceiver; #[stable(feature = "rust1", since = "1.0.0")] pub use self::deref::{Deref, DerefMut}; #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 5d5733d38fca1..254b306fcaafe 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -921,7 +921,7 @@ #![stable(feature = "pin", since = "1.33.0")] use crate::hash::{Hash, Hasher}; -use crate::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, Receiver}; +use crate::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, LegacyReceiver}; #[allow(unused_imports)] use crate::{ cell::{RefCell, UnsafeCell}, @@ -1692,8 +1692,8 @@ impl> DerefMut for Pin { #[unstable(feature = "deref_pure_trait", issue = "87121")] unsafe impl DerefPure for Pin {} -#[unstable(feature = "receiver_trait", issue = "none")] -impl Receiver for Pin {} +#[unstable(feature = "legacy_receiver_trait", issue = "none")] +impl LegacyReceiver for Pin {} #[stable(feature = "pin", since = "1.33.0")] impl fmt::Debug for Pin { diff --git a/tests/codegen/avr/avr-func-addrspace.rs b/tests/codegen/avr/avr-func-addrspace.rs index 7f9a7e6e81103..a2dcb1c092472 100644 --- a/tests/codegen/avr/avr-func-addrspace.rs +++ b/tests/codegen/avr/avr-func-addrspace.rs @@ -18,8 +18,8 @@ pub trait Sized {} #[lang = "copy"] pub trait Copy {} impl Copy for *const T {} -#[lang = "receiver"] -pub trait Receiver {} +#[lang = "legacy_receiver"] +pub trait LegacyReceiver {} #[lang = "tuple_trait"] pub trait Tuple {} diff --git a/tests/codegen/sanitizer/kcfi/emit-type-metadata-trait-objects.rs b/tests/codegen/sanitizer/kcfi/emit-type-metadata-trait-objects.rs index c1967e55e75b4..5ab55a467268b 100644 --- a/tests/codegen/sanitizer/kcfi/emit-type-metadata-trait-objects.rs +++ b/tests/codegen/sanitizer/kcfi/emit-type-metadata-trait-objects.rs @@ -16,8 +16,8 @@ trait Sized {} #[lang = "copy"] trait Copy {} impl Copy for &T {} -#[lang = "receiver"] -trait Receiver {} +#[lang = "legacy_receiver"] +trait LegacyReceiver {} #[lang = "dispatch_from_dyn"] trait DispatchFromDyn {} impl<'a, T: ?Sized + Unsize, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {} diff --git a/tests/rustdoc-json/impls/auto.rs b/tests/rustdoc-json/impls/auto.rs index e14c935b23b87..f37dae4c1ed43 100644 --- a/tests/rustdoc-json/impls/auto.rs +++ b/tests/rustdoc-json/impls/auto.rs @@ -4,8 +4,8 @@ #[lang = "sized"] trait Sized {} -#[lang = "receiver"] -pub trait Receiver {} +#[lang = "legacy_receiver"] +pub trait LegacyReceiver {} pub auto trait Bar {} diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs index 28c8063a92311..fc50560226a74 100644 --- a/tests/ui/abi/compatibility.rs +++ b/tests/ui/abi/compatibility.rs @@ -79,10 +79,10 @@ mod prelude { #[lang = "sized"] pub trait Sized {} - #[lang = "receiver"] - pub trait Receiver {} - impl Receiver for &T {} - impl Receiver for &mut T {} + #[lang = "legacy_receiver"] + pub trait LegacyReceiver {} + impl LegacyReceiver for &T {} + impl LegacyReceiver for &mut T {} #[lang = "copy"] pub trait Copy: Sized {} diff --git a/tests/ui/privacy/privacy1.rs b/tests/ui/privacy/privacy1.rs index fcb2108ab5fec..31f3960100371 100644 --- a/tests/ui/privacy/privacy1.rs +++ b/tests/ui/privacy/privacy1.rs @@ -12,14 +12,14 @@ pub trait Deref { type Target; } -#[lang="receiver"] -pub trait Receiver: Deref {} +#[lang="legacy_receiver"] +pub trait LegacyReceiver: Deref {} impl<'a, T> Deref for &'a T { type Target = T; } -impl<'a, T> Receiver for &'a T {} +impl<'a, T> LegacyReceiver for &'a T {} mod bar { // shouldn't bring in too much diff --git a/tests/ui/traits/const-traits/const-fns-are-early-bound.rs b/tests/ui/traits/const-traits/const-fns-are-early-bound.rs index b3087349e4d3c..b87387f4d5de3 100644 --- a/tests/ui/traits/const-traits/const-fns-are-early-bound.rs +++ b/tests/ui/traits/const-traits/const-fns-are-early-bound.rs @@ -82,12 +82,12 @@ trait Copy {} #[lang = "tuple_trait"] trait Tuple {} -#[lang = "receiver"] -trait Receiver {} +#[lang = "legacy_receiver"] +trait LegacyReceiver {} -impl Receiver for &T {} +impl LegacyReceiver for &T {} -impl Receiver for &mut T {} +impl LegacyReceiver for &mut T {} #[stable(feature = "minicore", since = "1.0.0")] pub mod effects { diff --git a/tests/ui/traits/const-traits/effects/minicore.rs b/tests/ui/traits/const-traits/effects/minicore.rs index 1c3c66bc3ce76..9b615450c68fe 100644 --- a/tests/ui/traits/const-traits/effects/minicore.rs +++ b/tests/ui/traits/const-traits/effects/minicore.rs @@ -137,12 +137,12 @@ macro_rules! impl_fn_mut_tuple { //impl_fn_mut_tuple!(A B C D); //impl_fn_mut_tuple!(A B C D E); -#[lang = "receiver"] -trait Receiver {} +#[lang = "legacy_receiver"] +trait LegacyReceiver {} -impl Receiver for &T {} +impl LegacyReceiver for &T {} -impl Receiver for &mut T {} +impl LegacyReceiver for &mut T {} #[lang = "destruct"] #[const_trait] @@ -454,7 +454,7 @@ impl /* const */ Deref for Option { } } -impl Receiver for Pin

{} +impl LegacyReceiver for Pin

{} impl Clone for RefCell { fn clone(&self) -> RefCell { From 03048096f6c4ed89ee2a5d6c86cd8268d0bc61bd Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 23 Oct 2024 19:44:17 +0200 Subject: [PATCH 08/15] stop hashing compile-time constant --- compiler/rustc_query_system/src/ich/impls_syntax.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/compiler/rustc_query_system/src/ich/impls_syntax.rs b/compiler/rustc_query_system/src/ich/impls_syntax.rs index 29a28b10a068e..0665401df8e84 100644 --- a/compiler/rustc_query_system/src/ich/impls_syntax.rs +++ b/compiler/rustc_query_system/src/ich/impls_syntax.rs @@ -111,13 +111,8 @@ impl<'a> HashStable> for SourceFile { impl<'tcx> HashStable> for rustc_feature::Features { fn hash_stable(&self, hcx: &mut StableHashingContext<'tcx>, hasher: &mut StableHasher) { // Unfortunately we cannot exhaustively list fields here, since the - // struct is macro generated. + // struct has private fields (to ensure its invariant is maintained) self.enabled_lang_features().hash_stable(hcx, hasher); self.enabled_lib_features().hash_stable(hcx, hasher); - - // FIXME: why do we hash something that is a compile-time constant? - for feature in rustc_feature::UNSTABLE_LANG_FEATURES.iter() { - feature.name.hash_stable(hcx, hasher); - } } } From 2e3091d66ccd2e474ac63beaace3813c0f085cfa Mon Sep 17 00:00:00 2001 From: clubby789 Date: Sat, 19 Oct 2024 14:02:40 +0000 Subject: [PATCH 09/15] Don't allow test revisions that conflict with built in cfgs --- src/tools/compiletest/src/common.rs | 18 ++++++++++++++++++ src/tools/compiletest/src/lib.rs | 1 + src/tools/compiletest/src/runtest.rs | 3 +++ tests/ui/lint/lint-missing-doc-expect.rs | 4 ++-- 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index ff059940f7ccd..3e6423e474adf 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -376,6 +376,7 @@ pub struct Config { pub only_modified: bool, pub target_cfgs: OnceLock, + pub builtin_cfg_names: OnceLock>, pub nocapture: bool, @@ -440,6 +441,11 @@ impl Config { self.target_cfg().panic == PanicStrategy::Unwind } + /// Get the list of builtin, 'well known' cfg names + pub fn builtin_cfg_names(&self) -> &HashSet { + self.builtin_cfg_names.get_or_init(|| builtin_cfg_names(self)) + } + pub fn has_threads(&self) -> bool { // Wasm targets don't have threads unless `-threads` is in the target // name, such as `wasm32-wasip1-threads`. @@ -651,6 +657,18 @@ pub enum Endian { Big, } +fn builtin_cfg_names(config: &Config) -> HashSet { + rustc_output( + config, + &["--print=check-cfg", "-Zunstable-options", "--check-cfg=cfg()"], + Default::default(), + ) + .lines() + .map(|l| if let Some((name, _)) = l.split_once('=') { name.to_string() } else { l.to_string() }) + .chain(std::iter::once(String::from("test"))) + .collect() +} + fn rustc_output(config: &Config, args: &[&str], envs: HashMap) -> String { let mut command = Command::new(&config.rustc_path); add_dylib_path(&mut command, iter::once(&config.compile_lib_path)); diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 7d6ede9bcdac5..54ba98ffcc4b3 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -356,6 +356,7 @@ pub fn parse_config(args: Vec) -> Config { force_rerun: matches.opt_present("force-rerun"), target_cfgs: OnceLock::new(), + builtin_cfg_names: OnceLock::new(), nocapture: matches.opt_present("nocapture"), diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 36c5106ddad03..fc409ba3762e5 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -478,6 +478,9 @@ impl<'test> TestCx<'test> { "error: redundant cfg argument `{normalized_revision}` is already created by the revision" ); } + if self.config.builtin_cfg_names().contains(&normalized_revision) { + panic!("error: revision `{normalized_revision}` collides with a builtin cfg"); + } cmd.args(cfg_arg); } diff --git a/tests/ui/lint/lint-missing-doc-expect.rs b/tests/ui/lint/lint-missing-doc-expect.rs index 991f65003dc26..b1abf8b69620c 100644 --- a/tests/ui/lint/lint-missing-doc-expect.rs +++ b/tests/ui/lint/lint-missing-doc-expect.rs @@ -1,10 +1,10 @@ // Make sure that `#[expect(missing_docs)]` is always correctly fulfilled. //@ check-pass -//@ revisions: lib bin test +//@ revisions: lib bin test_ //@ [lib]compile-flags: --crate-type lib //@ [bin]compile-flags: --crate-type bin -//@ [test]compile-flags: --test +//@ [test_]compile-flags: --test #[expect(missing_docs)] pub fn foo() {} From dab76eccdfbb6f7b4b445ad05ba4ef004c43e130 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 12 Oct 2024 11:52:30 +0200 Subject: [PATCH 10/15] fix a couple clippy:complexitys double_parens filter_map_identity needless_question_mark redundant_guards --- compiler/rustc_attr/src/builtin.rs | 4 ++-- compiler/rustc_middle/src/mir/pretty.rs | 4 ++-- compiler/rustc_mir_transform/src/coverage/mappings.rs | 2 +- compiler/rustc_mir_transform/src/coverage/spans.rs | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index e412417a9e95f..537d8e045311c 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -619,11 +619,11 @@ pub fn eval_condition( // we can't use `try_gate_cfg` as symbols don't differentiate between `r#true` // and `true`, and we want to keep the former working without feature gate gate_cfg( - &(( + &( if *b { kw::True } else { kw::False }, sym::cfg_boolean_literals, |features: &Features| features.cfg_boolean_literals(), - )), + ), cfg.span(), sess, features, diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 2a3a070a6e715..faa022b50ef13 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -277,9 +277,9 @@ pub fn create_dump_file<'tcx>( ) })?; } - Ok(fs::File::create_buffered(&file_path).map_err(|e| { + fs::File::create_buffered(&file_path).map_err(|e| { io::Error::new(e.kind(), format!("IO error creating MIR dump file: {file_path:?}; {e}")) - })?) + }) } /////////////////////////////////////////////////////////////////////////// diff --git a/compiler/rustc_mir_transform/src/coverage/mappings.rs b/compiler/rustc_mir_transform/src/coverage/mappings.rs index bc86ae22a0dbd..2db7c6cf1d6fd 100644 --- a/compiler/rustc_mir_transform/src/coverage/mappings.rs +++ b/compiler/rustc_mir_transform/src/coverage/mappings.rs @@ -363,7 +363,7 @@ fn calc_test_vectors_index(conditions: &mut Vec) -> usize { let ConditionInfo { condition_id, true_next_id, false_next_id } = branch.condition_info; [true_next_id, false_next_id] .into_iter() - .filter_map(std::convert::identity) + .flatten() .for_each(|next_id| indegree_stats[next_id] += 1); (condition_id, branch) }) diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index da7d20cf19a68..085c738f1f9fc 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -87,7 +87,7 @@ fn remove_unwanted_expansion_spans(covspans: &mut Vec) { covspans.retain(|covspan| { match covspan.expn_kind { // Retain only the first await-related or macro-expanded covspan with this span. - Some(ExpnKind::Desugaring(kind)) if kind == DesugaringKind::Await => { + Some(ExpnKind::Desugaring(DesugaringKind::Await)) => { deduplicated_spans.insert(covspan.span) } Some(ExpnKind::Macro(MacroKind::Bang, _)) => deduplicated_spans.insert(covspan.span), From 464f4057c28ef3c6ae4acb696ee27f7f3f2112ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 12 Oct 2024 12:59:32 +0200 Subject: [PATCH 11/15] fix some manual_map --- .../src/diagnostics/mutability_errors.rs | 10 +++------- compiler/rustc_hir_typeck/src/method/suggest.rs | 2 +- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index a5f3298b02cc2..315851729b1e0 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -959,13 +959,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { None } } - hir::ExprKind::MethodCall(_, _, args, span) => { - if let Some(def_id) = typeck_results.type_dependent_def_id(*hir_id) { - Some((def_id, *span, *args)) - } else { - None - } - } + hir::ExprKind::MethodCall(_, _, args, span) => typeck_results + .type_dependent_def_id(*hir_id) + .map(|def_id| (def_id, *span, *args)), _ => None, } }; diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 9dd5954114860..eaf40a193a634 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -537,7 +537,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && binding_id != self.binding_id { if self.check_and_add_sugg_binding(LetStmt { - ty_hir_id_opt: if let Some(ty) = ty { Some(ty.hir_id) } else { None }, + ty_hir_id_opt: ty.map(|ty| ty.hir_id), binding_id, span: pat.span, init_hir_id: init.hir_id, From d84d659cb523e1156be8f7657879eb168a3f7fd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 12 Oct 2024 21:38:06 +0200 Subject: [PATCH 12/15] clone range in a more obvious way --- compiler/rustc_infer/src/infer/type_variable.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/compiler/rustc_infer/src/infer/type_variable.rs b/compiler/rustc_infer/src/infer/type_variable.rs index 779ce976becc0..2086483b94a71 100644 --- a/compiler/rustc_infer/src/infer/type_variable.rs +++ b/compiler/rustc_infer/src/infer/type_variable.rs @@ -187,10 +187,7 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> { value_count: usize, ) -> (Range, Vec) { let range = TyVid::from_usize(value_count)..TyVid::from_usize(self.num_vars()); - ( - range.start..range.end, - (range.start..range.end).map(|index| self.var_origin(index)).collect(), - ) + (range.clone(), range.map(|index| self.var_origin(index)).collect()) } /// Returns indices of all variables that are not yet From 4e1b3ab0e7965b8cce016f1ca01cd2df37e11635 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 24 Oct 2024 00:41:27 +0000 Subject: [PATCH 13/15] Print safety correctly in extern static items --- compiler/rustc_ast_pretty/src/pprust/state/item.rs | 7 ++++++- tests/ui/unpretty/extern-static.rs | 6 ++++++ tests/ui/unpretty/extern-static.stdout | 6 ++++++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 tests/ui/unpretty/extern-static.rs create mode 100644 tests/ui/unpretty/extern-static.stdout diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 8217b6df5b470..8279c66836c0f 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -38,7 +38,6 @@ impl<'a> State<'a> { self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs); } ast::ForeignItemKind::Static(box ast::StaticItem { ty, mutability, expr, safety }) => { - self.print_safety(*safety); self.print_item_const( ident, Some(*mutability), @@ -46,6 +45,7 @@ impl<'a> State<'a> { ty, expr.as_deref(), vis, + *safety, ast::Defaultness::Final, ) } @@ -84,10 +84,12 @@ impl<'a> State<'a> { ty: &ast::Ty, body: Option<&ast::Expr>, vis: &ast::Visibility, + safety: ast::Safety, defaultness: ast::Defaultness, ) { self.head(""); self.print_visibility(vis); + self.print_safety(safety); self.print_defaultness(defaultness); let leading = match mutbl { None => "const", @@ -181,6 +183,7 @@ impl<'a> State<'a> { ty, body.as_deref(), &item.vis, + ast::Safety::Default, ast::Defaultness::Final, ); } @@ -192,6 +195,7 @@ impl<'a> State<'a> { ty, expr.as_deref(), &item.vis, + ast::Safety::Default, *defaultness, ); } @@ -549,6 +553,7 @@ impl<'a> State<'a> { ty, expr.as_deref(), vis, + ast::Safety::Default, *defaultness, ); } diff --git a/tests/ui/unpretty/extern-static.rs b/tests/ui/unpretty/extern-static.rs new file mode 100644 index 0000000000000..fbd605b12caec --- /dev/null +++ b/tests/ui/unpretty/extern-static.rs @@ -0,0 +1,6 @@ +//@ compile-flags: -Zunpretty=normal +//@ check-pass + +unsafe extern "C" { + pub unsafe static STATIC: (); +} diff --git a/tests/ui/unpretty/extern-static.stdout b/tests/ui/unpretty/extern-static.stdout new file mode 100644 index 0000000000000..fbd605b12caec --- /dev/null +++ b/tests/ui/unpretty/extern-static.stdout @@ -0,0 +1,6 @@ +//@ compile-flags: -Zunpretty=normal +//@ check-pass + +unsafe extern "C" { + pub unsafe static STATIC: (); +} From 1920c66a8d96978e0d0e5db318fa3e0fb2e0f37e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 15 Oct 2024 15:17:25 -0400 Subject: [PATCH 14/15] Plumb through param_env to note_type_err --- .../src/diagnostics/bound_region_errors.rs | 12 +++---- .../src/region_infer/opaque_types.rs | 1 + .../src/check/compare_impl_item.rs | 15 +++++---- compiler/rustc_hir_analysis/src/check/mod.rs | 4 +-- .../src/coherence/builtin.rs | 1 + compiler/rustc_hir_typeck/src/callee.rs | 4 ++- compiler/rustc_hir_typeck/src/coercion.rs | 6 +++- compiler/rustc_hir_typeck/src/demand.rs | 11 +++++-- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 9 ++++-- .../rustc_hir_typeck/src/method/confirm.rs | 8 ++++- compiler/rustc_passes/src/check_attr.rs | 4 +-- .../src/error_reporting/infer/mod.rs | 31 +++++++++++++++---- .../src/error_reporting/infer/region.rs | 12 +++++-- .../traits/fulfillment_errors.rs | 17 ++++++---- .../src/error_reporting/traits/mod.rs | 2 ++ 15 files changed, 98 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index 2437a43bd5a36..2fa752384a161 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -65,6 +65,7 @@ impl<'tcx> UniverseInfo<'tcx> { UniverseInfoInner::RelateTys { expected, found } => { let err = mbcx.infcx.err_ctxt().report_mismatched_types( &cause, + mbcx.param_env, expected, found, TypeError::RegionsPlaceholderMismatch, @@ -480,12 +481,11 @@ fn try_extract_error_from_region_constraints<'a, 'tcx>( .try_report_from_nll() .or_else(|| { if let SubregionOrigin::Subtype(trace) = cause { - Some( - infcx.err_ctxt().report_and_explain_type_error( - *trace, - TypeError::RegionsPlaceholderMismatch, - ), - ) + Some(infcx.err_ctxt().report_and_explain_type_error( + *trace, + infcx.tcx.param_env(generic_param_scope), + TypeError::RegionsPlaceholderMismatch, + )) } else { None } diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index a16c1931a552b..abce98265b3cb 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -360,6 +360,7 @@ fn check_opaque_type_well_formed<'tcx>( .err_ctxt() .report_mismatched_types( &ObligationCause::misc(definition_span, def_id), + param_env, opaque_ty, definition_ty, err, diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index fc5ec31cda80c..7a56b3784f8b3 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -282,6 +282,7 @@ fn compare_method_predicate_entailment<'tcx>( let emitted = report_trait_method_mismatch( infcx, cause, + param_env, terr, (trait_m, trait_sig), (impl_m, impl_sig), @@ -575,10 +576,10 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( hir.get_if_local(impl_m.def_id) .and_then(|node| node.fn_decl()) .map(|decl| (decl.output.span(), Cow::from("return type in trait"), false)), - Some(infer::ValuePairs::Terms(ExpectedFound { + Some(param_env.and(infer::ValuePairs::Terms(ExpectedFound { expected: trait_return_ty.into(), found: impl_return_ty.into(), - })), + }))), terr, false, ); @@ -602,6 +603,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( let emitted = report_trait_method_mismatch( infcx, cause, + param_env, terr, (trait_m, trait_sig), (impl_m, impl_sig), @@ -915,6 +917,7 @@ impl<'tcx> ty::FallibleTypeFolder> for RemapHiddenTyRegions<'tcx> { fn report_trait_method_mismatch<'tcx>( infcx: &InferCtxt<'tcx>, mut cause: ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, terr: TypeError<'tcx>, (trait_m, trait_sig): (ty::AssocItem, ty::FnSig<'tcx>), (impl_m, impl_sig): (ty::AssocItem, ty::FnSig<'tcx>), @@ -1000,10 +1003,10 @@ fn report_trait_method_mismatch<'tcx>( &mut diag, &cause, trait_err_span.map(|sp| (sp, Cow::from("type in trait"), false)), - Some(infer::ValuePairs::PolySigs(ExpectedFound { + Some(param_env.and(infer::ValuePairs::PolySigs(ExpectedFound { expected: ty::Binder::dummy(trait_sig), found: ty::Binder::dummy(impl_sig), - })), + }))), terr, false, ); @@ -1797,10 +1800,10 @@ fn compare_const_predicate_entailment<'tcx>( &mut diag, &cause, trait_c_span.map(|span| (span, Cow::from("type in trait"), false)), - Some(infer::ValuePairs::Terms(ExpectedFound { + Some(param_env.and(infer::ValuePairs::Terms(ExpectedFound { expected: trait_ty.into(), found: impl_ty.into(), - })), + }))), terr, false, ); diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 959b17b2d4073..f2f9c69e49f70 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -646,10 +646,10 @@ pub fn check_function_signature<'tcx>( &mut diag, &cause, None, - Some(infer::ValuePairs::PolySigs(ExpectedFound { + Some(param_env.and(infer::ValuePairs::PolySigs(ExpectedFound { expected: expected_sig, found: actual_sig, - })), + }))), err, false, ); diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 76c75d976ee0f..b4f6b5a9dd24f 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -364,6 +364,7 @@ pub(crate) fn coerce_unsized_info<'tcx>( .err_ctxt() .report_mismatched_types( &cause, + param_env, mk_ptr(mt_b.ty), target, ty::error::TypeError::Mutability, diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index fa6a86c691188..06e2a5e349340 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -862,7 +862,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } Err(e) => { // FIXME(effects): better diagnostic - self.err_ctxt().report_mismatched_consts(&cause, effect, param, e).emit(); + self.err_ctxt() + .report_mismatched_consts(&cause, self.param_env, effect, param, e) + .emit(); } } } diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index de80ccf790c1b..6fa958d949602 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1723,6 +1723,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { }) => { err = fcx.err_ctxt().report_mismatched_types( cause, + fcx.param_env, expected, found, coercion_error, @@ -1752,6 +1753,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { }) => { err = fcx.err_ctxt().report_mismatched_types( cause, + fcx.param_env, expected, found, coercion_error, @@ -1787,6 +1789,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { _ => { err = fcx.err_ctxt().report_mismatched_types( cause, + fcx.param_env, expected, found, coercion_error, @@ -1897,7 +1900,8 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { block_or_return_id: hir::HirId, expression: Option<&'tcx hir::Expr<'tcx>>, ) -> Diag<'infcx> { - let mut err = fcx.err_ctxt().report_mismatched_types(cause, expected, found, ty_err); + let mut err = + fcx.err_ctxt().report_mismatched_types(cause, fcx.param_env, expected, found, ty_err); let due_to_block = matches!(fcx.tcx.hir_node(block_or_return_id), hir::Node::Block(..)); diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 777248ff873de..3399a9fe88078 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -191,7 +191,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.at(cause, self.param_env) .sup(DefineOpaqueTypes::Yes, expected, actual) .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) - .map_err(|e| self.err_ctxt().report_mismatched_types(cause, expected, actual, e)) + .map_err(|e| { + self.err_ctxt().report_mismatched_types(cause, self.param_env, expected, actual, e) + }) } pub(crate) fn demand_eqtype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) { @@ -218,7 +220,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.at(cause, self.param_env) .eq(DefineOpaqueTypes::Yes, expected, actual) .map(|infer_ok| self.register_infer_ok_obligations(infer_ok)) - .map_err(|e| self.err_ctxt().report_mismatched_types(cause, expected, actual, e)) + .map_err(|e| { + self.err_ctxt().report_mismatched_types(cause, self.param_env, expected, actual, e) + }) } pub(crate) fn demand_coerce( @@ -271,7 +275,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let expr = expr.peel_drop_temps(); let cause = self.misc(expr.span); let expr_ty = self.resolve_vars_if_possible(checked_ty); - let mut err = self.err_ctxt().report_mismatched_types(&cause, expected, expr_ty, e); + let mut err = + self.err_ctxt().report_mismatched_types(&cause, self.param_env, expected, expr_ty, e); self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected, expected_ty_expr, Some(e)); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index f29d6199a875e..a6c249da103f3 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -827,6 +827,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { formal_and_expected_inputs[mismatch_idx.into()], provided_arg_tys[mismatch_idx.into()].0, ), + self.param_env, terr, ); err.span_label( @@ -912,7 +913,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let trace = mk_trace(provided_span, formal_and_expected_inputs[*expected_idx], provided_ty); if !matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308) { - let mut err = self.err_ctxt().report_and_explain_type_error(trace, *e); + let mut err = + self.err_ctxt().report_and_explain_type_error(trace, self.param_env, *e); suggest_confusable(&mut err); reported = Some(err.emit()); return false; @@ -940,7 +942,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (formal_ty, expected_ty) = formal_and_expected_inputs[*expected_idx]; let (provided_ty, provided_arg_span) = provided_arg_tys[*provided_idx]; let trace = mk_trace(provided_arg_span, (formal_ty, expected_ty), provided_ty); - let mut err = self.err_ctxt().report_and_explain_type_error(trace, *err); + let mut err = + self.err_ctxt().report_and_explain_type_error(trace, self.param_env, *err); self.emit_coerce_suggestions( &mut err, provided_args[*provided_idx], @@ -1113,7 +1116,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &mut err, &trace.cause, None, - Some(trace.values), + Some(self.param_env.and(trace.values)), e, true, ); diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index f4685725dd30f..96784fcb61b2c 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -538,7 +538,13 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { // to the feature, like the self type can't reference method args. if self.tcx.features().arbitrary_self_types() { self.err_ctxt() - .report_mismatched_types(&cause, method_self_ty, self_ty, terr) + .report_mismatched_types( + &cause, + self.param_env, + method_self_ty, + self_ty, + terr, + ) .emit(); } else { // This has/will have errored in wfcheck, which we cannot depend on from here, as typeck on functions diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 8644284482385..61e196bdebe66 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -2300,10 +2300,10 @@ impl<'tcx> CheckAttrVisitor<'tcx> { &mut diag, &cause, None, - Some(ValuePairs::PolySigs(ExpectedFound { + Some(param_env.and(ValuePairs::PolySigs(ExpectedFound { expected: ty::Binder::dummy(expected_sig), found: ty::Binder::dummy(sig), - })), + }))), terr, false, ); diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index df5800ab58a66..fd991100879b4 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -75,6 +75,7 @@ use crate::errors::{ObligationCauseFailureCode, TypeErrorAdditionalDiags}; use crate::infer; use crate::infer::relate::{self, RelateResult, TypeRelation}; use crate::infer::{InferCtxt, TypeTrace, ValuePairs}; +use crate::solve::deeply_normalize_for_diagnostics; use crate::traits::{ IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode, }; @@ -145,21 +146,31 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { pub fn report_mismatched_types( &self, cause: &ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, expected: Ty<'tcx>, actual: Ty<'tcx>, err: TypeError<'tcx>, ) -> Diag<'a> { - self.report_and_explain_type_error(TypeTrace::types(cause, true, expected, actual), err) + self.report_and_explain_type_error( + TypeTrace::types(cause, true, expected, actual), + param_env, + err, + ) } pub fn report_mismatched_consts( &self, cause: &ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, expected: ty::Const<'tcx>, actual: ty::Const<'tcx>, err: TypeError<'tcx>, ) -> Diag<'a> { - self.report_and_explain_type_error(TypeTrace::consts(cause, true, expected, actual), err) + self.report_and_explain_type_error( + TypeTrace::consts(cause, true, expected, actual), + param_env, + err, + ) } pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option> { @@ -1133,7 +1144,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { diag: &mut Diag<'_>, cause: &ObligationCause<'tcx>, secondary_span: Option<(Span, Cow<'static, str>, bool)>, - mut values: Option>, + mut values: Option>>, terr: TypeError<'tcx>, prefer_label: bool, ) { @@ -1241,8 +1252,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } let (expected_found, exp_found, is_simple_error, values) = match values { None => (None, Mismatch::Fixed("type"), false, None), - Some(values) => { - let values = self.resolve_vars_if_possible(values); + Some(ty::ParamEnvAnd { param_env: _, value: values }) => { + let mut values = self.resolve_vars_if_possible(values); let (is_simple_error, exp_found) = match values { ValuePairs::Terms(ExpectedFound { expected, found }) => { match (expected.unpack(), found.unpack()) { @@ -1773,6 +1784,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { pub fn report_and_explain_type_error( &self, trace: TypeTrace<'tcx>, + param_env: ty::ParamEnv<'tcx>, terr: TypeError<'tcx>, ) -> Diag<'a> { debug!("report_and_explain_type_error(trace={:?}, terr={:?})", trace, terr); @@ -1784,7 +1796,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { self.type_error_additional_suggestions(&trace, terr), ); let mut diag = self.dcx().create_err(failure_code); - self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr, false); + self.note_type_err( + &mut diag, + &trace.cause, + None, + Some(param_env.and(trace.values)), + terr, + false, + ); diag } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index 94610a9e0e653..833358b2e14d2 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -295,7 +295,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let mut err = match origin { infer::Subtype(box trace) => { let terr = TypeError::RegionsDoesNotOutlive(sup, sub); - let mut err = self.report_and_explain_type_error(trace, terr); + let mut err = self.report_and_explain_type_error( + trace, + self.tcx.param_env(generic_param_scope), + terr, + ); match (*sub, *sup) { (ty::RePlaceholder(_), ty::RePlaceholder(_)) => {} (ty::RePlaceholder(_), _) => { @@ -646,7 +650,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } infer::Subtype(box trace) => { let terr = TypeError::RegionsPlaceholderMismatch; - return self.report_and_explain_type_error(trace, terr); + return self.report_and_explain_type_error( + trace, + self.tcx.param_env(generic_param_scope), + terr, + ); } _ => { return self.report_concrete_failure( diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 9ee4963a3603b..6ef64c3ed80a8 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1290,7 +1290,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ( Some(( data.projection_term, - false, self.resolve_vars_if_possible(normalized_term), data.term, )), @@ -1335,7 +1334,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { derive_better_type_error(lhs, rhs) { ( - Some((lhs, true, self.resolve_vars_if_possible(expected_term), rhs)), + Some((lhs, self.resolve_vars_if_possible(expected_term), rhs)), better_type_err, ) } else if let Some(rhs) = rhs.to_alias_term() @@ -1343,7 +1342,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { derive_better_type_error(rhs, lhs) { ( - Some((rhs, true, self.resolve_vars_if_possible(expected_term), lhs)), + Some((rhs, self.resolve_vars_if_possible(expected_term), lhs)), better_type_err, ) } else { @@ -1354,7 +1353,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }; let msg = values - .and_then(|(predicate, _, normalized_term, expected_term)| { + .and_then(|(predicate, normalized_term, expected_term)| { self.maybe_detailed_projection_msg(predicate, normalized_term, expected_term) }) .unwrap_or_else(|| { @@ -1431,8 +1430,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { &mut diag, &obligation.cause, secondary_span, - values.map(|(_, _, normalized_ty, expected_ty)| { - infer::ValuePairs::Terms(ExpectedFound::new(true, expected_ty, normalized_ty)) + values.map(|(_, normalized_ty, expected_ty)| { + obligation.param_env.and(infer::ValuePairs::Terms(ExpectedFound::new( + true, + expected_ty, + normalized_ty, + ))) }), err, false, @@ -2654,6 +2657,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }; self.report_and_explain_type_error( TypeTrace::trait_refs(&cause, true, expected_trait_ref, found_trait_ref), + obligation.param_env, terr, ) } @@ -2744,6 +2748,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { { return Ok(self.report_and_explain_type_error( TypeTrace::trait_refs(&obligation.cause, true, expected_trait_ref, found_trait_ref), + obligation.param_env, ty::error::TypeError::Mismatch, )); } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs index ba57909fc23a6..ca23f7765819f 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs @@ -287,6 +287,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { FulfillmentErrorCode::Subtype(ref expected_found, ref err) => self .report_mismatched_types( &error.obligation.cause, + error.obligation.param_env, expected_found.expected, expected_found.found, *err, @@ -295,6 +296,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { FulfillmentErrorCode::ConstEquate(ref expected_found, ref err) => { let mut diag = self.report_mismatched_consts( &error.obligation.cause, + error.obligation.param_env, expected_found.expected, expected_found.found, *err, From 4217b8702dcd4e45ea506dd0fc8e1cec6115d52a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 15 Oct 2024 15:24:22 -0400 Subject: [PATCH 15/15] Deeply normalize type trace in type error reporting --- .../src/error_reporting/infer/mod.rs | 5 ++++- .../deeply-normalize-type-expectation.rs | 17 +++++++++++++++++ .../deeply-normalize-type-expectation.stderr | 17 +++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 tests/ui/traits/next-solver/diagnostics/deeply-normalize-type-expectation.rs create mode 100644 tests/ui/traits/next-solver/diagnostics/deeply-normalize-type-expectation.stderr diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index fd991100879b4..b9a569d25e324 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -1252,8 +1252,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } let (expected_found, exp_found, is_simple_error, values) = match values { None => (None, Mismatch::Fixed("type"), false, None), - Some(ty::ParamEnvAnd { param_env: _, value: values }) => { + Some(ty::ParamEnvAnd { param_env, value: values }) => { let mut values = self.resolve_vars_if_possible(values); + if self.next_trait_solver() { + values = deeply_normalize_for_diagnostics(self, param_env, values); + } let (is_simple_error, exp_found) = match values { ValuePairs::Terms(ExpectedFound { expected, found }) => { match (expected.unpack(), found.unpack()) { diff --git a/tests/ui/traits/next-solver/diagnostics/deeply-normalize-type-expectation.rs b/tests/ui/traits/next-solver/diagnostics/deeply-normalize-type-expectation.rs new file mode 100644 index 0000000000000..5c53b745933b5 --- /dev/null +++ b/tests/ui/traits/next-solver/diagnostics/deeply-normalize-type-expectation.rs @@ -0,0 +1,17 @@ +//@ compile-flags: -Znext-solver + +// Make sure we try to mention a deeply normalized type in a type mismatch error. + +trait Mirror { + type Assoc; +} +impl Mirror for T { + type Assoc = T; +} + +fn needs(_: ::Assoc) {} + +fn main() { + needs::(()); + //~^ ERROR mismatched types +} diff --git a/tests/ui/traits/next-solver/diagnostics/deeply-normalize-type-expectation.stderr b/tests/ui/traits/next-solver/diagnostics/deeply-normalize-type-expectation.stderr new file mode 100644 index 0000000000000..88643945863d5 --- /dev/null +++ b/tests/ui/traits/next-solver/diagnostics/deeply-normalize-type-expectation.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/deeply-normalize-type-expectation.rs:15:18 + | +LL | needs::(()); + | ------------ ^^ expected `i32`, found `()` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/deeply-normalize-type-expectation.rs:12:4 + | +LL | fn needs(_: ::Assoc) {} + | ^^^^^ ----------------------- + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`.