From 04e7a10af68e6174e42e9ce4a6e81f97722a6032 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 4 Feb 2025 15:15:28 +0100 Subject: [PATCH 01/22] intrinsics: unify rint, roundeven, nearbyint in a single round_ties_even intrinsic --- .../src/intrinsics/mod.rs | 16 +- .../rustc_codegen_gcc/src/intrinsic/mod.rs | 9 +- compiler/rustc_codegen_llvm/src/intrinsic.rs | 22 +-- .../rustc_hir_analysis/src/check/intrinsic.rs | 18 +- compiler/rustc_span/src/symbol.rs | 16 +- library/core/src/intrinsics/mod.rs | 185 +++++++----------- library/std/src/f128.rs | 2 +- library/std/src/f16.rs | 2 +- library/std/src/f32.rs | 2 +- library/std/src/f64.rs | 2 +- src/tools/miri/src/intrinsics/mod.rs | 16 +- tests/codegen/intrinsics/nearby.rs | 18 -- tests/ui/intrinsics/intrinsic-nearby.rs | 11 -- 13 files changed, 111 insertions(+), 208 deletions(-) delete mode 100644 tests/codegen/intrinsics/nearby.rs delete mode 100644 tests/ui/intrinsics/intrinsic-nearby.rs diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 26f14532b458e..4d9bed8652cbd 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -340,14 +340,10 @@ fn codegen_float_intrinsic_call<'tcx>( sym::ceilf64 => ("ceil", 1, fx.tcx.types.f64, types::F64), sym::truncf32 => ("truncf", 1, fx.tcx.types.f32, types::F32), sym::truncf64 => ("trunc", 1, fx.tcx.types.f64, types::F64), - sym::rintf32 => ("rintf", 1, fx.tcx.types.f32, types::F32), - sym::rintf64 => ("rint", 1, fx.tcx.types.f64, types::F64), + sym::round_ties_even_f32 => ("rintf", 1, fx.tcx.types.f32, types::F32), + sym::round_ties_even_f64 => ("rint", 1, fx.tcx.types.f64, types::F64), sym::roundf32 => ("roundf", 1, fx.tcx.types.f32, types::F32), sym::roundf64 => ("round", 1, fx.tcx.types.f64, types::F64), - sym::roundevenf32 => ("roundevenf", 1, fx.tcx.types.f32, types::F32), - sym::roundevenf64 => ("roundeven", 1, fx.tcx.types.f64, types::F64), - sym::nearbyintf32 => ("nearbyintf", 1, fx.tcx.types.f32, types::F32), - sym::nearbyintf64 => ("nearbyint", 1, fx.tcx.types.f64, types::F64), sym::sinf32 => ("sinf", 1, fx.tcx.types.f32, types::F32), sym::sinf64 => ("sin", 1, fx.tcx.types.f64, types::F64), sym::cosf32 => ("cosf", 1, fx.tcx.types.f32, types::F32), @@ -399,8 +395,8 @@ fn codegen_float_intrinsic_call<'tcx>( | sym::ceilf64 | sym::truncf32 | sym::truncf64 - | sym::nearbyintf32 - | sym::nearbyintf64 + | sym::round_ties_even_f32 + | sym::round_ties_even_f64 | sym::sqrtf32 | sym::sqrtf64 => { let val = match intrinsic { @@ -408,7 +404,9 @@ fn codegen_float_intrinsic_call<'tcx>( sym::floorf32 | sym::floorf64 => fx.bcx.ins().floor(args[0]), sym::ceilf32 | sym::ceilf64 => fx.bcx.ins().ceil(args[0]), sym::truncf32 | sym::truncf64 => fx.bcx.ins().trunc(args[0]), - sym::nearbyintf32 | sym::nearbyintf64 => fx.bcx.ins().nearest(args[0]), + sym::round_ties_even_f32 | sym::round_ties_even_f64 => { + fx.bcx.ins().nearest(args[0]) + } sym::sqrtf32 | sym::sqrtf64 => fx.bcx.ins().sqrt(args[0]), _ => unreachable!(), }; diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 48606f5f91c0f..83d0db0fb54a9 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -84,14 +84,11 @@ fn get_simple_intrinsic<'gcc, 'tcx>( sym::ceilf64 => "ceil", sym::truncf32 => "truncf", sym::truncf64 => "trunc", - sym::rintf32 => "rintf", - sym::rintf64 => "rint", - sym::nearbyintf32 => "nearbyintf", - sym::nearbyintf64 => "nearbyint", + // We match the LLVM backend and lower this to `rint`. + sym::round_ties_even_f32 => "rintf", + sym::round_ties_even_f64 => "rint", sym::roundf32 => "roundf", sym::roundf64 => "round", - sym::roundevenf32 => "roundevenf", - sym::roundevenf64 => "roundeven", sym::abort => "abort", _ => return None, }; diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 43d6ccfcb4a28..464a6ce434d1e 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -126,15 +126,14 @@ fn get_simple_intrinsic<'ll>( sym::truncf64 => "llvm.trunc.f64", sym::truncf128 => "llvm.trunc.f128", - sym::rintf16 => "llvm.rint.f16", - sym::rintf32 => "llvm.rint.f32", - sym::rintf64 => "llvm.rint.f64", - sym::rintf128 => "llvm.rint.f128", - - sym::nearbyintf16 => "llvm.nearbyint.f16", - sym::nearbyintf32 => "llvm.nearbyint.f32", - sym::nearbyintf64 => "llvm.nearbyint.f64", - sym::nearbyintf128 => "llvm.nearbyint.f128", + // We could use any of `rint`, `nearbyint`, or `roundeven` + // for this -- they are all identical in semantics when + // assuming the default FP environment. + // `rint` is what we used for $forever. + sym::round_ties_even_f16 => "llvm.rint.f16", + sym::round_ties_even_f32 => "llvm.rint.f32", + sym::round_ties_even_f64 => "llvm.rint.f64", + sym::round_ties_even_f128 => "llvm.rint.f128", sym::roundf16 => "llvm.round.f16", sym::roundf32 => "llvm.round.f32", @@ -143,11 +142,6 @@ fn get_simple_intrinsic<'ll>( sym::ptr_mask => "llvm.ptrmask", - sym::roundevenf16 => "llvm.roundeven.f16", - sym::roundevenf32 => "llvm.roundeven.f32", - sym::roundevenf64 => "llvm.roundeven.f64", - sym::roundevenf128 => "llvm.roundeven.f128", - _ => return None, }; Some(cx.get_intrinsic(llvm_name)) diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index cf3d489730425..acdd2facc24dc 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -398,26 +398,16 @@ pub fn check_intrinsic_type( sym::truncf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64), sym::truncf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128), - sym::rintf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16), - sym::rintf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32), - sym::rintf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64), - sym::rintf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128), - - sym::nearbyintf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16), - sym::nearbyintf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32), - sym::nearbyintf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64), - sym::nearbyintf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128), + sym::round_ties_even_f16 => (0, 0, vec![tcx.types.f16], tcx.types.f16), + sym::round_ties_even_f32 => (0, 0, vec![tcx.types.f32], tcx.types.f32), + sym::round_ties_even_f64 => (0, 0, vec![tcx.types.f64], tcx.types.f64), + sym::round_ties_even_f128 => (0, 0, vec![tcx.types.f128], tcx.types.f128), sym::roundf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16), sym::roundf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32), sym::roundf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64), sym::roundf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128), - sym::roundevenf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16), - sym::roundevenf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32), - sym::roundevenf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64), - sym::roundevenf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128), - sym::volatile_load | sym::unaligned_volatile_load => { (1, 0, vec![Ty::new_imm_ptr(tcx, param(0))], param(0)) } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 382b12638f43f..0188327fd8235 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1337,10 +1337,6 @@ symbols! { native_link_modifiers_whole_archive, natvis_file, ne, - nearbyintf128, - nearbyintf16, - nearbyintf32, - nearbyintf64, needs_allocator, needs_drop, needs_panic_runtime, @@ -1655,20 +1651,16 @@ symbols! { return_position_impl_trait_in_trait, return_type_notation, rhs, - rintf128, - rintf16, - rintf32, - rintf64, riscv_target_feature, rlib, ropi, ropi_rwpi: "ropi-rwpi", rotate_left, rotate_right, - roundevenf128, - roundevenf16, - roundevenf32, - roundevenf64, + round_ties_even_f128, + round_ties_even_f16, + round_ties_even_f32, + round_ties_even_f64, roundf128, roundf16, roundf32, diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index bf07632d9928b..320122a53e9dd 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -2739,110 +2739,112 @@ pub unsafe fn truncf128(_x: f128) -> f128 { unreachable!() } -/// Returns the nearest integer to an `f16`. Changing the rounding mode is not possible in Rust, -/// so this rounds half-way cases to the number with an even least significant digit. -/// -/// May raise an inexact floating-point exception if the argument is not an integer. -/// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions -/// cannot actually be utilized from Rust code. -/// In other words, this intrinsic is equivalent in behavior to `nearbyintf16` and `roundevenf16`. +/// Returns the nearest integer to an `f16`. Rounds half-way cases to the number with an even +/// least significant digit. /// /// The stabilized version of this intrinsic is /// [`f16::round_ties_even`](../../std/primitive.f16.html#method.round_ties_even) #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] #[rustc_nounwind] -pub unsafe fn rintf16(_x: f16) -> f16 { +#[cfg(not(bootstrap))] +pub unsafe fn round_ties_even_f16(_x: f16) -> f16 { unreachable!() } -/// Returns the nearest integer to an `f32`. Changing the rounding mode is not possible in Rust, -/// so this rounds half-way cases to the number with an even least significant digit. -/// -/// May raise an inexact floating-point exception if the argument is not an integer. -/// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions -/// cannot actually be utilized from Rust code. -/// In other words, this intrinsic is equivalent in behavior to `nearbyintf32` and `roundevenf32`. + +/// To be removed on next bootstrap bump. +#[cfg(bootstrap)] +pub unsafe fn round_ties_even_f16(x: f16) -> f16 { + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + #[rustc_nounwind] + unsafe fn rintf16(_x: f16) -> f16 { + unreachable!() + } + + // SAFETY: this intrinsic isn't actually unsafe + unsafe { rintf16(x) } +} + +/// Returns the nearest integer to an `f32`. Rounds half-way cases to the number with an even +/// least significant digit. /// /// The stabilized version of this intrinsic is /// [`f32::round_ties_even`](../../std/primitive.f32.html#method.round_ties_even) #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] #[rustc_nounwind] -pub unsafe fn rintf32(_x: f32) -> f32 { +#[cfg(not(bootstrap))] +pub unsafe fn round_ties_even_f32(_x: f32) -> f32 { unreachable!() } -/// Returns the nearest integer to an `f64`. Changing the rounding mode is not possible in Rust, -/// so this rounds half-way cases to the number with an even least significant digit. -/// -/// May raise an inexact floating-point exception if the argument is not an integer. -/// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions -/// cannot actually be utilized from Rust code. -/// In other words, this intrinsic is equivalent in behavior to `nearbyintf64` and `roundevenf64`. + +/// To be removed on next bootstrap bump. +#[cfg(bootstrap)] +pub unsafe fn round_ties_even_f32(x: f32) -> f32 { + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + #[rustc_nounwind] + unsafe fn rintf32(_x: f32) -> f32 { + unreachable!() + } + + // SAFETY: this intrinsic isn't actually unsafe + unsafe { rintf32(x) } +} + +/// Returns the nearest integer to an `f64`. Rounds half-way cases to the number with an even +/// least significant digit. /// /// The stabilized version of this intrinsic is /// [`f64::round_ties_even`](../../std/primitive.f64.html#method.round_ties_even) #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] #[rustc_nounwind] -pub unsafe fn rintf64(_x: f64) -> f64 { +#[cfg(not(bootstrap))] +pub unsafe fn round_ties_even_f64(_x: f64) -> f64 { unreachable!() } -/// Returns the nearest integer to an `f128`. Changing the rounding mode is not possible in Rust, -/// so this rounds half-way cases to the number with an even least significant digit. -/// -/// May raise an inexact floating-point exception if the argument is not an integer. -/// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions -/// cannot actually be utilized from Rust code. -/// In other words, this intrinsic is equivalent in behavior to `nearbyintf128` and `roundevenf128`. + +/// To be removed on next bootstrap bump. +#[cfg(bootstrap)] +pub unsafe fn round_ties_even_f64(x: f64) -> f64 { + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + #[rustc_nounwind] + unsafe fn rintf64(_x: f64) -> f64 { + unreachable!() + } + + // SAFETY: this intrinsic isn't actually unsafe + unsafe { rintf64(x) } +} + +/// Returns the nearest integer to an `f128`. Rounds half-way cases to the number with an even +/// least significant digit. /// /// The stabilized version of this intrinsic is /// [`f128::round_ties_even`](../../std/primitive.f128.html#method.round_ties_even) #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] #[rustc_nounwind] -pub unsafe fn rintf128(_x: f128) -> f128 { +#[cfg(not(bootstrap))] +pub unsafe fn round_ties_even_f128(_x: f128) -> f128 { unreachable!() } -/// Returns the nearest integer to an `f16`. Changing the rounding mode is not possible in Rust, -/// so this rounds half-way cases to the number with an even least significant digit. -/// -/// This intrinsic does not have a stable counterpart. -#[rustc_intrinsic] -#[rustc_intrinsic_must_be_overridden] -#[rustc_nounwind] -pub unsafe fn nearbyintf16(_x: f16) -> f16 { - unreachable!() -} -/// Returns the nearest integer to an `f32`. Changing the rounding mode is not possible in Rust, -/// so this rounds half-way cases to the number with an even least significant digit. -/// -/// This intrinsic does not have a stable counterpart. -#[rustc_intrinsic] -#[rustc_intrinsic_must_be_overridden] -#[rustc_nounwind] -pub unsafe fn nearbyintf32(_x: f32) -> f32 { - unreachable!() -} -/// Returns the nearest integer to an `f64`. Changing the rounding mode is not possible in Rust, -/// so this rounds half-way cases to the number with an even least significant digit. -/// -/// This intrinsic does not have a stable counterpart. -#[rustc_intrinsic] -#[rustc_intrinsic_must_be_overridden] -#[rustc_nounwind] -pub unsafe fn nearbyintf64(_x: f64) -> f64 { - unreachable!() -} -/// Returns the nearest integer to an `f128`. Changing the rounding mode is not possible in Rust, -/// so this rounds half-way cases to the number with an even least significant digit. -/// -/// This intrinsic does not have a stable counterpart. -#[rustc_intrinsic] -#[rustc_intrinsic_must_be_overridden] -#[rustc_nounwind] -pub unsafe fn nearbyintf128(_x: f128) -> f128 { - unreachable!() +/// To be removed on next bootstrap bump. +#[cfg(bootstrap)] +pub unsafe fn round_ties_even_f128(x: f128) -> f128 { + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + #[rustc_nounwind] + unsafe fn rintf128(_x: f128) -> f128 { + unreachable!() + } + + // SAFETY: this intrinsic isn't actually unsafe + unsafe { rintf128(x) } } /// Returns the nearest integer to an `f16`. Rounds half-way cases away from zero. @@ -2886,47 +2888,6 @@ pub unsafe fn roundf128(_x: f128) -> f128 { unreachable!() } -/// Returns the nearest integer to an `f16`. Rounds half-way cases to the number -/// with an even least significant digit. -/// -/// This intrinsic does not have a stable counterpart. -#[rustc_intrinsic] -#[rustc_intrinsic_must_be_overridden] -#[rustc_nounwind] -pub unsafe fn roundevenf16(_x: f16) -> f16 { - unreachable!() -} -/// Returns the nearest integer to an `f32`. Rounds half-way cases to the number -/// with an even least significant digit. -/// -/// This intrinsic does not have a stable counterpart. -#[rustc_intrinsic] -#[rustc_intrinsic_must_be_overridden] -#[rustc_nounwind] -pub unsafe fn roundevenf32(_x: f32) -> f32 { - unreachable!() -} -/// Returns the nearest integer to an `f64`. Rounds half-way cases to the number -/// with an even least significant digit. -/// -/// This intrinsic does not have a stable counterpart. -#[rustc_intrinsic] -#[rustc_intrinsic_must_be_overridden] -#[rustc_nounwind] -pub unsafe fn roundevenf64(_x: f64) -> f64 { - unreachable!() -} -/// Returns the nearest integer to an `f128`. Rounds half-way cases to the number -/// with an even least significant digit. -/// -/// This intrinsic does not have a stable counterpart. -#[rustc_intrinsic] -#[rustc_intrinsic_must_be_overridden] -#[rustc_nounwind] -pub unsafe fn roundevenf128(_x: f128) -> f128 { - unreachable!() -} - /// Float addition that allows optimizations based on algebraic rules. /// May assume inputs are finite. /// diff --git a/library/std/src/f128.rs b/library/std/src/f128.rs index d65f5ed61cfbc..615c4fd334846 100644 --- a/library/std/src/f128.rs +++ b/library/std/src/f128.rs @@ -129,7 +129,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn round_ties_even(self) -> f128 { - unsafe { intrinsics::rintf128(self) } + unsafe { intrinsics::round_ties_even_f128(self) } } /// Returns the integer part of `self`. diff --git a/library/std/src/f16.rs b/library/std/src/f16.rs index 5b0903bceabb4..85b82b91fabc3 100644 --- a/library/std/src/f16.rs +++ b/library/std/src/f16.rs @@ -129,7 +129,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn round_ties_even(self) -> f16 { - unsafe { intrinsics::rintf16(self) } + unsafe { intrinsics::round_ties_even_f16(self) } } /// Returns the integer part of `self`. diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index f9b6723788ae3..da1f000278dad 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -125,7 +125,7 @@ impl f32 { #[stable(feature = "round_ties_even", since = "1.77.0")] #[inline] pub fn round_ties_even(self) -> f32 { - unsafe { intrinsics::rintf32(self) } + unsafe { intrinsics::round_ties_even_f32(self) } } /// Returns the integer part of `self`. diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index 0de55a15d48e8..8a9f693a7a821 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -125,7 +125,7 @@ impl f64 { #[stable(feature = "round_ties_even", since = "1.77.0")] #[inline] pub fn round_ties_even(self) -> f64 { - unsafe { intrinsics::rintf64(self) } + unsafe { intrinsics::round_ties_even_f64(self) } } /// Returns the integer part of `self`. diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index bce78adcaea45..0faad0f7621a5 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -145,7 +145,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(Scalar::from_bool(branch), dest)?; } - "floorf16" | "ceilf16" | "truncf16" | "roundf16" | "rintf16" => { + "floorf16" | "ceilf16" | "truncf16" | "roundf16" | "round_ties_even_f16" => { let [f] = check_arg_count(args)?; let f = this.read_scalar(f)?.to_f16()?; let mode = match intrinsic_name { @@ -153,14 +153,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "ceilf16" => Round::TowardPositive, "truncf16" => Round::TowardZero, "roundf16" => Round::NearestTiesToAway, - "rintf16" => Round::NearestTiesToEven, + "round_ties_even_f16" => Round::NearestTiesToEven, _ => bug!(), }; let res = f.round_to_integral(mode).value; let res = this.adjust_nan(res, &[f]); this.write_scalar(res, dest)?; } - "floorf32" | "ceilf32" | "truncf32" | "roundf32" | "rintf32" => { + "floorf32" | "ceilf32" | "truncf32" | "roundf32" | "round_ties_even_f32" => { let [f] = check_arg_count(args)?; let f = this.read_scalar(f)?.to_f32()?; let mode = match intrinsic_name { @@ -168,14 +168,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "ceilf32" => Round::TowardPositive, "truncf32" => Round::TowardZero, "roundf32" => Round::NearestTiesToAway, - "rintf32" => Round::NearestTiesToEven, + "round_ties_even_f32" => Round::NearestTiesToEven, _ => bug!(), }; let res = f.round_to_integral(mode).value; let res = this.adjust_nan(res, &[f]); this.write_scalar(res, dest)?; } - "floorf64" | "ceilf64" | "truncf64" | "roundf64" | "rintf64" => { + "floorf64" | "ceilf64" | "truncf64" | "roundf64" | "round_ties_even_f64" => { let [f] = check_arg_count(args)?; let f = this.read_scalar(f)?.to_f64()?; let mode = match intrinsic_name { @@ -183,14 +183,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "ceilf64" => Round::TowardPositive, "truncf64" => Round::TowardZero, "roundf64" => Round::NearestTiesToAway, - "rintf64" => Round::NearestTiesToEven, + "round_ties_even_f64" => Round::NearestTiesToEven, _ => bug!(), }; let res = f.round_to_integral(mode).value; let res = this.adjust_nan(res, &[f]); this.write_scalar(res, dest)?; } - "floorf128" | "ceilf128" | "truncf128" | "roundf128" | "rintf128" => { + "floorf128" | "ceilf128" | "truncf128" | "roundf128" | "round_ties_even_f128" => { let [f] = check_arg_count(args)?; let f = this.read_scalar(f)?.to_f128()?; let mode = match intrinsic_name { @@ -198,7 +198,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "ceilf128" => Round::TowardPositive, "truncf128" => Round::TowardZero, "roundf128" => Round::NearestTiesToAway, - "rintf128" => Round::NearestTiesToEven, + "round_ties_even_f128" => Round::NearestTiesToEven, _ => bug!(), }; let res = f.round_to_integral(mode).value; diff --git a/tests/codegen/intrinsics/nearby.rs b/tests/codegen/intrinsics/nearby.rs deleted file mode 100644 index 520fe2f1886eb..0000000000000 --- a/tests/codegen/intrinsics/nearby.rs +++ /dev/null @@ -1,18 +0,0 @@ -#![crate_type = "lib"] -#![feature(core_intrinsics)] - -use std::intrinsics; - -// CHECK-LABEL: @nearbyintf32 -#[no_mangle] -pub unsafe fn nearbyintf32(a: f32) -> f32 { - // CHECK: llvm.nearbyint.f32 - intrinsics::nearbyintf32(a) -} - -// CHECK-LABEL: @nearbyintf64 -#[no_mangle] -pub unsafe fn nearbyintf64(a: f64) -> f64 { - // CHECK: llvm.nearbyint.f64 - intrinsics::nearbyintf64(a) -} diff --git a/tests/ui/intrinsics/intrinsic-nearby.rs b/tests/ui/intrinsics/intrinsic-nearby.rs deleted file mode 100644 index 990ecfc2b70d0..0000000000000 --- a/tests/ui/intrinsics/intrinsic-nearby.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ run-pass -#![feature(core_intrinsics)] - -use std::intrinsics::*; - -fn main() { - unsafe { - assert_eq!(nearbyintf32(5.234f32), 5f32); - assert_eq!(nearbyintf64(6.777f64), 7f64); - } -} From 92fd960ca4144d43f5753019d950193cba9d4194 Mon Sep 17 00:00:00 2001 From: bendn Date: Sun, 16 Feb 2025 17:18:53 +0700 Subject: [PATCH 02/22] stabilize (const_)ptr_sub_ptr --- compiler/rustc_serialize/src/lib.rs | 1 - library/alloc/src/lib.rs | 1 - library/core/src/intrinsics/mod.rs | 1 + library/core/src/ptr/const_ptr.rs | 11 +++----- library/core/src/ptr/mut_ptr.rs | 11 +++----- library/core/src/ptr/non_null.rs | 10 +++---- .../ptr_offset_from_unsigned_neg.rs | 2 -- src/tools/miri/tests/pass/ptr_offset.rs | 1 - tests/ui/consts/offset_from.rs | 3 -- tests/ui/consts/offset_from_ub.rs | 1 - tests/ui/consts/offset_from_ub.stderr | 28 +++++++++---------- 11 files changed, 27 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs index 47f72298e22ce..9e9b78cfdd57c 100644 --- a/compiler/rustc_serialize/src/lib.rs +++ b/compiler/rustc_serialize/src/lib.rs @@ -13,7 +13,6 @@ #![feature(core_intrinsics)] #![feature(min_specialization)] #![feature(never_type)] -#![feature(ptr_sub_ptr)] #![feature(rustdoc_internals)] #![warn(unreachable_pub)] // tidy-alphabetical-end diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 1bb0f76106472..6e4612b709cae 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -136,7 +136,6 @@ #![feature(pointer_like_trait)] #![feature(ptr_internals)] #![feature(ptr_metadata)] -#![feature(ptr_sub_ptr)] #![feature(set_ptr_value)] #![feature(sized_type_properties)] #![feature(slice_from_ptr_range)] diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 99c42f3626e7c..7cc604901ef00 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -3675,6 +3675,7 @@ pub const unsafe fn ptr_offset_from(_ptr: *const T, _base: *const T) -> isize #[rustc_nounwind] #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] +#[rustc_intrinsic_const_stable_indirect] pub const unsafe fn ptr_offset_from_unsigned(_ptr: *const T, _base: *const T) -> usize { unimplemented!() } diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 974946a7818d7..14693de0ae010 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -723,7 +723,6 @@ impl *const T { /// to [`sub`](#method.sub)). The following are all equivalent, assuming /// that their safety preconditions are met: /// ```rust - /// # #![feature(ptr_sub_ptr)] /// # unsafe fn blah(ptr: *const i32, origin: *const i32, count: usize) -> bool { unsafe { /// ptr.sub_ptr(origin) == count /// # && @@ -752,8 +751,6 @@ impl *const T { /// # Examples /// /// ``` - /// #![feature(ptr_sub_ptr)] - /// /// let a = [0; 5]; /// let ptr1: *const i32 = &a[1]; /// let ptr2: *const i32 = &a[3]; @@ -767,8 +764,8 @@ impl *const T { /// // This would be incorrect, as the pointers are not correctly ordered: /// // ptr1.sub_ptr(ptr2) /// ``` - #[unstable(feature = "ptr_sub_ptr", issue = "95892")] - #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")] + #[stable(feature = "ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn sub_ptr(self, origin: *const T) -> usize @@ -812,8 +809,8 @@ impl *const T { /// /// For non-`Sized` pointees this operation considers only the data pointers, /// ignoring the metadata. - #[unstable(feature = "ptr_sub_ptr", issue = "95892")] - #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")] + #[stable(feature = "ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn byte_sub_ptr(self, origin: *const U) -> usize { diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 94ebd0d2522ee..6f9019ae08848 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -895,7 +895,6 @@ impl *mut T { /// to [`sub`](#method.sub)). The following are all equivalent, assuming /// that their safety preconditions are met: /// ```rust - /// # #![feature(ptr_sub_ptr)] /// # unsafe fn blah(ptr: *mut i32, origin: *mut i32, count: usize) -> bool { unsafe { /// ptr.sub_ptr(origin) == count /// # && @@ -924,8 +923,6 @@ impl *mut T { /// # Examples /// /// ``` - /// #![feature(ptr_sub_ptr)] - /// /// let mut a = [0; 5]; /// let p: *mut i32 = a.as_mut_ptr(); /// unsafe { @@ -940,8 +937,8 @@ impl *mut T { /// /// // This would be incorrect, as the pointers are not correctly ordered: /// // ptr1.offset_from(ptr2) - #[unstable(feature = "ptr_sub_ptr", issue = "95892")] - #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")] + #[stable(feature = "ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn sub_ptr(self, origin: *const T) -> usize @@ -962,8 +959,8 @@ impl *mut T { /// /// For non-`Sized` pointees this operation considers only the data pointers, /// ignoring the metadata. - #[unstable(feature = "ptr_sub_ptr", issue = "95892")] - #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")] + #[stable(feature = "ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const unsafe fn byte_sub_ptr(self, origin: *mut U) -> usize { diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index f4ac00062d733..befb3ccb14be5 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -856,7 +856,6 @@ impl NonNull { /// to [`sub`](#method.sub)). The following are all equivalent, assuming /// that their safety preconditions are met: /// ```rust - /// # #![feature(ptr_sub_ptr)] /// # unsafe fn blah(ptr: std::ptr::NonNull, origin: std::ptr::NonNull, count: usize) -> bool { unsafe { /// ptr.sub_ptr(origin) == count /// # && @@ -885,7 +884,6 @@ impl NonNull { /// # Examples /// /// ``` - /// #![feature(ptr_sub_ptr)] /// use std::ptr::NonNull; /// /// let a = [0; 5]; @@ -903,8 +901,8 @@ impl NonNull { /// ``` #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - #[unstable(feature = "ptr_sub_ptr", issue = "95892")] - #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")] + #[stable(feature = "ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] pub const unsafe fn sub_ptr(self, subtracted: NonNull) -> usize where T: Sized, @@ -925,8 +923,8 @@ impl NonNull { /// ignoring the metadata. #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces - #[unstable(feature = "ptr_sub_ptr", issue = "95892")] - #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")] + #[stable(feature = "ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")] pub const unsafe fn byte_sub_ptr(self, origin: NonNull) -> usize { // SAFETY: the caller must uphold the safety contract for `byte_sub_ptr`. unsafe { self.as_ptr().byte_sub_ptr(origin.as_ptr()) } diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_unsigned_neg.rs b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_unsigned_neg.rs index 13eb5bfb3421d..13874398f7be5 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_unsigned_neg.rs +++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_unsigned_neg.rs @@ -1,6 +1,4 @@ //@normalize-stderr-test: "\d+ < \d+" -> "$$ADDR < $$ADDR" -#![feature(ptr_sub_ptr)] - fn main() { let arr = [0u8; 8]; let ptr1 = arr.as_ptr(); diff --git a/src/tools/miri/tests/pass/ptr_offset.rs b/src/tools/miri/tests/pass/ptr_offset.rs index 92b275b00327d..a8a0d2836e704 100644 --- a/src/tools/miri/tests/pass/ptr_offset.rs +++ b/src/tools/miri/tests/pass/ptr_offset.rs @@ -1,5 +1,4 @@ //@compile-flags: -Zmiri-permissive-provenance -#![feature(ptr_sub_ptr)] use std::{mem, ptr}; fn main() { diff --git a/tests/ui/consts/offset_from.rs b/tests/ui/consts/offset_from.rs index 7737b5ab0b8a6..c06314ac7df04 100644 --- a/tests/ui/consts/offset_from.rs +++ b/tests/ui/consts/offset_from.rs @@ -1,8 +1,5 @@ //@ run-pass -#![feature(const_ptr_sub_ptr)] -#![feature(ptr_sub_ptr)] - struct Struct { field: (), } diff --git a/tests/ui/consts/offset_from_ub.rs b/tests/ui/consts/offset_from_ub.rs index 8835690060505..39384bf0c8b93 100644 --- a/tests/ui/consts/offset_from_ub.rs +++ b/tests/ui/consts/offset_from_ub.rs @@ -1,5 +1,4 @@ //@ normalize-stderr: "\d+ bytes" -> "$$BYTES bytes" -#![feature(const_ptr_sub_ptr)] #![feature(core_intrinsics)] use std::intrinsics::{ptr_offset_from, ptr_offset_from_unsigned}; diff --git a/tests/ui/consts/offset_from_ub.stderr b/tests/ui/consts/offset_from_ub.stderr index 1379365cc25cc..8cfbdd131909a 100644 --- a/tests/ui/consts/offset_from_ub.stderr +++ b/tests/ui/consts/offset_from_ub.stderr @@ -1,5 +1,5 @@ error[E0080]: evaluation of constant value failed - --> $DIR/offset_from_ub.rs:19:27 + --> $DIR/offset_from_ub.rs:18:27 | LL | let offset = unsafe { ptr_offset_from(field_ptr, base_ptr) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on two different pointers that are not both derived from the same allocation @@ -12,67 +12,67 @@ error[E0080]: evaluation of constant value failed note: inside `std::ptr::const_ptr::::offset_from` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `NOT_PTR` - --> $DIR/offset_from_ub.rs:25:14 + --> $DIR/offset_from_ub.rs:24:14 | LL | unsafe { (42 as *const u8).offset_from(&5u8) as usize } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0080]: evaluation of constant value failed - --> $DIR/offset_from_ub.rs:32:14 + --> $DIR/offset_from_ub.rs:31:14 | LL | unsafe { ptr_offset_from(field_ptr, base_ptr as *const u16) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ exact_div: 1_isize cannot be divided by 2_isize without remainder error[E0080]: evaluation of constant value failed - --> $DIR/offset_from_ub.rs:39:14 + --> $DIR/offset_from_ub.rs:38:14 | LL | unsafe { ptr_offset_from(ptr2, ptr1) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on two different pointers that are not both derived from the same allocation error[E0080]: evaluation of constant value failed - --> $DIR/offset_from_ub.rs:48:14 + --> $DIR/offset_from_ub.rs:47:14 | LL | unsafe { ptr_offset_from(end_ptr, start_ptr) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on two different pointers where the memory range between them is not in-bounds of an allocation error[E0080]: evaluation of constant value failed - --> $DIR/offset_from_ub.rs:57:14 + --> $DIR/offset_from_ub.rs:56:14 | LL | unsafe { ptr_offset_from(start_ptr, end_ptr) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on two different pointers where the memory range between them is not in-bounds of an allocation error[E0080]: evaluation of constant value failed - --> $DIR/offset_from_ub.rs:66:14 + --> $DIR/offset_from_ub.rs:65:14 | LL | unsafe { ptr_offset_from_unsigned(field_ptr, base_ptr) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called on two different pointers that are not both derived from the same allocation error[E0080]: evaluation of constant value failed - --> $DIR/offset_from_ub.rs:73:14 + --> $DIR/offset_from_ub.rs:72:14 | LL | unsafe { ptr_offset_from(ptr2, ptr1) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called when first pointer is too far ahead of second error[E0080]: evaluation of constant value failed - --> $DIR/offset_from_ub.rs:79:14 + --> $DIR/offset_from_ub.rs:78:14 | LL | unsafe { ptr_offset_from(ptr1, ptr2) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called when first pointer is too far before second error[E0080]: evaluation of constant value failed - --> $DIR/offset_from_ub.rs:87:14 + --> $DIR/offset_from_ub.rs:86:14 | LL | unsafe { ptr_offset_from(ptr1, ptr2) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called when first pointer is too far before second error[E0080]: evaluation of constant value failed - --> $DIR/offset_from_ub.rs:94:14 + --> $DIR/offset_from_ub.rs:93:14 | LL | unsafe { ptr_offset_from_unsigned(p, p.add(2) ) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called when first pointer has smaller offset than second: 0 < 8 error[E0080]: evaluation of constant value failed - --> $DIR/offset_from_ub.rs:101:14 + --> $DIR/offset_from_ub.rs:100:14 | LL | unsafe { ptr_offset_from_unsigned(ptr2, ptr1) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called when first pointer is too far ahead of second @@ -85,7 +85,7 @@ error[E0080]: evaluation of constant value failed note: inside `std::ptr::const_ptr::::offset_from` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `OFFSET_VERY_FAR1` - --> $DIR/offset_from_ub.rs:110:14 + --> $DIR/offset_from_ub.rs:109:14 | LL | unsafe { ptr2.offset_from(ptr1) } | ^^^^^^^^^^^^^^^^^^^^^^ @@ -98,7 +98,7 @@ error[E0080]: evaluation of constant value failed note: inside `std::ptr::const_ptr::::offset_from` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `OFFSET_VERY_FAR2` - --> $DIR/offset_from_ub.rs:116:14 + --> $DIR/offset_from_ub.rs:115:14 | LL | unsafe { ptr1.offset_from(ptr2.wrapping_offset(1)) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 51d9a6c617b6e7357b506e59a4b4a64e5e63a825 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 29 Jan 2025 06:31:50 +0000 Subject: [PATCH 03/22] Track where crate dependencies come from in `creader` Introduce an enum that represents the different possible sources for dependencies, and use them where possible. This will enable more fine grained control and provides better context than passing the `dep_root` tuple. Use this to ensure that injected crates always show up as private by default. --- compiler/rustc_metadata/src/creader.rs | 93 ++++++++++++++++++++------ 1 file changed, 73 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index c2dda21bb72e6..9efe18af863ad 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -162,6 +162,39 @@ impl<'a> std::fmt::Debug for CrateDump<'a> { } } +/// Reason that a crate is being sourced as a dependency. +#[derive(Clone, Copy)] +enum CrateOrigin<'a> { + /// This crate was a dependency of another crate. + IndirectDependency { + dep_root: &'a CratePaths, + /// Dependency info about this crate. + dep: &'a CrateDep, + }, + /// Injected by `rustc`. + Injected, + /// Provided by `extern crate foo` or as part of the extern prelude. + Extern, +} + +impl<'a> CrateOrigin<'a> { + /// Return the dependency root, if any. + fn dep_root(&self) -> Option<&'a CratePaths> { + match self { + CrateOrigin::IndirectDependency { dep_root, .. } => Some(dep_root), + _ => None, + } + } + + /// Return dependency information, if any. + fn dep(&self) -> Option<&'a CrateDep> { + match self { + CrateOrigin::IndirectDependency { dep, .. } => Some(dep), + _ => None, + } + } +} + impl CStore { pub fn from_tcx(tcx: TyCtxt<'_>) -> FreezeReadGuard<'_, CStore> { FreezeReadGuard::map(tcx.untracked().cstore.read(), |cstore| { @@ -497,7 +530,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { &self, name: Symbol, private_dep: Option, - dep_root: Option<&CratePaths>, + origin: CrateOrigin<'_>, ) -> bool { // Standard library crates are never private. if STDLIB_STABLE_CRATES.contains(&name) { @@ -505,12 +538,16 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { return false; } + if matches!(origin, CrateOrigin::Injected) { + return true; + } + let extern_private = self.sess.opts.externs.get(name.as_str()).map(|e| e.is_private_dep); // Any descendants of `std` should be private. These crates are usually not marked // private in metadata, so we ignore that field. if extern_private.is_none() - && let Some(dep) = dep_root + && let Some(dep) = origin.dep_root() && STDLIB_STABLE_CRATES.contains(&dep.name) { return true; @@ -528,7 +565,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { fn register_crate( &mut self, host_lib: Option, - dep_root: Option<&CratePaths>, + origin: CrateOrigin<'_>, lib: Library, dep_kind: CrateDepKind, name: Symbol, @@ -540,7 +577,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { let Library { source, metadata } = lib; let crate_root = metadata.get_root(); let host_hash = host_lib.as_ref().map(|lib| lib.metadata.get_root().hash()); - let private_dep = self.is_private_dep(name, private_dep, dep_root); + let private_dep = self.is_private_dep(name, private_dep, origin); // Claim this crate number and cache it let feed = self.cstore.intern_stable_crate_id(&crate_root, self.tcx)?; @@ -556,7 +593,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // Maintain a reference to the top most crate. // Stash paths for top-most crate locally if necessary. let crate_paths; - let dep_root = if let Some(dep_root) = dep_root { + let dep_root = if let Some(dep_root) = origin.dep_root() { dep_root } else { crate_paths = CratePaths::new(crate_root.name(), source.clone()); @@ -664,17 +701,19 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { name: Symbol, span: Span, dep_kind: CrateDepKind, + origin: CrateOrigin<'_>, ) -> Option { self.used_extern_options.insert(name); - match self.maybe_resolve_crate(name, dep_kind, None) { + match self.maybe_resolve_crate(name, dep_kind, origin) { Ok(cnum) => { self.cstore.set_used_recursively(cnum); Some(cnum) } Err(err) => { debug!("failed to resolve crate {} {:?}", name, dep_kind); - let missing_core = - self.maybe_resolve_crate(sym::core, CrateDepKind::Explicit, None).is_err(); + let missing_core = self + .maybe_resolve_crate(sym::core, CrateDepKind::Explicit, CrateOrigin::Extern) + .is_err(); err.report(self.sess, span, missing_core); None } @@ -685,15 +724,15 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { &'b mut self, name: Symbol, mut dep_kind: CrateDepKind, - dep_of: Option<(&'b CratePaths, &'b CrateDep)>, + origin: CrateOrigin<'b>, ) -> Result { info!("resolving crate `{}`", name); if !name.as_str().is_ascii() { return Err(CrateError::NonAsciiName(name)); } - let dep_root = dep_of.map(|d| d.0); - let dep = dep_of.map(|d| d.1); + let dep_root = origin.dep_root(); + let dep = origin.dep(); let hash = dep.map(|d| d.hash); let host_hash = dep.map(|d| d.host_hash).flatten(); let extra_filename = dep.map(|d| &d.extra_filename[..]); @@ -736,7 +775,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // not specified by `--extern` on command line parameters, it may be // `private-dependency` when `register_crate` is called for the first time. Then it must be updated to // `public-dependency` here. - let private_dep = self.is_private_dep(name, private_dep, dep_root); + let private_dep = self.is_private_dep(name, private_dep, origin); let data = self.cstore.get_crate_data_mut(cnum); if data.is_proc_macro_crate() { dep_kind = CrateDepKind::MacrosOnly; @@ -747,7 +786,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } (LoadResult::Loaded(library), host_library) => { info!("register newly loaded library for `{}`", name); - self.register_crate(host_library, dep_root, library, dep_kind, name, private_dep) + self.register_crate(host_library, origin, library, dep_kind, name, private_dep) } _ => panic!(), } @@ -823,7 +862,11 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { CrateDepKind::MacrosOnly => CrateDepKind::MacrosOnly, _ => dep.kind, }; - let cnum = self.maybe_resolve_crate(dep.name, dep_kind, Some((dep_root, &dep)))?; + let cnum = self.maybe_resolve_crate( + dep.name, + dep_kind, + CrateOrigin::IndirectDependency { dep_root, dep: &dep }, + )?; crate_num_map.push(cnum); } @@ -917,7 +960,9 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { }; info!("panic runtime not found -- loading {}", name); - let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else { + let Some(cnum) = + self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, CrateOrigin::Injected) + else { return; }; let data = self.cstore.get_crate_data(cnum); @@ -946,7 +991,9 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { info!("loading profiler"); let name = Symbol::intern(&self.sess.opts.unstable_opts.profiler_runtime); - let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else { + let Some(cnum) = + self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, CrateOrigin::Injected) + else { return; }; let data = self.cstore.get_crate_data(cnum); @@ -1059,7 +1106,12 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { if entry.force { let name_interned = Symbol::intern(name); if !self.used_extern_options.contains(&name_interned) { - self.resolve_crate(name_interned, DUMMY_SP, CrateDepKind::Explicit); + self.resolve_crate( + name_interned, + DUMMY_SP, + CrateDepKind::Explicit, + CrateOrigin::Extern, + ); } } } @@ -1185,6 +1237,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { info!("{:?}", CrateDump(self.cstore)); } + /// Process an `extern crate foo` AST node. pub fn process_extern_crate( &mut self, item: &ast::Item, @@ -1210,7 +1263,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { CrateDepKind::Explicit }; - let cnum = self.resolve_crate(name, item.span, dep_kind)?; + let cnum = self.resolve_crate(name, item.span, dep_kind, CrateOrigin::Extern)?; let path_len = definitions.def_path(def_id).data.len(); self.cstore.update_extern_crate( @@ -1229,7 +1282,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> Option { - let cnum = self.resolve_crate(name, span, CrateDepKind::Explicit)?; + let cnum = self.resolve_crate(name, span, CrateDepKind::Explicit, CrateOrigin::Extern)?; self.cstore.update_extern_crate( cnum, @@ -1246,7 +1299,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } pub fn maybe_process_path_extern(&mut self, name: Symbol) -> Option { - self.maybe_resolve_crate(name, CrateDepKind::Explicit, None).ok() + self.maybe_resolve_crate(name, CrateDepKind::Explicit, CrateOrigin::Extern).ok() } } From 83d70c029860e619f8cb91f15bfc34f7f2d7965f Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 29 Jan 2025 23:45:36 +0000 Subject: [PATCH 04/22] Improve debugging for metadata structures I had to do a lot of debug by printing; having these `Debug` traits in place made it easier. Additionally, add some more information to existing `info!` statements. --- compiler/rustc_metadata/src/creader.rs | 3 ++- compiler/rustc_metadata/src/locator.rs | 10 ++++++---- compiler/rustc_metadata/src/rmeta/decoder.rs | 4 ++++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 9efe18af863ad..582572586cf17 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -147,6 +147,7 @@ impl<'a> std::fmt::Debug for CrateDump<'a> { writeln!(fmt, " cnum: {cnum}")?; writeln!(fmt, " hash: {}", data.hash())?; writeln!(fmt, " reqd: {:?}", data.dep_kind())?; + writeln!(fmt, " priv: {:?}", data.is_private_dep())?; let CrateSource { dylib, rlib, rmeta } = data.source(); if let Some(dylib) = dylib { writeln!(fmt, " dylib: {}", dylib.0.display())?; @@ -770,7 +771,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { match result { (LoadResult::Previous(cnum), None) => { - info!("library for `{}` was loaded previously", name); + info!("library for `{}` was loaded previously, cnum {cnum}", name); // When `private_dep` is none, it indicates the directly dependent crate. If it is // not specified by `--extern` on command line parameters, it may be // `private-dependency` when `register_crate` is called for the first time. Then it must be updated to diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 2ddabeb49f70d..3f3e58384cbf4 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -260,7 +260,7 @@ pub(crate) struct CrateLocator<'a> { crate_rejections: CrateRejections, } -#[derive(Clone)] +#[derive(Clone, Debug)] pub(crate) struct CratePaths { pub(crate) name: Symbol, source: CrateSource, @@ -272,7 +272,7 @@ impl CratePaths { } } -#[derive(Copy, Clone, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq)] pub(crate) enum CrateFlavor { Rlib, Rmeta, @@ -893,13 +893,13 @@ fn get_flavor_from_path(path: &Path) -> CrateFlavor { // ------------------------------------------ Error reporting ------------------------------------- -#[derive(Clone)] +#[derive(Clone, Debug)] struct CrateMismatch { path: PathBuf, got: String, } -#[derive(Clone, Default)] +#[derive(Clone, Debug, Default)] struct CrateRejections { via_hash: Vec, via_triple: Vec, @@ -912,6 +912,7 @@ struct CrateRejections { /// Candidate rejection reasons collected during crate search. /// If no candidate is accepted, then these reasons are presented to the user, /// otherwise they are ignored. +#[derive(Debug)] pub(crate) struct CombinedLocatorError { crate_name: Symbol, dep_root: Option, @@ -921,6 +922,7 @@ pub(crate) struct CombinedLocatorError { crate_rejections: CrateRejections, } +#[derive(Debug)] pub(crate) enum CrateError { NonAsciiName(Symbol), ExternLocationNotExist(Symbol, PathBuf), diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index e8dcda875e67a..0516179f62ca0 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1936,6 +1936,10 @@ impl CrateMetadata { self.root.needs_panic_runtime } + pub(crate) fn is_private_dep(&self) -> bool { + self.private_dep + } + pub(crate) fn is_panic_runtime(&self) -> bool { self.root.panic_runtime } From efff15afeabedacc2798d214dac404061df1555d Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 18 Feb 2025 13:40:58 -0800 Subject: [PATCH 05/22] compiler: Align::max_for_offset -> Align::max_aligned_factor No functional changes. --- compiler/rustc_abi/src/lib.rs | 17 ++++++++--------- compiler/rustc_ty_utils/src/layout.rs | 2 +- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 098638b6bcfa7..761df0ba1ceb6 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -810,20 +810,19 @@ impl Align { self.bits().try_into().unwrap() } - /// Computes the best alignment possible for the given offset - /// (the largest power of two that the offset is a multiple of). + /// Obtain the greatest factor of `size` that is an alignment + /// (the largest power of two the Size is a multiple of). /// - /// N.B., for an offset of `0`, this happens to return `2^64`. + /// Note that all numbers are factors of 0 #[inline] - pub fn max_for_offset(offset: Size) -> Align { - Align { pow2: offset.bytes().trailing_zeros() as u8 } + pub fn max_aligned_factor(size: Size) -> Align { + Align { pow2: size.bytes().trailing_zeros() as u8 } } - /// Lower the alignment, if necessary, such that the given offset - /// is aligned to it (the offset is a multiple of the alignment). + /// Reduces Align to an aligned factor of `size`. #[inline] - pub fn restrict_for_offset(self, offset: Size) -> Align { - self.min(Align::max_for_offset(offset)) + pub fn restrict_for_offset(self, size: Size) -> Align { + self.min(Align::max_aligned_factor(size)) } } diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index b6a14d147cad4..e95c95ed6c59f 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -534,7 +534,7 @@ fn layout_of_uncached<'tcx>( ( BackendRepr::Memory { sized: true }, AbiAndPrefAlign { - abi: Align::max_for_offset(size), + abi: Align::max_aligned_factor(size), pref: dl.vector_align(size).pref, }, ) From 5c474fd99b97b0d86d410dfe25b876b374b436fa Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 18 Feb 2025 18:53:15 -0800 Subject: [PATCH 06/22] compiler: `BackendRepr::inherent_{size,align} -> scalar_{size,align}` This pair of fn was introduced to perform invariant checks for scalars. Their current behavior doesn't mesh as well with checking SIMD types, so change the name of the fn to reflect their actual use-case and refactor the corresponding checks. Also simplify the returns from Option to Option, because every site was mapping away the "preferred" alignment anyways. --- compiler/rustc_abi/src/layout.rs | 37 ++++++++----- compiler/rustc_abi/src/lib.rs | 53 ++++++++++--------- .../rustc_ty_utils/src/layout/invariant.rs | 51 ++++++++++-------- 3 files changed, 78 insertions(+), 63 deletions(-) diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 53243266f992b..3f83787ea3765 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -310,10 +310,10 @@ impl LayoutCalculator { let mut align = if repr.pack.is_some() { dl.i8_align } else { dl.aggregate_align }; let mut max_repr_align = repr.align; - // If all the non-ZST fields have the same ABI and union ABI optimizations aren't - // disabled, we can use that common ABI for the union as a whole. + // If all the non-ZST fields have the same repr and union repr optimizations aren't + // disabled, we can use that common repr for the union as a whole. struct AbiMismatch; - let mut common_non_zst_abi_and_align = if repr.inhibits_union_abi_opt() { + let mut common_non_zst_repr_and_align = if repr.inhibits_union_abi_opt() { // Can't optimize Err(AbiMismatch) } else { @@ -337,14 +337,14 @@ impl LayoutCalculator { continue; } - if let Ok(common) = common_non_zst_abi_and_align { + if let Ok(common) = common_non_zst_repr_and_align { // Discard valid range information and allow undef let field_abi = field.backend_repr.to_union(); if let Some((common_abi, common_align)) = common { if common_abi != field_abi { // Different fields have different ABI: disable opt - common_non_zst_abi_and_align = Err(AbiMismatch); + common_non_zst_repr_and_align = Err(AbiMismatch); } else { // Fields with the same non-Aggregate ABI should also // have the same alignment @@ -357,7 +357,7 @@ impl LayoutCalculator { } } else { // First non-ZST field: record its ABI and alignment - common_non_zst_abi_and_align = Ok(Some((field_abi, field.align.abi))); + common_non_zst_repr_and_align = Ok(Some((field_abi, field.align.abi))); } } } @@ -376,16 +376,25 @@ impl LayoutCalculator { // If all non-ZST fields have the same ABI, we may forward that ABI // for the union as a whole, unless otherwise inhibited. - let abi = match common_non_zst_abi_and_align { + let backend_repr = match common_non_zst_repr_and_align { Err(AbiMismatch) | Ok(None) => BackendRepr::Memory { sized: true }, - Ok(Some((abi, _))) => { - if abi.inherent_align(dl).map(|a| a.abi) != Some(align.abi) { - // Mismatched alignment (e.g. union is #[repr(packed)]): disable opt + Ok(Some((repr, _))) => match repr { + // Mismatched alignment (e.g. union is #[repr(packed)]): disable opt + BackendRepr::Scalar(_) | BackendRepr::ScalarPair(_, _) + if repr.scalar_align(dl).unwrap() != align.abi => + { BackendRepr::Memory { sized: true } - } else { - abi } - } + // Vectors require at least element alignment, else disable the opt + BackendRepr::Vector { element, count: _ } if element.align(dl).abi > align.abi => { + BackendRepr::Memory { sized: true } + } + // the alignment tests passed and we can use this + BackendRepr::Scalar(..) + | BackendRepr::ScalarPair(..) + | BackendRepr::Vector { .. } + | BackendRepr::Memory { .. } => repr, + }, }; let Some(union_field_count) = NonZeroUsize::new(only_variant.len()) else { @@ -400,7 +409,7 @@ impl LayoutCalculator { Ok(LayoutData { variants: Variants::Single { index: only_variant_idx }, fields: FieldsShape::Union(union_field_count), - backend_repr: abi, + backend_repr, largest_niche: None, uninhabited: false, align, diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 761df0ba1ceb6..43a7141472c53 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1454,37 +1454,38 @@ impl BackendRepr { matches!(*self, BackendRepr::Scalar(s) if s.is_bool()) } - /// Returns the fixed alignment of this ABI, if any is mandated. - pub fn inherent_align(&self, cx: &C) -> Option { - Some(match *self { - BackendRepr::Scalar(s) => s.align(cx), - BackendRepr::ScalarPair(s1, s2) => s1.align(cx).max(s2.align(cx)), - BackendRepr::Vector { element, count } => { - cx.data_layout().vector_align(element.size(cx) * count) - } - BackendRepr::Memory { .. } => return None, - }) + /// The psABI alignment for a `Scalar` or `ScalarPair` + /// + /// `None` for other variants. + pub fn scalar_align(&self, cx: &C) -> Option { + match *self { + BackendRepr::Scalar(s) => Some(s.align(cx).abi), + BackendRepr::ScalarPair(s1, s2) => Some(s1.align(cx).max(s2.align(cx)).abi), + // The align of a Vector can vary in surprising ways + BackendRepr::Vector { .. } | BackendRepr::Memory { .. } => None, + } } - /// Returns the fixed size of this ABI, if any is mandated. - pub fn inherent_size(&self, cx: &C) -> Option { - Some(match *self { - BackendRepr::Scalar(s) => { - // No padding in scalars. - s.size(cx) - } + /// The psABI size for a `Scalar` or `ScalarPair` + /// + /// `None` for other variants + pub fn scalar_size(&self, cx: &C) -> Option { + match *self { + // No padding in scalars. + BackendRepr::Scalar(s) => Some(s.size(cx)), + // May have some padding between the pair. BackendRepr::ScalarPair(s1, s2) => { - // May have some padding between the pair. let field2_offset = s1.size(cx).align_to(s2.align(cx).abi); - (field2_offset + s2.size(cx)).align_to(self.inherent_align(cx)?.abi) - } - BackendRepr::Vector { element, count } => { - // No padding in vectors, except possibly for trailing padding - // to make the size a multiple of align (e.g. for vectors of size 3). - (element.size(cx) * count).align_to(self.inherent_align(cx)?.abi) + let size = (field2_offset + s2.size(cx)).align_to( + self.scalar_align(cx) + // We absolutely must have an answer here or everything is FUBAR. + .unwrap(), + ); + Some(size) } - BackendRepr::Memory { .. } => return None, - }) + // The size of a Vector can vary in surprising ways + BackendRepr::Vector { .. } | BackendRepr::Memory { .. } => None, + } } /// Discard validity range information and allow undef. diff --git a/compiler/rustc_ty_utils/src/layout/invariant.rs b/compiler/rustc_ty_utils/src/layout/invariant.rs index 5ea6716c5ca14..cbbe993b62f69 100644 --- a/compiler/rustc_ty_utils/src/layout/invariant.rs +++ b/compiler/rustc_ty_utils/src/layout/invariant.rs @@ -69,31 +69,30 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou } fn check_layout_abi<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayout<'tcx>) { - // Verify the ABI mandated alignment and size. - let align = layout.backend_repr.inherent_align(cx).map(|align| align.abi); - let size = layout.backend_repr.inherent_size(cx); - let Some((align, size)) = align.zip(size) else { - assert_matches!( - layout.layout.backend_repr(), - BackendRepr::Memory { .. }, - "ABI unexpectedly missing alignment and/or size in {layout:#?}" + // Verify the ABI-mandated alignment and size for scalars. + let align = layout.backend_repr.scalar_align(cx); + let size = layout.backend_repr.scalar_size(cx); + if let Some(align) = align { + assert_eq!( + layout.layout.align().abi, + align, + "alignment mismatch between ABI and layout in {layout:#?}" ); - return; - }; - assert_eq!( - layout.layout.align().abi, - align, - "alignment mismatch between ABI and layout in {layout:#?}" - ); - assert_eq!( - layout.layout.size(), - size, - "size mismatch between ABI and layout in {layout:#?}" - ); + } + if let Some(size) = size { + assert_eq!( + layout.layout.size(), + size, + "size mismatch between ABI and layout in {layout:#?}" + ); + } // Verify per-ABI invariants match layout.layout.backend_repr() { BackendRepr::Scalar(_) => { + // These must always be present for `Scalar` types. + let align = align.unwrap(); + let size = size.unwrap(); // Check that this matches the underlying field. let inner = skip_newtypes(cx, layout); assert!( @@ -235,9 +234,15 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou "`ScalarPair` second field with bad ABI in {inner:#?}", ); } - BackendRepr::Vector { element, .. } => { - assert!(align >= element.align(cx).abi); // just sanity-checking `vector_align`. - // FIXME: Do some kind of check of the inner type, like for Scalar and ScalarPair. + BackendRepr::Vector { element, count } => { + let align = layout.align.abi; + let size = layout.size; + let element_align = element.align(cx).abi; + let element_size = element.size(cx); + // Currently, vectors must always be aligned to at least their elements: + assert!(align >= element_align); + // And the size has to be element * count plus alignment padding, of course + assert!(size == (element_size * count).align_to(align)); } BackendRepr::Memory { .. } => {} // Nothing to check. } From 79f41c773aaad6a10c2c752d223bd5aba0371f9b Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Wed, 19 Feb 2025 14:53:31 -0800 Subject: [PATCH 07/22] compiler: split vector_align into cabi and llvmlike Introduce a pair of functions that actually describe what they do, because it wasn't clear the alignment is sometimes a forgery. --- compiler/rustc_abi/src/callconv/reg.rs | 2 +- compiler/rustc_abi/src/lib.rs | 23 ++++++++++++++--------- compiler/rustc_ty_utils/src/layout.rs | 7 +++++-- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_abi/src/callconv/reg.rs b/compiler/rustc_abi/src/callconv/reg.rs index 66f47c52c15d1..8cf140dbaad4e 100644 --- a/compiler/rustc_abi/src/callconv/reg.rs +++ b/compiler/rustc_abi/src/callconv/reg.rs @@ -57,7 +57,7 @@ impl Reg { 128 => dl.f128_align.abi, _ => panic!("unsupported float: {self:?}"), }, - RegKind::Vector => dl.vector_align(self.size).abi, + RegKind::Vector => dl.llvmlike_vector_align(self.size).abi, } } } diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 43a7141472c53..094a25129aea4 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -408,16 +408,21 @@ impl TargetDataLayout { } } + /// psABI-mandated alignment for a vector type, if any #[inline] - pub fn vector_align(&self, vec_size: Size) -> AbiAndPrefAlign { - for &(size, align) in &self.vector_align { - if size == vec_size { - return align; - } - } - // Default to natural alignment, which is what LLVM does. - // That is, use the size, rounded up to a power of 2. - AbiAndPrefAlign::new(Align::from_bytes(vec_size.bytes().next_power_of_two()).unwrap()) + fn cabi_vector_align(&self, vec_size: Size) -> Option { + self.vector_align + .iter() + .find(|(size, _align)| *size == vec_size) + .map(|(_size, align)| *align) + } + + /// an alignment resembling the one LLVM would pick for a vector + #[inline] + pub fn llvmlike_vector_align(&self, vec_size: Size) -> AbiAndPrefAlign { + self.cabi_vector_align(vec_size).unwrap_or(AbiAndPrefAlign::new( + Align::from_bytes(vec_size.bytes().next_power_of_two()).unwrap(), + )) } } diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index e95c95ed6c59f..0b5683bb84b62 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -535,11 +535,14 @@ fn layout_of_uncached<'tcx>( BackendRepr::Memory { sized: true }, AbiAndPrefAlign { abi: Align::max_aligned_factor(size), - pref: dl.vector_align(size).pref, + pref: dl.llvmlike_vector_align(size).pref, }, ) } else { - (BackendRepr::Vector { element: e_abi, count: e_len }, dl.vector_align(size)) + ( + BackendRepr::Vector { element: e_abi, count: e_len }, + dl.llvmlike_vector_align(size), + ) }; let size = size.align_to(align.abi); From 46f7a7d378972b4034118f798657a6d35091a4ca Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 18 Feb 2025 19:27:26 -0800 Subject: [PATCH 08/22] rust-analyzer: use new function in (incorrect) layout computation This is only to fix the build. --- src/tools/rust-analyzer/crates/hir-ty/src/layout.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs index f5a7b6581230f..a72bcad50a0ad 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs @@ -179,7 +179,7 @@ fn layout_of_simd_ty( .size .checked_mul(e_len, dl) .ok_or(LayoutError::BadCalc(LayoutCalculatorError::SizeOverflow))?; - let align = dl.vector_align(size); + let align = dl.llvmlike_vector_align(size); let size = size.align_to(align.abi); // Compute the placement of the vector fields: From 1412cfc987b2b6691367c2e7428c083bb207d722 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 29 Jan 2025 23:54:15 +0000 Subject: [PATCH 09/22] Inject `compiler_builtins` during postprocessing rather than via AST `compiler_builtins` is currently injected as `extern crate compiler_builtins as _`. This has made gating via diagnostics difficult because it appears in the crate graph as a non-private dependency, and there isn't an easy way to differentiate between the injected AST and user-specified `extern crate compiler_builtins`. Resolve this by injecting `compiler_builtins` during postprocessing rather than early in the AST. Most of the time this isn't even needed because it shows up in `std` or `core`'s crate graph, but injection is still needed to ensure `#![no_core]` works correctly. A similar change was attempted at [1] but this encountered errors building `proc_macro` and `rustc-std-workspace-std`. Similar failures showed up while working on this patch, which were traced back to `compiler_builtins` showing up in the graph twice (once via dependency and once via injection). This is resolved by not injecting if a `#![compiler_builtins]` crate already exists. [1]: https://github.com/rust-lang/rust/pull/113634 --- .../src/standard_library_imports.rs | 49 +++++-------------- compiler/rustc_metadata/messages.ftl | 3 ++ compiler/rustc_metadata/src/creader.rs | 38 ++++++++++++++ compiler/rustc_metadata/src/errors.rs | 6 +++ compiler/rustc_metadata/src/rmeta/decoder.rs | 4 ++ tests/ui/extern-flag/empty-extern-arg.stderr | 8 +-- .../issue-59191-replace-root-with-fn.rs | 3 +- .../issue-59191-replace-root-with-fn.stderr | 13 +++-- tests/ui/proc-macro/meta-macro-hygiene.stdout | 1 - .../nonterminal-token-hygiene.stdout | 1 - 10 files changed, 73 insertions(+), 53 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/standard_library_imports.rs b/compiler/rustc_builtin_macros/src/standard_library_imports.rs index 1a3f4d2d44908..6933ca09349a1 100644 --- a/compiler/rustc_builtin_macros/src/standard_library_imports.rs +++ b/compiler/rustc_builtin_macros/src/standard_library_imports.rs @@ -19,16 +19,12 @@ pub fn inject( let edition = sess.psess.edition; // the first name in this list is the crate name of the crate with the prelude - let names: &[Symbol] = if attr::contains_name(pre_configured_attrs, sym::no_core) { + let name: Symbol = if attr::contains_name(pre_configured_attrs, sym::no_core) { return 0; } else if attr::contains_name(pre_configured_attrs, sym::no_std) { - if attr::contains_name(pre_configured_attrs, sym::compiler_builtins) { - &[sym::core] - } else { - &[sym::core, sym::compiler_builtins] - } + sym::core } else { - &[sym::std] + sym::std }; let expn_id = resolver.expansion_for_ast_pass( @@ -43,36 +39,16 @@ pub fn inject( let ecfg = ExpansionConfig::default("std_lib_injection".to_string(), features); let cx = ExtCtxt::new(sess, ecfg, resolver, None); - // .rev() to preserve ordering above in combination with insert(0, ...) - for &name in names.iter().rev() { - let ident_span = if edition >= Edition2018 { span } else { call_site }; - let item = if name == sym::compiler_builtins { - // compiler_builtins is a private implementation detail. We only - // need to insert it into the crate graph for linking and should not - // expose any of its public API. - // - // FIXME(#113634) We should inject this during post-processing like - // we do for the panic runtime, profiler runtime, etc. - cx.item( - span, - Ident::new(kw::Underscore, ident_span), - thin_vec![], - ast::ItemKind::ExternCrate(Some(name)), - ) - } else { - cx.item( - span, - Ident::new(name, ident_span), - thin_vec![cx.attr_word(sym::macro_use, span)], - ast::ItemKind::ExternCrate(None), - ) - }; - krate.items.insert(0, item); - } + let ident_span = if edition >= Edition2018 { span } else { call_site }; - // The crates have been injected, the assumption is that the first one is - // the one with the prelude. - let name = names[0]; + let item = cx.item( + span, + Ident::new(name, ident_span), + thin_vec![cx.attr_word(sym::macro_use, span)], + ast::ItemKind::ExternCrate(None), + ); + + krate.items.insert(0, item); let root = (edition == Edition2015).then_some(kw::PathRoot); @@ -88,6 +64,7 @@ pub fn inject( .map(|&symbol| Ident::new(symbol, span)) .collect(); + // Inject the relevant crate's prelude. let use_item = cx.item( span, Ident::empty(), diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl index 6fc84b06647f5..df0a25712cca4 100644 --- a/compiler/rustc_metadata/messages.ftl +++ b/compiler/rustc_metadata/messages.ftl @@ -47,6 +47,9 @@ metadata_crate_dep_rustc_driver = metadata_crate_location_unknown_type = extern location for {$crate_name} is of an unknown type: {$path} +metadata_crate_not_compiler_builtins = + the crate `{$crate_name}` resolved as `compiler_builtins` but is not `#![compiler_builtins]` + metadata_crate_not_panic_runtime = the crate `{$crate_name}` is not a panic runtime diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 582572586cf17..a935bc3662dab 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -1118,6 +1118,43 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } } + /// Inject the `compiler_builtins` crate if it is not already in the graph. + fn inject_compiler_builtins(&mut self, krate: &ast::Crate) { + // `compiler_builtins` does not get extern builtins, nor do `#![no_core]` crates + if attr::contains_name(&krate.attrs, sym::compiler_builtins) + || attr::contains_name(&krate.attrs, sym::no_core) + { + info!("`compiler_builtins` unneeded"); + return; + } + + // If a `#![compiler_builtins]` crate already exists, avoid injecting it twice. This is + // the common case since usually it appears as a dependency of `std` or `alloc`. + for (cnum, cmeta) in self.cstore.iter_crate_data() { + if cmeta.is_compiler_builtins() { + info!("`compiler_builtins` already exists (cnum = {cnum}); skipping injection"); + return; + } + } + + // `compiler_builtins` is not yet in the graph; inject it. Error on resolution failure. + let Some(cnum) = self.resolve_crate( + sym::compiler_builtins, + krate.spans.inner_span.shrink_to_lo(), + CrateDepKind::Explicit, + CrateOrigin::Injected, + ) else { + info!("`compiler_builtins` not resolved"); + return; + }; + + // Sanity check that the loaded crate is `#![compiler_builtins]` + let cmeta = self.cstore.get_crate_data(cnum); + if !cmeta.is_compiler_builtins() { + self.dcx().emit_err(errors::CrateNotCompilerBuiltins { crate_name: cmeta.name() }); + } + } + fn inject_dependency_if( &mut self, krate: CrateNum, @@ -1227,6 +1264,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } pub fn postprocess(&mut self, krate: &ast::Crate) { + self.inject_compiler_builtins(krate); self.inject_forced_externs(); self.inject_profiler_runtime(); self.inject_allocator_crate(krate); diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index a77f9bc623b5b..2ad6389c0b4ac 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -332,6 +332,12 @@ pub struct CrateNotPanicRuntime { pub crate_name: Symbol, } +#[derive(Diagnostic)] +#[diag(metadata_crate_not_compiler_builtins)] +pub struct CrateNotCompilerBuiltins { + pub crate_name: Symbol, +} + #[derive(Diagnostic)] #[diag(metadata_no_panic_strategy)] pub struct NoPanicStrategy { diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 0516179f62ca0..ef0267eb3d908 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1948,6 +1948,10 @@ impl CrateMetadata { self.root.profiler_runtime } + pub(crate) fn is_compiler_builtins(&self) -> bool { + self.root.compiler_builtins + } + pub(crate) fn needs_allocator(&self) -> bool { self.root.needs_allocator } diff --git a/tests/ui/extern-flag/empty-extern-arg.stderr b/tests/ui/extern-flag/empty-extern-arg.stderr index b9a128e02e16b..79efcc5d8b041 100644 --- a/tests/ui/extern-flag/empty-extern-arg.stderr +++ b/tests/ui/extern-flag/empty-extern-arg.stderr @@ -7,11 +7,5 @@ error: unwinding panics are not supported without std = help: using nightly cargo, use -Zbuild-std with panic="abort" to avoid unwinding = note: since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem -error: requires `sized` lang_item - --> $DIR/empty-extern-arg.rs:6:11 - | -LL | fn main() {} - | ^^ - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/proc-macro/issue-59191-replace-root-with-fn.rs b/tests/ui/proc-macro/issue-59191-replace-root-with-fn.rs index c1b55fd99dfad..6afafb7114a61 100644 --- a/tests/ui/proc-macro/issue-59191-replace-root-with-fn.rs +++ b/tests/ui/proc-macro/issue-59191-replace-root-with-fn.rs @@ -3,7 +3,8 @@ //@ edition:2018 //@ proc-macro: issue-59191.rs -//@ error-pattern: requires `sized` lang_item +//@ needs-unwind (affects error output) +//@ error-pattern: error: `#[panic_handler]` function required #![feature(custom_inner_attributes)] #![issue_59191::no_main] diff --git a/tests/ui/proc-macro/issue-59191-replace-root-with-fn.stderr b/tests/ui/proc-macro/issue-59191-replace-root-with-fn.stderr index 2d0c92ff2974f..3cd98d9c72b82 100644 --- a/tests/ui/proc-macro/issue-59191-replace-root-with-fn.stderr +++ b/tests/ui/proc-macro/issue-59191-replace-root-with-fn.stderr @@ -1,10 +1,9 @@ -error: requires `sized` lang_item - --> $DIR/issue-59191-replace-root-with-fn.rs:9:1 - | -LL | #![issue_59191::no_main] - | ^^^^^^^^^^^^^^^^^^^^^^^^ +error: `#[panic_handler]` function required, but not found + +error: unwinding panics are not supported without std | - = note: this error originates in the attribute macro `issue_59191::no_main` (in Nightly builds, run with -Z macro-backtrace for more info) + = help: using nightly cargo, use -Zbuild-std with panic="abort" to avoid unwinding + = note: since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem -error: aborting due to 1 previous error +error: aborting due to 2 previous errors diff --git a/tests/ui/proc-macro/meta-macro-hygiene.stdout b/tests/ui/proc-macro/meta-macro-hygiene.stdout index fae8446515af0..1ee7179e84c04 100644 --- a/tests/ui/proc-macro/meta-macro-hygiene.stdout +++ b/tests/ui/proc-macro/meta-macro-hygiene.stdout @@ -20,7 +20,6 @@ Respanned: TokenStream [Ident { ident: "$crate", span: $DIR/auxiliary/make-macro use core /* 0#1 */::prelude /* 0#1 */::rust_2018 /* 0#1 */::*; #[macro_use /* 0#1 */] extern crate core /* 0#1 */; -extern crate compiler_builtins /* NNN */ as _ /* 0#1 */; // Don't load unnecessary hygiene information from std extern crate std /* 0#0 */; diff --git a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout index e7dda7d3c1606..c80a33206fb4f 100644 --- a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout +++ b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout @@ -39,7 +39,6 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ use ::core /* 0#1 */::prelude /* 0#1 */::rust_2015 /* 0#1 */::*; #[macro_use /* 0#1 */] extern crate core /* 0#2 */; -extern crate compiler_builtins /* NNN */ as _ /* 0#2 */; // Don't load unnecessary hygiene information from std extern crate std /* 0#0 */; From cb1d076d42e9285488436688b8879225ab6db80e Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 14 Jan 2025 20:04:59 +0000 Subject: [PATCH 10/22] Partially revert ed63539282 ("Mark dependencies ... private by default") Remove the portion of ed63539282 that automatically sets crates private based on whether they are dependencies of `std`. Instead, this is controlled by dependency configuration in `Cargo.toml`. --- compiler/rustc_metadata/src/creader.rs | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index a935bc3662dab..b94e32e17d418 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -32,7 +32,7 @@ use rustc_session::lint::{self, BuiltinLintDiag}; use rustc_session::output::validate_crate_name; use rustc_session::search_paths::PathKind; use rustc_span::edition::Edition; -use rustc_span::{DUMMY_SP, Ident, STDLIB_STABLE_CRATES, Span, Symbol, sym}; +use rustc_span::{DUMMY_SP, Ident, Span, Symbol, sym}; use rustc_target::spec::{PanicStrategy, Target, TargetTuple}; use tracing::{debug, info, trace}; @@ -533,27 +533,11 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { private_dep: Option, origin: CrateOrigin<'_>, ) -> bool { - // Standard library crates are never private. - if STDLIB_STABLE_CRATES.contains(&name) { - tracing::info!("returning false for {name} is private"); - return false; - } - if matches!(origin, CrateOrigin::Injected) { return true; } let extern_private = self.sess.opts.externs.get(name.as_str()).map(|e| e.is_private_dep); - - // Any descendants of `std` should be private. These crates are usually not marked - // private in metadata, so we ignore that field. - if extern_private.is_none() - && let Some(dep) = origin.dep_root() - && STDLIB_STABLE_CRATES.contains(&dep.name) - { - return true; - } - match (extern_private, private_dep) { // Explicit non-private via `--extern`, explicit non-private from metadata, or // unspecified with default to public. From 8c1b49d5e92c035661459063a645b78a47b6346a Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 28 Jan 2025 22:25:23 +0000 Subject: [PATCH 11/22] Use `public-dependencies` in all sysroot crates In [1], most dependencies of `std` and other sysroot crates were marked private, but this did not happen for `alloc` and `test`. Update these here, marking public standard library crates as the only non-private dependencies. [1]: https://github.com/rust-lang/rust/pull/111076 --- ...stdlib-Disable-f16-and-f128-in-compiler-builtins.patch | 2 +- library/alloc/Cargo.toml | 4 +++- library/sysroot/Cargo.toml | 8 +++++--- library/test/Cargo.toml | 6 ++++-- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch index e3a9512dda9c6..eb1fc4b0ad59f 100644 --- a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch +++ b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch @@ -15,7 +15,7 @@ index 7165c3e48af..968552ad435 100644 edition = "2021" [dependencies] - core = { path = "../core" } + core = { path = "../core", public = true } -compiler_builtins = { version = "=0.1.146", features = ['rustc-dep-of-std'] } +compiler_builtins = { version = "=0.1.146", features = ['rustc-dep-of-std', 'no-f16-f128'] } diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index c1d7f324f1770..395cff13189de 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -1,3 +1,5 @@ +cargo-features = ["public-dependency"] + [package] name = "alloc" version = "0.0.0" @@ -9,7 +11,7 @@ autobenches = false edition = "2021" [dependencies] -core = { path = "../core" } +core = { path = "../core", public = true } compiler_builtins = { version = "=0.1.146", features = ['rustc-dep-of-std'] } [dev-dependencies] diff --git a/library/sysroot/Cargo.toml b/library/sysroot/Cargo.toml index aa6c3dc32e2ba..45a9eda445dfb 100644 --- a/library/sysroot/Cargo.toml +++ b/library/sysroot/Cargo.toml @@ -1,3 +1,5 @@ +cargo-features = ["public-dependency"] + [package] name = "sysroot" version = "0.0.0" @@ -5,10 +7,10 @@ edition = "2021" # this is a dummy crate to ensure that all required crates appear in the sysroot [dependencies] -proc_macro = { path = "../proc_macro" } +proc_macro = { path = "../proc_macro", public = true } profiler_builtins = { path = "../profiler_builtins", optional = true } -std = { path = "../std" } -test = { path = "../test" } +std = { path = "../std", public = true } +test = { path = "../test", public = true } # Forward features to the `std` crate as necessary [features] diff --git a/library/test/Cargo.toml b/library/test/Cargo.toml index 75cc7c00e389c..241ef324b0088 100644 --- a/library/test/Cargo.toml +++ b/library/test/Cargo.toml @@ -1,3 +1,5 @@ +cargo-features = ["public-dependency"] + [package] name = "test" version = "0.0.0" @@ -5,8 +7,8 @@ edition = "2021" [dependencies] getopts = { version = "0.2.21", features = ['rustc-dep-of-std'] } -std = { path = "../std" } -core = { path = "../core" } +std = { path = "../std", public = true } +core = { path = "../core", public = true } [target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies] libc = { version = "0.2.150", default-features = false } From aca5b5dd5260d4e2c1bf584fc6ba36b5fba239cb Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 28 Jan 2025 23:20:36 +0000 Subject: [PATCH 12/22] If the parent dependency is private, treat dependents as private Currently, marking a dependency private does not automatically make all its child dependencies private. Resolve this by making its children private by default as well. This also resolves some FIXMEs for tests that are intended to fail but previously passed. [1]: https://github.com/rust-lang/rust/pull/135501#issuecomment-2620242419 --- compiler/rustc_metadata/src/creader.rs | 31 ++++++++++++++++--- .../pub-priv-dep/reexport_from_priv.rs | 3 +- .../pub-priv-dep/reexport_from_priv.stderr | 14 +++++++++ .../privacy/pub-priv-dep/shared_indirect.rs | 3 +- .../pub-priv-dep/shared_indirect.stderr | 14 +++++++++ 5 files changed, 56 insertions(+), 9 deletions(-) create mode 100644 tests/ui/privacy/pub-priv-dep/reexport_from_priv.stderr create mode 100644 tests/ui/privacy/pub-priv-dep/shared_indirect.stderr diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index b94e32e17d418..58ff2425748f8 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -168,7 +168,10 @@ impl<'a> std::fmt::Debug for CrateDump<'a> { enum CrateOrigin<'a> { /// This crate was a dependency of another crate. IndirectDependency { + /// Where this dependency was included from. dep_root: &'a CratePaths, + /// True if the parent is private, meaning the dependent should also be private. + parent_private: bool, /// Dependency info about this crate. dep: &'a CrateDep, }, @@ -194,6 +197,17 @@ impl<'a> CrateOrigin<'a> { _ => None, } } + + /// `Some(true)` if the dependency is private or its parent is private, `Some(false)` if the + /// dependency is not private, `None` if it could not be determined. + fn private_dep(&self) -> Option { + match self { + CrateOrigin::IndirectDependency { parent_private, dep, .. } => { + Some(dep.is_private || *parent_private) + } + _ => None, + } + } } impl CStore { @@ -585,7 +599,8 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { &crate_paths }; - let cnum_map = self.resolve_crate_deps(dep_root, &crate_root, &metadata, cnum, dep_kind)?; + let cnum_map = + self.resolve_crate_deps(dep_root, &crate_root, &metadata, cnum, dep_kind, private_dep)?; let raw_proc_macros = if crate_root.is_proc_macro_crate() { let temp_root; @@ -722,7 +737,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { let host_hash = dep.map(|d| d.host_hash).flatten(); let extra_filename = dep.map(|d| &d.extra_filename[..]); let path_kind = if dep.is_some() { PathKind::Dependency } else { PathKind::Crate }; - let private_dep = dep.map(|d| d.is_private); + let private_dep = origin.private_dep(); let result = if let Some(cnum) = self.existing_match(name, hash, path_kind) { (LoadResult::Previous(cnum), None) @@ -819,6 +834,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { metadata: &MetadataBlob, krate: CrateNum, dep_kind: CrateDepKind, + parent_is_private: bool, ) -> Result { debug!( "resolving deps of external crate `{}` with dep root `{}`", @@ -837,11 +853,12 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { crate_num_map.push(krate); for dep in deps { info!( - "resolving dep `{}`->`{}` hash: `{}` extra filename: `{}`", + "resolving dep `{}`->`{}` hash: `{}` extra filename: `{}` private {}", crate_root.name(), dep.name, dep.hash, - dep.extra_filename + dep.extra_filename, + dep.is_private, ); let dep_kind = match dep_kind { CrateDepKind::MacrosOnly => CrateDepKind::MacrosOnly, @@ -850,7 +867,11 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { let cnum = self.maybe_resolve_crate( dep.name, dep_kind, - CrateOrigin::IndirectDependency { dep_root, dep: &dep }, + CrateOrigin::IndirectDependency { + dep_root, + parent_private: parent_is_private, + dep: &dep, + }, )?; crate_num_map.push(cnum); } diff --git a/tests/ui/privacy/pub-priv-dep/reexport_from_priv.rs b/tests/ui/privacy/pub-priv-dep/reexport_from_priv.rs index 3c6e9825e7288..136e0ceeb5bec 100644 --- a/tests/ui/privacy/pub-priv-dep/reexport_from_priv.rs +++ b/tests/ui/privacy/pub-priv-dep/reexport_from_priv.rs @@ -1,6 +1,5 @@ //@ aux-crate:priv:reexport=reexport.rs //@ compile-flags: -Zunstable-options -//@ check-pass // Checks the behavior of a reexported item from a private dependency. @@ -9,7 +8,7 @@ extern crate reexport; -// FIXME: This should trigger. pub fn leaks_priv() -> reexport::Shared { + //~^ ERROR type `Shared` from private dependency 'shared' in public interface reexport::Shared } diff --git a/tests/ui/privacy/pub-priv-dep/reexport_from_priv.stderr b/tests/ui/privacy/pub-priv-dep/reexport_from_priv.stderr new file mode 100644 index 0000000000000..f1573283ff2e3 --- /dev/null +++ b/tests/ui/privacy/pub-priv-dep/reexport_from_priv.stderr @@ -0,0 +1,14 @@ +error: type `Shared` from private dependency 'shared' in public interface + --> $DIR/reexport_from_priv.rs:11:1 + | +LL | pub fn leaks_priv() -> reexport::Shared { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/reexport_from_priv.rs:7:9 + | +LL | #![deny(exported_private_dependencies)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/privacy/pub-priv-dep/shared_indirect.rs b/tests/ui/privacy/pub-priv-dep/shared_indirect.rs index 34b624b4a1a40..2fe66ae80cf48 100644 --- a/tests/ui/privacy/pub-priv-dep/shared_indirect.rs +++ b/tests/ui/privacy/pub-priv-dep/shared_indirect.rs @@ -1,7 +1,6 @@ //@ aux-crate:priv:shared=shared.rs //@ aux-crate:priv:indirect1=indirect1.rs //@ compile-flags: -Zunstable-options -//@ check-pass // A shared dependency, where it is only indirectly public. // @@ -23,7 +22,7 @@ extern crate shared; extern crate indirect1; -// FIXME: This should trigger. pub fn leaks_priv() -> shared::Shared { + //~^ ERROR type `Shared` from private dependency 'shared' in public interface shared::Shared } diff --git a/tests/ui/privacy/pub-priv-dep/shared_indirect.stderr b/tests/ui/privacy/pub-priv-dep/shared_indirect.stderr new file mode 100644 index 0000000000000..dbc534713d16e --- /dev/null +++ b/tests/ui/privacy/pub-priv-dep/shared_indirect.stderr @@ -0,0 +1,14 @@ +error: type `Shared` from private dependency 'shared' in public interface + --> $DIR/shared_indirect.rs:25:1 + | +LL | pub fn leaks_priv() -> shared::Shared { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/shared_indirect.rs:20:9 + | +LL | #![deny(exported_private_dependencies)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + From 93925809eb2f4be76c7babcc7cdb73d10ef977bd Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Thu, 30 Jan 2025 02:52:39 +0000 Subject: [PATCH 13/22] Replace some instances of `pub` with `pub(crate)` The recent fixes to private dependencies exposed some cases in the UEFI module where private dependencies are exposed in a public interface. These do not need to be crate-public, so change them to `pub(crate)`. --- library/std/src/sys/pal/uefi/process.rs | 2 +- library/std/src/sys/pal/uefi/time.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/pal/uefi/process.rs b/library/std/src/sys/pal/uefi/process.rs index 9efe9a314f2e9..c73a6350357a4 100644 --- a/library/std/src/sys/pal/uefi/process.rs +++ b/library/std/src/sys/pal/uefi/process.rs @@ -388,7 +388,7 @@ mod uefi_command_internal { } } - pub fn start_image(&mut self) -> io::Result { + pub(crate) fn start_image(&mut self) -> io::Result { self.update_st_crc32()?; // Use our system table instead of the default one diff --git a/library/std/src/sys/pal/uefi/time.rs b/library/std/src/sys/pal/uefi/time.rs index 495ff2dc930ed..c4ff3015ac60d 100644 --- a/library/std/src/sys/pal/uefi/time.rs +++ b/library/std/src/sys/pal/uefi/time.rs @@ -84,7 +84,7 @@ pub(crate) mod system_time_internal { // This algorithm is based on the one described in the post // https://blog.reverberate.org/2020/05/12/optimizing-date-algorithms.html - pub const fn uefi_time_to_duration(t: r_efi::system::Time) -> Duration { + pub(crate) const fn uefi_time_to_duration(t: r_efi::system::Time) -> Duration { assert!(t.month <= 12); assert!(t.month != 0); From 8e88547e965c5de8a9e9641920826f902051f9a3 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 18 Feb 2025 17:11:12 +0000 Subject: [PATCH 14/22] Tweak error code for sized checks of const/static --- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 14 +++++++++++--- compiler/rustc_hir_typeck/src/expr.rs | 2 +- compiler/rustc_middle/src/traits/mod.rs | 2 +- .../src/error_reporting/traits/suggestions.rs | 4 ++-- tests/ui/consts/const-slice-array-deref.stderr | 1 + tests/ui/consts/const-unsized.stderr | 4 ++++ .../consts/const_refs_to_static-ice-121413.stderr | 1 + .../issue-36122-accessing-externed-dst.stderr | 1 + tests/ui/issues/issue-54410.stderr | 1 + tests/ui/static/issue-24446.stderr | 1 + tests/ui/statics/unsized_type2.stderr | 1 + .../ice-unsized-tuple-const-issue-121443.stderr | 1 + 12 files changed, 26 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index f98504e19decb..228d15faaa466 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1108,7 +1108,13 @@ fn check_associated_item( let ty = tcx.type_of(item.def_id).instantiate_identity(); let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty); wfcx.register_wf_obligation(span, loc, ty.into()); - check_sized_if_body(wfcx, item.def_id.expect_local(), ty, Some(span)); + check_sized_if_body( + wfcx, + item.def_id.expect_local(), + ty, + Some(span), + ObligationCauseCode::SizedConstOrStatic, + ); Ok(()) } ty::AssocKind::Fn => { @@ -1354,7 +1360,7 @@ fn check_item_type( traits::ObligationCause::new( ty_span, wfcx.body_def_id, - ObligationCauseCode::WellFormed(None), + ObligationCauseCode::SizedConstOrStatic, ), wfcx.param_env, item_ty, @@ -1698,6 +1704,7 @@ fn check_fn_or_method<'tcx>( hir::FnRetTy::Return(ty) => Some(ty.span), hir::FnRetTy::DefaultReturn(_) => None, }, + ObligationCauseCode::SizedReturnType, ); } @@ -1706,13 +1713,14 @@ fn check_sized_if_body<'tcx>( def_id: LocalDefId, ty: Ty<'tcx>, maybe_span: Option, + code: ObligationCauseCode<'tcx>, ) { let tcx = wfcx.tcx(); if let Some(body) = tcx.hir_maybe_body_owned_by(def_id) { let span = maybe_span.unwrap_or(body.value.span); wfcx.register_bound( - ObligationCause::new(span, def_id, traits::ObligationCauseCode::SizedReturnType), + ObligationCause::new(span, def_id, code), wfcx.param_env, ty, tcx.require_lang_item(LangItem::Sized, Some(span)), diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 1c63b8b365594..c39ed29d0d315 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1810,7 +1810,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { crate::GatherLocalsVisitor::new(&fcx).visit_body(body); let ty = fcx.check_expr_with_expectation(body.value, expected); - fcx.require_type_is_sized(ty, body.value.span, ObligationCauseCode::ConstSized); + fcx.require_type_is_sized(ty, body.value.span, ObligationCauseCode::SizedConstOrStatic); fcx.write_ty(block.hir_id, ty); ty } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 53bc9eb7e466c..686fcd459a754 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -274,7 +274,7 @@ pub enum ObligationCauseCode<'tcx> { }, /// Constant expressions must be sized. - ConstSized, + SizedConstOrStatic, /// `static` items must have `Sync` type. SharedStatic, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index ee0ab0dfbb82a..2de005ef0192d 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3125,8 +3125,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { Applicability::MachineApplicable, ); } - ObligationCauseCode::ConstSized => { - err.note("constant expressions must have a statically known size"); + ObligationCauseCode::SizedConstOrStatic => { + err.note("statics and constants must have a statically known size"); } ObligationCauseCode::InlineAsmSized => { err.note("all inline asm arguments must have a statically known size"); diff --git a/tests/ui/consts/const-slice-array-deref.stderr b/tests/ui/consts/const-slice-array-deref.stderr index 346685380cc6c..b1d069280885d 100644 --- a/tests/ui/consts/const-slice-array-deref.stderr +++ b/tests/ui/consts/const-slice-array-deref.stderr @@ -5,6 +5,7 @@ LL | const ONE: [u16] = [1]; | ^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[u16]` + = note: statics and constants must have a statically known size error[E0308]: mismatched types --> $DIR/const-slice-array-deref.rs:1:20 diff --git a/tests/ui/consts/const-unsized.stderr b/tests/ui/consts/const-unsized.stderr index 7931d7adafdb1..8328e19aac22d 100644 --- a/tests/ui/consts/const-unsized.stderr +++ b/tests/ui/consts/const-unsized.stderr @@ -5,6 +5,7 @@ LL | const CONST_0: dyn Debug + Sync = *(&0 as &(dyn Debug + Sync)); | ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `(dyn Debug + Sync + 'static)` + = note: statics and constants must have a statically known size error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/const-unsized.rs:7:18 @@ -13,6 +14,7 @@ LL | const CONST_FOO: str = *"foo"; | ^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` + = note: statics and constants must have a statically known size error[E0277]: the size for values of type `(dyn Debug + Sync + 'static)` cannot be known at compilation time --> $DIR/const-unsized.rs:11:18 @@ -21,6 +23,7 @@ LL | static STATIC_1: dyn Debug + Sync = *(&1 as &(dyn Debug + Sync)); | ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `(dyn Debug + Sync + 'static)` + = note: statics and constants must have a statically known size error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/const-unsized.rs:15:20 @@ -29,6 +32,7 @@ LL | static STATIC_BAR: str = *"bar"; | ^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` + = note: statics and constants must have a statically known size error[E0507]: cannot move out of a shared reference --> $DIR/const-unsized.rs:3:35 diff --git a/tests/ui/consts/const_refs_to_static-ice-121413.stderr b/tests/ui/consts/const_refs_to_static-ice-121413.stderr index 8665d9b685223..3980a7e9b93ba 100644 --- a/tests/ui/consts/const_refs_to_static-ice-121413.stderr +++ b/tests/ui/consts/const_refs_to_static-ice-121413.stderr @@ -30,6 +30,7 @@ LL | static FOO: Sync = AtomicUsize::new(0); | ^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `(dyn Sync + 'static)` + = note: statics and constants must have a statically known size error: aborting due to 2 previous errors; 1 warning emitted diff --git a/tests/ui/extern/issue-36122-accessing-externed-dst.stderr b/tests/ui/extern/issue-36122-accessing-externed-dst.stderr index 64178e6f84390..6f805aec1df02 100644 --- a/tests/ui/extern/issue-36122-accessing-externed-dst.stderr +++ b/tests/ui/extern/issue-36122-accessing-externed-dst.stderr @@ -5,6 +5,7 @@ LL | static symbol: [usize]; | ^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[usize]` + = note: statics and constants must have a statically known size error[E0133]: use of extern static is unsafe and requires unsafe function or block --> $DIR/issue-36122-accessing-externed-dst.rs:5:20 diff --git a/tests/ui/issues/issue-54410.stderr b/tests/ui/issues/issue-54410.stderr index 97e5990750e3c..2cd5a2a49ef5d 100644 --- a/tests/ui/issues/issue-54410.stderr +++ b/tests/ui/issues/issue-54410.stderr @@ -5,6 +5,7 @@ LL | pub static mut symbol: [i8]; | ^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[i8]` + = note: statics and constants must have a statically known size error: aborting due to 1 previous error diff --git a/tests/ui/static/issue-24446.stderr b/tests/ui/static/issue-24446.stderr index 033caf07d8e54..0e6e338c5efeb 100644 --- a/tests/ui/static/issue-24446.stderr +++ b/tests/ui/static/issue-24446.stderr @@ -14,6 +14,7 @@ LL | static foo: dyn Fn() -> u32 = || -> u32 { | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `(dyn Fn() -> u32 + 'static)` + = note: statics and constants must have a statically known size error[E0308]: mismatched types --> $DIR/issue-24446.rs:2:35 diff --git a/tests/ui/statics/unsized_type2.stderr b/tests/ui/statics/unsized_type2.stderr index ffbbe218c87a0..3f9b0879c166d 100644 --- a/tests/ui/statics/unsized_type2.stderr +++ b/tests/ui/statics/unsized_type2.stderr @@ -10,6 +10,7 @@ note: required because it appears within the type `Foo` | LL | pub struct Foo { | ^^^ + = note: statics and constants must have a statically known size error[E0308]: mismatched types --> $DIR/unsized_type2.rs:14:45 diff --git a/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.stderr b/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.stderr index 76e015a7238b5..4609e02716fdc 100644 --- a/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.stderr +++ b/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.stderr @@ -11,6 +11,7 @@ LL | const TEST: Fn = some_fn; | ^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `(dyn FnOnce() -> u8 + 'static)` + = note: statics and constants must have a statically known size error[E0277]: the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time --> $DIR/ice-unsized-tuple-const-issue-121443.rs:11:14 From c3e8ba3a91570534bc219950631aa65f3a8afa9e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 20 Feb 2025 02:21:58 +0000 Subject: [PATCH 15/22] Check signature WF when lowering MIR body --- .../rustc_hir_analysis/src/check/wfcheck.rs | 2 +- compiler/rustc_mir_transform/src/lib.rs | 18 ++++++++++++++++ tests/crashes/129095.rs | 5 ++++- tests/crashes/132960.rs | 2 +- tests/crashes/134654.rs | 3 +++ tests/crashes/135128.rs | 2 ++ tests/crashes/135570.rs | 3 +++ .../consts/dont-ctfe-unsized-initializer.rs | 7 +++++++ .../dont-ctfe-unsized-initializer.stderr | 21 +++++++++++++++++++ 9 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 tests/ui/consts/dont-ctfe-unsized-initializer.rs create mode 100644 tests/ui/consts/dont-ctfe-unsized-initializer.stderr diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 228d15faaa466..ec0d1dfa351c0 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -201,7 +201,7 @@ fn check_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGua hir::Node::ImplItem(item) => check_impl_item(tcx, item), hir::Node::ForeignItem(item) => check_foreign_item(tcx, item), hir::Node::OpaqueTy(_) => Ok(crate::check::check::check_item_type(tcx, def_id)), - _ => unreachable!(), + _ => unreachable!("{node:?}"), }; if let Some(generics) = node.generics() { diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 04c9375b83176..5df12ac4d8bc2 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -513,6 +513,24 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> & body.tainted_by_errors = Some(error_reported); } + // Also taint the body if it's within a top-level item that is not well formed. + // + // We do this check here and not during `mir_promoted` because that may result + // in borrowck cycles if WF requires looking into an opaque hidden type. + let root = tcx.typeck_root_def_id(def.to_def_id()); + match tcx.def_kind(root) { + DefKind::Fn + | DefKind::AssocFn + | DefKind::Static { .. } + | DefKind::Const + | DefKind::AssocConst => { + if let Err(guar) = tcx.check_well_formed(root.expect_local()) { + body.tainted_by_errors = Some(guar); + } + } + _ => {} + } + run_analysis_to_runtime_passes(tcx, &mut body); tcx.alloc_steal_mir(body) diff --git a/tests/crashes/129095.rs b/tests/crashes/129095.rs index d82474e18e706..b1bb74708c2d7 100644 --- a/tests/crashes/129095.rs +++ b/tests/crashes/129095.rs @@ -1,10 +1,13 @@ //@ known-bug: rust-lang/rust#129095 //@ compile-flags: -Zmir-enable-passes=+GVN -Zmir-enable-passes=+Inline -Zvalidate-mir +#![feature(adt_const_params, unsized_const_params)] +#![allow(incomplete_features)] + pub fn function_with_bytes() -> &'static [u8] { BYTES } pub fn main() { - assert_eq!(function_with_bytes::(), &[0x41, 0x41, 0x41, 0x41]); + assert_eq!(function_with_bytes::(), &[0x41, 0x41, 0x41, 0x41]); } diff --git a/tests/crashes/132960.rs b/tests/crashes/132960.rs index 87d0ee7dedebd..c23a339342914 100644 --- a/tests/crashes/132960.rs +++ b/tests/crashes/132960.rs @@ -1,6 +1,6 @@ //@ known-bug: #132960 -#![feature(adt_const_params, const_ptr_read, generic_const_exprs)] +#![feature(adt_const_params, const_ptr_read, generic_const_exprs, unsized_const_params)] const fn concat_strs() -> &'static str where diff --git a/tests/crashes/134654.rs b/tests/crashes/134654.rs index 8a8d18359e96f..f2323fe4ecdcd 100644 --- a/tests/crashes/134654.rs +++ b/tests/crashes/134654.rs @@ -2,6 +2,9 @@ //@ compile-flags: -Zmir-enable-passes=+GVN -Zmir-enable-passes=+Inline -Zvalidate-mir //@ only-x86_64 +#![feature(adt_const_params, unsized_const_params)] +#![allow(incomplete_features)] + fn function_with_bytes() -> &'static [u8] { BYTES diff --git a/tests/crashes/135128.rs b/tests/crashes/135128.rs index 2ce17df824a0c..a8fd1ae1ff56a 100644 --- a/tests/crashes/135128.rs +++ b/tests/crashes/135128.rs @@ -1,6 +1,8 @@ //@ known-bug: #135128 //@ compile-flags: -Copt-level=1 --edition=2021 +#![feature(trivial_bounds)] + async fn return_str() -> str where str: Sized, diff --git a/tests/crashes/135570.rs b/tests/crashes/135570.rs index a9eda97ef9de7..7919ceb26d50d 100644 --- a/tests/crashes/135570.rs +++ b/tests/crashes/135570.rs @@ -2,6 +2,9 @@ //@compile-flags: -Zvalidate-mir -Zmir-enable-passes=+Inline -Copt-level=0 -Zmir-enable-passes=+GVN //@ only-x86_64 +#![feature(adt_const_params, unsized_const_params)] +#![allow(incomplete_features)] + fn function_with_bytes( ) -> &'static [u8] { BYTES diff --git a/tests/ui/consts/dont-ctfe-unsized-initializer.rs b/tests/ui/consts/dont-ctfe-unsized-initializer.rs new file mode 100644 index 0000000000000..cca38b760dcc8 --- /dev/null +++ b/tests/ui/consts/dont-ctfe-unsized-initializer.rs @@ -0,0 +1,7 @@ +static S: str = todo!(); +//~^ ERROR the size for values of type `str` cannot be known at compilation time + +const C: str = todo!(); +//~^ ERROR the size for values of type `str` cannot be known at compilation time + +fn main() {} diff --git a/tests/ui/consts/dont-ctfe-unsized-initializer.stderr b/tests/ui/consts/dont-ctfe-unsized-initializer.stderr new file mode 100644 index 0000000000000..e69790fc1823c --- /dev/null +++ b/tests/ui/consts/dont-ctfe-unsized-initializer.stderr @@ -0,0 +1,21 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/dont-ctfe-unsized-initializer.rs:1:11 + | +LL | static S: str = todo!(); + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: statics and constants must have a statically known size + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/dont-ctfe-unsized-initializer.rs:4:10 + | +LL | const C: str = todo!(); + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: statics and constants must have a statically known size + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. From 0e9a6cc12841192f76ee6ad100e1c76c433e5ea5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 21 Feb 2025 19:22:08 +0000 Subject: [PATCH 16/22] Don't typeck during WF, instead check outside of WF in check_crate --- .../rustc_hir_analysis/src/check/check.rs | 7 +-- compiler/rustc_hir_analysis/src/check/mod.rs | 2 +- compiler/rustc_hir_analysis/src/lib.rs | 10 ++-- .../unevaluated-const-ice-119731.stderr | 12 ++--- tests/ui/consts/issue-39974.stderr | 12 ++--- tests/ui/layout/issue-84108.stderr | 18 +++---- .../ui/type-alias-impl-trait/issue-53092-2.rs | 6 ++- .../issue-53092-2.stderr | 50 ++++++++++++++----- .../ui/wf/wf-normalization-sized.next.stderr | 20 ++++---- 9 files changed, 80 insertions(+), 57 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 516ecbcfe0ef9..ea9e628d4bec9 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -745,14 +745,10 @@ fn check_static_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) { pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { match tcx.def_kind(def_id) { DefKind::Static { .. } => { - tcx.ensure_ok().typeck(def_id); - maybe_check_static_with_link_section(tcx, def_id); check_static_inhabited(tcx, def_id); check_static_linkage(tcx, def_id); } - DefKind::Const => { - tcx.ensure_ok().typeck(def_id); - } + DefKind::Const => {} DefKind::Enum => { check_enum(tcx, def_id); } @@ -766,7 +762,6 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { ExternAbi::Rust, ) } - // Everything else is checked entirely within check_item_body } DefKind::Impl { of_trait } => { if of_trait && let Some(impl_trait_header) = tcx.impl_trait_header(def_id) { diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 7b3c3ea2bb46b..096256cad55f0 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -145,7 +145,7 @@ pub fn forbid_intrinsic_abi(tcx: TyCtxt<'_>, sp: Span, abi: ExternAbi) { } } -fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId) { +pub(super) fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId) { // Only restricted on wasm target for now if !tcx.sess.target.is_like_wasm { return; diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 0859a39b15566..1ade4b26cdb70 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -212,7 +212,10 @@ pub fn check_crate(tcx: TyCtxt<'_>) { tcx.par_hir_body_owners(|item_def_id| { let def_kind = tcx.def_kind(item_def_id); match def_kind { - DefKind::Static { .. } => tcx.ensure_ok().eval_static_initializer(item_def_id), + DefKind::Static { .. } => { + tcx.ensure_ok().eval_static_initializer(item_def_id); + check::maybe_check_static_with_link_section(tcx, item_def_id); + } DefKind::Const if tcx.generics_of(item_def_id).is_empty() => { let instance = ty::Instance::new(item_def_id.into(), ty::GenericArgs::empty()); let cid = GlobalId { instance, promoted: None }; @@ -223,12 +226,9 @@ pub fn check_crate(tcx: TyCtxt<'_>) { } }); - // FIXME: Remove this when we implement creating `DefId`s - // for anon constants during their parents' typeck. - // Typeck all body owners in parallel will produce queries - // cycle errors because it may typeck on anon constants directly. tcx.par_hir_body_owners(|item_def_id| { let def_kind = tcx.def_kind(item_def_id); + // Skip `AnonConst`s because we feed their `type_of`. if !matches!(def_kind, DefKind::AnonConst) { tcx.ensure_ok().typeck(item_def_id); } diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr index 30a45ce377e7e..b73611c79b291 100644 --- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr +++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr @@ -54,12 +54,6 @@ warning: type `v17` should have an upper camel case name LL | pub struct v17 { | ^^^ help: convert the identifier to upper camel case (notice the capitalization): `V17` -error[E0425]: cannot find function `v6` in this scope - --> $DIR/unevaluated-const-ice-119731.rs:13:35 - | -LL | const v0: [[usize; v4]; v4] = v6(v8); - | ^^ not found in this scope - error: `[[usize; v4]; v4]` is forbidden as the type of a const generic parameter --> $DIR/unevaluated-const-ice-119731.rs:16:48 | @@ -72,6 +66,12 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more LL + #![feature(adt_const_params)] | +error[E0425]: cannot find function `v6` in this scope + --> $DIR/unevaluated-const-ice-119731.rs:13:35 + | +LL | const v0: [[usize; v4]; v4] = v6(v8); + | ^^ not found in this scope + error: maximum number of nodes exceeded in constant v20::v17::::{constant#0} --> $DIR/unevaluated-const-ice-119731.rs:28:37 | diff --git a/tests/ui/consts/issue-39974.stderr b/tests/ui/consts/issue-39974.stderr index a371ea5709e1b..d03f709b0eaf9 100644 --- a/tests/ui/consts/issue-39974.stderr +++ b/tests/ui/consts/issue-39974.stderr @@ -1,3 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/issue-39974.rs:5:19 + | +LL | f: [[f64; 2]; LENGTH], + | ^^^^^^ expected `usize`, found `f64` + error[E0308]: mismatched types --> $DIR/issue-39974.rs:1:21 | @@ -9,12 +15,6 @@ help: use a float literal LL | const LENGTH: f64 = 2.0; | ++ -error[E0308]: mismatched types - --> $DIR/issue-39974.rs:5:19 - | -LL | f: [[f64; 2]; LENGTH], - | ^^^^^^ expected `usize`, found `f64` - error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/layout/issue-84108.stderr b/tests/ui/layout/issue-84108.stderr index 8ddce285e23f8..e296abfc3b53b 100644 --- a/tests/ui/layout/issue-84108.stderr +++ b/tests/ui/layout/issue-84108.stderr @@ -29,6 +29,15 @@ LL | const BAR: (&Path, [u8], usize) = ("hello", [], 42); = help: the trait `Sized` is not implemented for `[u8]` = note: only the last element of a tuple may have a dynamically sized type +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/issue-84108.rs:15:13 + | +LL | static BAZ: ([u8], usize) = ([], 0); + | ^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: only the last element of a tuple may have a dynamically sized type + error[E0277]: the size for values of type `[u8]` cannot be known at compilation time --> $DIR/issue-84108.rs:9:12 | @@ -48,15 +57,6 @@ LL | const BAR: (&Path, [u8], usize) = ("hello", [], 42); = note: expected slice `[u8]` found array `[_; 0]` -error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/issue-84108.rs:15:13 - | -LL | static BAZ: ([u8], usize) = ([], 0); - | ^^^^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `[u8]` - = note: only the last element of a tuple may have a dynamically sized type - error[E0277]: the size for values of type `[u8]` cannot be known at compilation time --> $DIR/issue-84108.rs:15:13 | diff --git a/tests/ui/type-alias-impl-trait/issue-53092-2.rs b/tests/ui/type-alias-impl-trait/issue-53092-2.rs index 2383008d042f7..43df49adc4232 100644 --- a/tests/ui/type-alias-impl-trait/issue-53092-2.rs +++ b/tests/ui/type-alias-impl-trait/issue-53092-2.rs @@ -2,10 +2,12 @@ #![allow(dead_code)] type Bug = impl Fn(T) -> U + Copy; +//~^ ERROR cycle detected const CONST_BUG: Bug = unsafe { std::mem::transmute(|_: u8| ()) }; -//~^ ERROR cycle detected -//~| ERROR: non-defining opaque type use +//~^ ERROR item does not constrain `Bug::{opaque#0}`, but has it in its signature +//~| ERROR item does not constrain `Bug::{opaque#0}`, but has it in its signature +//~| ERROR non-defining opaque type use in defining scope fn make_bug>() -> Bug { |x| x.into() diff --git a/tests/ui/type-alias-impl-trait/issue-53092-2.stderr b/tests/ui/type-alias-impl-trait/issue-53092-2.stderr index ac580866704d7..678b0c84f78bc 100644 --- a/tests/ui/type-alias-impl-trait/issue-53092-2.stderr +++ b/tests/ui/type-alias-impl-trait/issue-53092-2.stderr @@ -1,5 +1,5 @@ error[E0792]: non-defining opaque type use in defining scope - --> $DIR/issue-53092-2.rs:6:18 + --> $DIR/issue-53092-2.rs:7:18 | LL | const CONST_BUG: Bug = unsafe { std::mem::transmute(|_: u8| ()) }; | ^^^^^^^^^^^ argument `u8` is not a generic parameter @@ -10,33 +10,59 @@ note: for this opaque type LL | type Bug = impl Fn(T) -> U + Copy; | ^^^^^^^^^^^^^^^^^^^^^^ -error[E0391]: cycle detected when type-checking `CONST_BUG` - --> $DIR/issue-53092-2.rs:6:1 +error[E0391]: cycle detected when computing type of `Bug::{opaque#0}` + --> $DIR/issue-53092-2.rs:4:18 + | +LL | type Bug = impl Fn(T) -> U + Copy; + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires computing type of opaque `Bug::{opaque#0}`... + --> $DIR/issue-53092-2.rs:4:18 + | +LL | type Bug = impl Fn(T) -> U + Copy; + | ^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires type-checking `CONST_BUG`... + --> $DIR/issue-53092-2.rs:7:1 | LL | const CONST_BUG: Bug = unsafe { std::mem::transmute(|_: u8| ()) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | = note: ...which requires computing layout of `Bug`... = note: ...which requires normalizing `Bug`... -note: ...which requires computing type of `Bug::{opaque#0}`... + = note: ...which again requires computing type of `Bug::{opaque#0}`, completing the cycle +note: cycle used when checking that `Bug::{opaque#0}` is well-formed --> $DIR/issue-53092-2.rs:4:18 | LL | type Bug = impl Fn(T) -> U + Copy; | ^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires computing type of opaque `Bug::{opaque#0}`... + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: item does not constrain `Bug::{opaque#0}`, but has it in its signature + --> $DIR/issue-53092-2.rs:7:7 + | +LL | const CONST_BUG: Bug = unsafe { std::mem::transmute(|_: u8| ()) }; + | ^^^^^^^^^ + | + = note: consider moving the opaque type's declaration and defining uses into a separate module +note: this opaque type is in the signature --> $DIR/issue-53092-2.rs:4:18 | LL | type Bug = impl Fn(T) -> U + Copy; | ^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires type-checking `CONST_BUG`, completing the cycle -note: cycle used when checking that `CONST_BUG` is well-formed - --> $DIR/issue-53092-2.rs:6:1 + +error: item does not constrain `Bug::{opaque#0}`, but has it in its signature + --> $DIR/issue-53092-2.rs:7:61 | LL | const CONST_BUG: Bug = unsafe { std::mem::transmute(|_: u8| ()) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + | ^^^^^^^ + | + = note: consider moving the opaque type's declaration and defining uses into a separate module +note: this opaque type is in the signature + --> $DIR/issue-53092-2.rs:4:18 + | +LL | type Bug = impl Fn(T) -> U + Copy; + | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0391, E0792. For more information about an error, try `rustc --explain E0391`. diff --git a/tests/ui/wf/wf-normalization-sized.next.stderr b/tests/ui/wf/wf-normalization-sized.next.stderr index 83b56bb6b19ad..66c4f214415d5 100644 --- a/tests/ui/wf/wf-normalization-sized.next.stderr +++ b/tests/ui/wf/wf-normalization-sized.next.stderr @@ -7,16 +7,6 @@ LL | const _: <[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize = (); = help: the trait `Sized` is not implemented for `[[[[[u8]]]]]` = note: slice and array elements must have `Sized` type -error[E0277]: the size for values of type `[[[[[u8]]]]]` cannot be known at compilation time - --> $DIR/wf-normalization-sized.rs:19:11 - | -LL | const _: <[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize = (); - | ^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `[[[[[u8]]]]]` - = note: slice and array elements must have `Sized` type - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/wf-normalization-sized.rs:22:11 | @@ -27,6 +17,16 @@ LL | const _: as WellUnformed>::RequestNormalize = (); note: required by an implicit `Sized` bound in `Vec` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL +error[E0277]: the size for values of type `[[[[[u8]]]]]` cannot be known at compilation time + --> $DIR/wf-normalization-sized.rs:19:11 + | +LL | const _: <[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize = (); + | ^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[[[[[u8]]]]]` + = note: slice and array elements must have `Sized` type + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/wf-normalization-sized.rs:22:11 | From 2a6daaf89a12dcb3467b057ec1a3d539623cd32c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 17 Feb 2025 05:33:06 +0000 Subject: [PATCH 17/22] Make asm a named field --- compiler/rustc_ast_lowering/src/item.rs | 4 +++- compiler/rustc_codegen_cranelift/src/global_asm.rs | 2 +- compiler/rustc_codegen_ssa/src/mono_item.rs | 2 +- compiler/rustc_hir/src/hir.rs | 6 +++--- compiler/rustc_hir/src/intravisit.rs | 2 +- compiler/rustc_hir/src/target.rs | 2 +- compiler/rustc_hir_analysis/src/check/check.rs | 2 +- compiler/rustc_hir_analysis/src/collect.rs | 2 +- .../rustc_hir_analysis/src/collect/resolve_bound_vars.rs | 2 +- compiler/rustc_hir_analysis/src/collect/type_of.rs | 6 +++--- compiler/rustc_hir_pretty/src/lib.rs | 2 +- compiler/rustc_hir_typeck/src/lib.rs | 2 +- compiler/rustc_incremental/src/persist/dirty_clean.rs | 2 +- compiler/rustc_lint/src/types.rs | 2 +- compiler/rustc_middle/src/hir/map.rs | 2 +- compiler/rustc_monomorphize/src/collector.rs | 2 +- compiler/rustc_passes/src/reachable.rs | 2 +- compiler/rustc_privacy/src/lib.rs | 2 +- src/librustdoc/html/render/span_map.rs | 2 +- src/librustdoc/visit_ast.rs | 2 +- .../clippy_lints/src/arbitrary_source_item_ordering.rs | 4 ++-- src/tools/clippy/clippy_lints/src/missing_doc.rs | 2 +- src/tools/clippy/clippy_lints/src/missing_inline.rs | 2 +- 23 files changed, 30 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index bc2db41546989..a7a03f7d6db91 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -251,7 +251,9 @@ impl<'hir> LoweringContext<'_, 'hir> { .arena .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))), }, - ItemKind::GlobalAsm(asm) => hir::ItemKind::GlobalAsm(self.lower_inline_asm(span, asm)), + ItemKind::GlobalAsm(asm) => { + hir::ItemKind::GlobalAsm { asm: self.lower_inline_asm(span, asm) } + } ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty, .. }) => { // We lower // diff --git a/compiler/rustc_codegen_cranelift/src/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs index 54745b0d8c104..0a23f63d6ba9b 100644 --- a/compiler/rustc_codegen_cranelift/src/global_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/global_asm.rs @@ -16,7 +16,7 @@ use crate::prelude::*; pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, item_id: ItemId) { let item = tcx.hir_item(item_id); - if let rustc_hir::ItemKind::GlobalAsm(asm) = item.kind { + if let rustc_hir::ItemKind::GlobalAsm { asm } = item.kind { let is_x86 = matches!(tcx.sess.asm_arch.unwrap(), InlineAsmArch::X86 | InlineAsmArch::X86_64); diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs index 5f95b6615bd30..a4d5f8bb7017a 100644 --- a/compiler/rustc_codegen_ssa/src/mono_item.rs +++ b/compiler/rustc_codegen_ssa/src/mono_item.rs @@ -36,7 +36,7 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> { } MonoItem::GlobalAsm(item_id) => { let item = cx.tcx().hir_item(item_id); - if let hir::ItemKind::GlobalAsm(asm) = item.kind { + if let hir::ItemKind::GlobalAsm { asm } = item.kind { let operands: Vec<_> = asm .operands .iter() diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index eafc60f9d72f7..7cd3037278326 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3848,7 +3848,7 @@ impl<'hir> Item<'hir> { expect_foreign_mod, (ExternAbi, &'hir [ForeignItemRef]), ItemKind::ForeignMod { abi, items }, (*abi, items); - expect_global_asm, &'hir InlineAsm<'hir>, ItemKind::GlobalAsm(asm), asm; + expect_global_asm, &'hir InlineAsm<'hir>, ItemKind::GlobalAsm { asm }, asm; expect_ty_alias, (&'hir Ty<'hir>, &'hir Generics<'hir>), ItemKind::TyAlias(ty, generics), (ty, generics); @@ -4015,7 +4015,7 @@ pub enum ItemKind<'hir> { /// An external module, e.g. `extern { .. }`. ForeignMod { abi: ExternAbi, items: &'hir [ForeignItemRef] }, /// Module-level inline assembly (from `global_asm!`). - GlobalAsm(&'hir InlineAsm<'hir>), + GlobalAsm { asm: &'hir InlineAsm<'hir> }, /// A type alias, e.g., `type Foo = Bar`. TyAlias(&'hir Ty<'hir>, &'hir Generics<'hir>), /// An enum definition, e.g., `enum Foo {C, D}`. @@ -4081,7 +4081,7 @@ impl ItemKind<'_> { ItemKind::Macro(..) => "macro", ItemKind::Mod(..) => "module", ItemKind::ForeignMod { .. } => "extern block", - ItemKind::GlobalAsm(..) => "global asm item", + ItemKind::GlobalAsm { .. } => "global asm item", ItemKind::TyAlias(..) => "type alias", ItemKind::Enum(..) => "enum", ItemKind::Struct(..) => "struct", diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index bd96fe9ee32c7..5a002423a0c9e 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -573,7 +573,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V:: try_visit!(visitor.visit_id(item.hir_id())); walk_list!(visitor, visit_foreign_item_ref, items); } - ItemKind::GlobalAsm(asm) => { + ItemKind::GlobalAsm { asm } => { try_visit!(visitor.visit_id(item.hir_id())); try_visit!(visitor.visit_inline_asm(asm, item.hir_id())); } diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs index f3e8f059c9e3c..70e95a84e68cc 100644 --- a/compiler/rustc_hir/src/target.rs +++ b/compiler/rustc_hir/src/target.rs @@ -110,7 +110,7 @@ impl Target { ItemKind::Macro(..) => Target::MacroDef, ItemKind::Mod(..) => Target::Mod, ItemKind::ForeignMod { .. } => Target::ForeignMod, - ItemKind::GlobalAsm(..) => Target::GlobalAsm, + ItemKind::GlobalAsm { .. } => Target::GlobalAsm, ItemKind::TyAlias(..) => Target::TyAlias, ItemKind::Enum(..) => Target::Enum, ItemKind::Struct(..) => Target::Struct, diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index b1b046d71752b..fbe3b60c5203e 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -897,7 +897,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { } DefKind::GlobalAsm => { let it = tcx.hir().expect_item(def_id); - let hir::ItemKind::GlobalAsm(asm) = it.kind else { + let hir::ItemKind::GlobalAsm { asm } = it.kind else { span_bug!(it.span, "DefKind::GlobalAsm but got {:#?}", it) }; InlineAsmCtxt::new_global_asm(tcx).check_asm(asm, def_id); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 5bb77c096dcf8..d2334c8cec5a9 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -680,7 +680,7 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { | hir::ItemKind::Use(..) | hir::ItemKind::Macro(..) | hir::ItemKind::Mod(_) - | hir::ItemKind::GlobalAsm(_) => {} + | hir::ItemKind::GlobalAsm { .. } => {} hir::ItemKind::ForeignMod { items, .. } => { for item in *items { let item = tcx.hir_foreign_item(item.id); diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 759c981a8f768..b5333f393bcd8 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -630,7 +630,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { | hir::ItemKind::Mod(..) | hir::ItemKind::ForeignMod { .. } | hir::ItemKind::Static(..) - | hir::ItemKind::GlobalAsm(..) => { + | hir::ItemKind::GlobalAsm { .. } => { // These sorts of items have no lifetime parameters at all. intravisit::walk_item(self, item); } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 717713d93399d..19b78f48cfc04 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -59,7 +59,7 @@ fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx // Anon consts outside the type system. Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. }) - | Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. }) + | Node::Item(&Item { kind: ItemKind::GlobalAsm { asm }, .. }) if let Some((anon_const, op_sp)) = asm.operands.iter().find_map(find_sym_fn) => { let ty = tcx.typeck(def_id).node_type(hir_id); @@ -83,7 +83,7 @@ fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx } } Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. }) - | Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. }) + | Node::Item(&Item { kind: ItemKind::GlobalAsm { asm }, .. }) if let Some((anon_const, op_sp)) = asm.operands.iter().find_map(find_const) => { let ty = tcx.typeck(def_id).node_type(hir_id); @@ -318,7 +318,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ | ItemKind::Macro(..) | ItemKind::Mod(..) | ItemKind::ForeignMod { .. } - | ItemKind::GlobalAsm(..) + | ItemKind::GlobalAsm { .. } | ItemKind::ExternCrate(..) | ItemKind::Use(..) => { span_bug!(item.span, "compute_type_of_item: unexpected item type: {:?}", item.kind); diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 34124a6aa11a3..b485b426c2882 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -692,7 +692,7 @@ impl<'a> State<'a> { } self.bclose(item.span); } - hir::ItemKind::GlobalAsm(asm) => { + hir::ItemKind::GlobalAsm { asm } => { self.head("global_asm!"); self.print_inline_asm(asm); self.end() diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 9d5184acb3ca7..c1ed5b0aa5074 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -277,7 +277,7 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti Some(fcx.next_ty_var(span)) } Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), span, .. }) - | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), span, .. }) => { + | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm { asm }, span, .. }) => { asm.operands.iter().find_map(|(op, _op_sp)| match op { hir::InlineAsmOperand::Const { anon_const } | hir::InlineAsmOperand::SymFn { anon_const } diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index 118a6fed036ed..56858679af663 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -261,7 +261,7 @@ impl<'tcx> DirtyCleanVisitor<'tcx> { HirItem::ForeignMod { .. } => ("ItemForeignMod", LABELS_HIR_ONLY), // Module-level inline assembly (from global_asm!) - HirItem::GlobalAsm(..) => ("ItemGlobalAsm", LABELS_HIR_ONLY), + HirItem::GlobalAsm { .. } => ("ItemGlobalAsm", LABELS_HIR_ONLY), // A type alias, e.g., `type Foo = Bar` HirItem::TyAlias(..) => ("ItemTy", LABELS_HIR_ONLY), diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 68b1f435a4cf7..4930cc35c9c3d 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1740,7 +1740,7 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDefinitions { hir::ItemKind::Impl(..) | hir::ItemKind::TraitAlias(..) | hir::ItemKind::Trait(..) - | hir::ItemKind::GlobalAsm(..) + | hir::ItemKind::GlobalAsm { .. } | hir::ItemKind::ForeignMod { .. } | hir::ItemKind::Mod(..) | hir::ItemKind::Macro(..) diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index 40dd6aa73fd4c..832f802661450 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -1166,7 +1166,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { ItemKind::Macro(..) => "macro", ItemKind::Mod(..) => "mod", ItemKind::ForeignMod { .. } => "foreign mod", - ItemKind::GlobalAsm(..) => "global asm", + ItemKind::GlobalAsm { .. } => "global asm", ItemKind::TyAlias(..) => "ty", ItemKind::Enum(..) => "enum", ItemKind::Struct(..) => "struct", diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 1195c25e13087..bf56f468179d8 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -479,7 +479,7 @@ fn collect_items_rec<'tcx>( recursion_depth_reset = None; let item = tcx.hir_item(item_id); - if let hir::ItemKind::GlobalAsm(asm) = item.kind { + if let hir::ItemKind::GlobalAsm { asm } = item.kind { for (op, op_sp) in asm.operands { match op { hir::InlineAsmOperand::Const { .. } => { diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index 1fe44bd3d21a9..fd465717bf766 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -246,7 +246,7 @@ impl<'tcx> ReachableContext<'tcx> { | hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Union(..) - | hir::ItemKind::GlobalAsm(..) => {} + | hir::ItemKind::GlobalAsm { .. } => {} } } Node::TraitItem(trait_method) => { diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 6faa2c1a00d23..41725d0c6a4f9 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -645,7 +645,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { // The interface is empty, and no nested items. hir::ItemKind::Use(..) | hir::ItemKind::ExternCrate(..) - | hir::ItemKind::GlobalAsm(..) => {} + | hir::ItemKind::GlobalAsm { .. } => {} // The interface is empty, and all nested items are processed by `visit_item`. hir::ItemKind::Mod(..) => {} hir::ItemKind::Macro(macro_def, _) => { diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs index 658d5965b3d2a..ce9c42c01cc73 100644 --- a/src/librustdoc/html/render/span_map.rs +++ b/src/librustdoc/html/render/span_map.rs @@ -288,7 +288,7 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> { | ItemKind::Use(_, _) | ItemKind::ExternCrate(_) | ItemKind::ForeignMod { .. } - | ItemKind::GlobalAsm(_) + | ItemKind::GlobalAsm { .. } // We already have "visit_mod" above so no need to check it here. | ItemKind::Mod(_) => {} } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index f606a3d8a9270..7b6921afa0808 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -439,7 +439,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } // If we're inlining, skip private items. _ if self.inlining && !is_pub => {} - hir::ItemKind::GlobalAsm(..) => {} + hir::ItemKind::GlobalAsm { .. } => {} hir::ItemKind::Use(_, hir::UseKind::ListStem) => {} hir::ItemKind::Use(path, kind) => { for &res in &path.res { diff --git a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs index aff40fa846be2..c0ae4960e10d9 100644 --- a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs +++ b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs @@ -362,7 +362,7 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering { } } else if let ItemKind::ForeignMod { .. } = item.kind { continue; - } else if let ItemKind::GlobalAsm(_) = item.kind { + } else if let ItemKind::GlobalAsm { .. } = item.kind { continue; } else if let ItemKind::Use(path, use_kind) = item.kind { if path.segments.is_empty() { @@ -467,7 +467,7 @@ fn convert_module_item_kind(value: &ItemKind<'_>) -> SourceItemOrderingModuleIte ItemKind::Macro(..) => Macro, ItemKind::Mod(..) => Mod, ItemKind::ForeignMod { .. } => ForeignMod, - ItemKind::GlobalAsm(..) => GlobalAsm, + ItemKind::GlobalAsm { .. } => GlobalAsm, ItemKind::TyAlias(..) => TyAlias, ItemKind::Enum(..) => Enum, ItemKind::Struct(..) => Struct, diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs index 06e92985e6648..47a9e17b3cfe1 100644 --- a/src/tools/clippy/clippy_lints/src/missing_doc.rs +++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs @@ -217,7 +217,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { | hir::ItemKind::Union(..) => {}, hir::ItemKind::ExternCrate(..) | hir::ItemKind::ForeignMod { .. } - | hir::ItemKind::GlobalAsm(..) + | hir::ItemKind::GlobalAsm { .. } | hir::ItemKind::Impl { .. } | hir::ItemKind::Use(..) => note_prev_span_then_ret!(self.prev_span, it.span), } diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs index fdc0930e957a0..3cf1a80607e8b 100644 --- a/src/tools/clippy/clippy_lints/src/missing_inline.rs +++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs @@ -128,7 +128,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { | hir::ItemKind::Static(..) | hir::ItemKind::Struct(..) | hir::ItemKind::TraitAlias(..) - | hir::ItemKind::GlobalAsm(..) + | hir::ItemKind::GlobalAsm { .. } | hir::ItemKind::TyAlias(..) | hir::ItemKind::Union(..) | hir::ItemKind::ExternCrate(..) From 37060aae13d0fe771f9d3222f1c644820a9d2837 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 17 Feb 2025 16:14:34 +0000 Subject: [PATCH 18/22] Initial cleanups of InlineAsmCtxt --- .../rustc_hir_analysis/src/check/check.rs | 2 +- .../src/check/intrinsicck.rs | 90 +++++++------------ .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 7 +- 3 files changed, 39 insertions(+), 60 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index fbe3b60c5203e..0d34b657dfc30 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -900,7 +900,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { let hir::ItemKind::GlobalAsm { asm } = it.kind else { span_bug!(it.span, "DefKind::GlobalAsm but got {:#?}", it) }; - InlineAsmCtxt::new_global_asm(tcx).check_asm(asm, def_id); + InlineAsmCtxt::new_global_asm(tcx, def_id).check_asm(asm); } _ => {} } diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index 90e93bdbb5075..00f2d46931fa6 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -16,10 +16,11 @@ use rustc_target::asm::{ use crate::errors::RegisterTypeUnstable; -pub struct InlineAsmCtxt<'a, 'tcx> { +pub struct InlineAsmCtxt<'a, 'tcx: 'a> { tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, - get_operand_ty: Box) -> Ty<'tcx> + 'a>, + target_features: &'tcx FxIndexSet, + expr_ty: Box) -> Ty<'tcx> + 'a>, } enum NonAsmTypeReason<'tcx> { @@ -29,14 +30,15 @@ enum NonAsmTypeReason<'tcx> { } impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { - pub fn new_global_asm(tcx: TyCtxt<'tcx>) -> Self { + pub fn new_global_asm(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { InlineAsmCtxt { tcx, typing_env: ty::TypingEnv { typing_mode: ty::TypingMode::non_body_analysis(), param_env: ty::ParamEnv::empty(), }, - get_operand_ty: Box::new(|e| bug!("asm operand in global asm: {e:?}")), + target_features: tcx.asm_target_features(def_id), + expr_ty: Box::new(|e| bug!("asm operand in global asm: {e:?}")), } } @@ -45,9 +47,19 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { pub fn new_in_fn( tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, - get_operand_ty: impl Fn(&'tcx hir::Expr<'tcx>) -> Ty<'tcx> + 'a, + def_id: LocalDefId, + expr_ty: impl Fn(&hir::Expr<'tcx>) -> Ty<'tcx> + 'a, ) -> Self { - InlineAsmCtxt { tcx, typing_env, get_operand_ty: Box::new(get_operand_ty) } + InlineAsmCtxt { + tcx, + typing_env, + target_features: tcx.asm_target_features(def_id), + expr_ty: Box::new(expr_ty), + } + } + + fn expr_ty(&self, expr: &hir::Expr<'tcx>) -> Ty<'tcx> { + (self.expr_ty)(expr) } // FIXME(compiler-errors): This could use `<$ty as Pointee>::Metadata == ()` @@ -139,9 +151,8 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { template: &[InlineAsmTemplatePiece], is_input: bool, tied_input: Option<(&'tcx hir::Expr<'tcx>, Option)>, - target_features: &FxIndexSet, ) -> Option { - let ty = (self.get_operand_ty)(expr); + let ty = self.expr_ty(expr); if ty.has_non_region_infer() { bug!("inference variable in asm operand ty: {:?} {:?}", expr, ty); } @@ -229,7 +240,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { if let Some((in_expr, Some(in_asm_ty))) = tied_input { if in_asm_ty != asm_ty { let msg = "incompatible types for asm inout argument"; - let in_expr_ty = (self.get_operand_ty)(in_expr); + let in_expr_ty = self.expr_ty(in_expr); self.tcx .dcx() .struct_span_err(vec![in_expr.span, expr.span], msg) @@ -291,7 +302,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { // (!). In that case we still need the earlier check to verify that the // register class is usable at all. if let Some(feature) = feature { - if !target_features.contains(feature) { + if !self.target_features.contains(feature) { let msg = format!("`{feature}` target feature is not enabled"); self.tcx .dcx() @@ -351,14 +362,13 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { Some(asm_ty) } - pub fn check_asm(&self, asm: &hir::InlineAsm<'tcx>, enclosing_id: LocalDefId) { - let target_features = self.tcx.asm_target_features(enclosing_id.to_def_id()); + pub fn check_asm(&self, asm: &hir::InlineAsm<'tcx>) { let Some(asm_arch) = self.tcx.sess.asm_arch else { self.tcx.dcx().delayed_bug("target architecture does not support asm"); return; }; let allow_experimental_reg = self.tcx.features().asm_experimental_reg(); - for (idx, (op, op_sp)) in asm.operands.iter().enumerate() { + for (idx, &(op, op_sp)) in asm.operands.iter().enumerate() { // Validate register classes against currently enabled target // features. We check that at least one type is available for // the enabled features. @@ -381,12 +391,12 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { if let Err(msg) = reg.validate( asm_arch, self.tcx.sess.relocation_model(), - target_features, + self.target_features, &self.tcx.sess.target, op.is_clobber(), ) { let msg = format!("cannot use register `{}`: {}", reg.name(), msg); - self.tcx.dcx().span_err(*op_sp, msg); + self.tcx.dcx().span_err(op_sp, msg); continue; } } @@ -401,7 +411,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { { match feature { Some(feature) => { - if target_features.contains(&feature) { + if self.target_features.contains(&feature) { missing_required_features.clear(); break; } else { @@ -426,7 +436,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { reg_class.name(), feature ); - self.tcx.dcx().span_err(*op_sp, msg); + self.tcx.dcx().span_err(op_sp, msg); // register isn't enabled, don't do more checks continue; } @@ -440,7 +450,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { .intersperse(", ") .collect::(), ); - self.tcx.dcx().span_err(*op_sp, msg); + self.tcx.dcx().span_err(op_sp, msg); // register isn't enabled, don't do more checks continue; } @@ -448,52 +458,21 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { } } - match *op { + match op { hir::InlineAsmOperand::In { reg, expr } => { - self.check_asm_operand_type( - idx, - reg, - expr, - asm.template, - true, - None, - target_features, - ); + self.check_asm_operand_type(idx, reg, expr, asm.template, true, None); } hir::InlineAsmOperand::Out { reg, late: _, expr } => { if let Some(expr) = expr { - self.check_asm_operand_type( - idx, - reg, - expr, - asm.template, - false, - None, - target_features, - ); + self.check_asm_operand_type(idx, reg, expr, asm.template, false, None); } } hir::InlineAsmOperand::InOut { reg, late: _, expr } => { - self.check_asm_operand_type( - idx, - reg, - expr, - asm.template, - false, - None, - target_features, - ); + self.check_asm_operand_type(idx, reg, expr, asm.template, false, None); } hir::InlineAsmOperand::SplitInOut { reg, late: _, in_expr, out_expr } => { - let in_ty = self.check_asm_operand_type( - idx, - reg, - in_expr, - asm.template, - true, - None, - target_features, - ); + let in_ty = + self.check_asm_operand_type(idx, reg, in_expr, asm.template, true, None); if let Some(out_expr) = out_expr { self.check_asm_operand_type( idx, @@ -502,7 +481,6 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { asm.template, false, Some((in_expr, in_ty)), - target_features, ); } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index cf61659479b13..bce9fbbd6d1f1 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -101,7 +101,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!("FnCtxt::check_asm: {} deferred checks", deferred_asm_checks.len()); for (asm, hir_id) in deferred_asm_checks.drain(..) { let enclosing_id = self.tcx.hir_enclosing_body_owner(hir_id); - let get_operand_ty = |expr| { + let expr_ty = |expr: &hir::Expr<'tcx>| { let ty = self.typeck_results.borrow().expr_ty_adjusted(expr); let ty = self.resolve_vars_if_possible(ty); if ty.has_non_region_infer() { @@ -113,9 +113,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { InlineAsmCtxt::new_in_fn( self.tcx, self.infcx.typing_env(self.param_env), - get_operand_ty, + enclosing_id, + expr_ty, ) - .check_asm(asm, enclosing_id); + .check_asm(asm); } } From 6ba39f7dc709a90bcb125974964a7e464ed86ff2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 17 Feb 2025 16:09:46 +0000 Subject: [PATCH 19/22] Make a fake body to store typeck results for global_asm --- compiler/rustc_ast_lowering/src/asm.rs | 18 +------ compiler/rustc_ast_lowering/src/item.rs | 5 +- .../rustc_borrowck/src/universal_regions.rs | 29 +++++++++-- .../rustc_codegen_cranelift/src/global_asm.rs | 6 +-- compiler/rustc_codegen_ssa/src/mono_item.rs | 9 ++-- compiler/rustc_hir/src/hir.rs | 25 ++++++++-- compiler/rustc_hir/src/intravisit.rs | 14 ++++-- .../rustc_hir_analysis/src/check/check.rs | 9 ---- .../src/check/intrinsicck.rs | 50 ++++++++++--------- .../src/collect/generics_of.rs | 3 +- .../rustc_hir_analysis/src/collect/type_of.rs | 35 +------------ compiler/rustc_hir_pretty/src/lib.rs | 6 +-- compiler/rustc_hir_typeck/src/expr.rs | 7 ++- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 8 +-- compiler/rustc_hir_typeck/src/lib.rs | 14 +++--- compiler/rustc_hir_typeck/src/writeback.rs | 9 ++-- compiler/rustc_lint/src/builtin.rs | 8 ++- compiler/rustc_middle/src/hir/map.rs | 3 +- compiler/rustc_middle/src/thir.rs | 4 +- compiler/rustc_middle/src/thir/visit.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 6 ++- .../rustc_mir_build/src/builder/expr/into.rs | 17 ++----- compiler/rustc_mir_build/src/builder/mod.rs | 5 +- .../rustc_mir_build/src/check_unsafety.rs | 5 +- compiler/rustc_mir_build/src/thir/cx/expr.rs | 9 +--- compiler/rustc_mir_build/src/thir/cx/mod.rs | 40 ++++++++------- compiler/rustc_mir_build/src/thir/print.rs | 6 +-- compiler/rustc_monomorphize/src/collector.rs | 13 +++-- .../src/operators/numeric_arithmetic.rs | 2 +- .../clippy/clippy_utils/src/hir_utils.rs | 5 +- tests/crashes/111709-2.rs | 15 ------ tests/crashes/111709.rs | 25 ---------- tests/crashes/96304.rs | 6 --- tests/ui/asm/asm-with-nested-closure.rs | 11 ++++ tests/ui/asm/global-asm-with-lifetimes.rs | 8 +++ .../asm/inline-asm-with-lifetimes.bad.stderr | 17 +++++++ tests/ui/asm/inline-asm-with-lifetimes.rs | 22 ++++++++ 37 files changed, 244 insertions(+), 232 deletions(-) delete mode 100644 tests/crashes/111709-2.rs delete mode 100644 tests/crashes/111709.rs delete mode 100644 tests/crashes/96304.rs create mode 100644 tests/ui/asm/asm-with-nested-closure.rs create mode 100644 tests/ui/asm/global-asm-with-lifetimes.rs create mode 100644 tests/ui/asm/inline-asm-with-lifetimes.bad.stderr create mode 100644 tests/ui/asm/inline-asm-with-lifetimes.rs diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 96c230ec243a2..cfd32fc066f41 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -1,13 +1,12 @@ use std::collections::hash_map::Entry; use std::fmt::Write; -use rustc_ast::ptr::P; use rustc_ast::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_session::parse::feature_err; -use rustc_span::{Span, kw, sym}; +use rustc_span::{Span, sym}; use rustc_target::asm; use super::LoweringContext; @@ -230,20 +229,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { tokens: None, }; - // Wrap the expression in an AnonConst. - let parent_def_id = self.current_hir_id_owner.def_id; - let node_id = self.next_node_id(); - self.create_def( - parent_def_id, - node_id, - kw::Empty, - DefKind::AnonConst, - *op_sp, - ); - let anon_const = AnonConst { id: node_id, value: P(expr) }; - hir::InlineAsmOperand::SymFn { - anon_const: self.lower_anon_const_to_anon_const(&anon_const), - } + hir::InlineAsmOperand::SymFn { expr: self.lower_expr(&expr) } } } InlineAsmOperand::Label { block } => { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index a7a03f7d6db91..1d3db64b47ed9 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -252,7 +252,10 @@ impl<'hir> LoweringContext<'_, 'hir> { .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))), }, ItemKind::GlobalAsm(asm) => { - hir::ItemKind::GlobalAsm { asm: self.lower_inline_asm(span, asm) } + let asm = self.lower_inline_asm(span, asm); + let fake_body = + self.lower_body(|this| (&[], this.expr(span, hir::ExprKind::InlineAsm(asm)))); + hir::ItemKind::GlobalAsm { asm, fake_body } } ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty, .. }) => { // We lower diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 9a68eeb3326eb..a71ca37bf1306 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -126,6 +126,11 @@ pub(crate) enum DefiningTy<'tcx> { /// The MIR represents an inline const. The signature has no inputs and a /// single return value found via `InlineConstArgs::ty`. InlineConst(DefId, GenericArgsRef<'tcx>), + + // Fake body for a global asm. Not particularly useful or interesting, + // but we need it so we can properly store the typeck results of the asm + // operands, which aren't associated with a body otherwise. + GlobalAsm(DefId), } impl<'tcx> DefiningTy<'tcx> { @@ -138,9 +143,10 @@ impl<'tcx> DefiningTy<'tcx> { DefiningTy::Closure(_, args) => args.as_closure().upvar_tys(), DefiningTy::CoroutineClosure(_, args) => args.as_coroutine_closure().upvar_tys(), DefiningTy::Coroutine(_, args) => args.as_coroutine().upvar_tys(), - DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => { - ty::List::empty() - } + DefiningTy::FnDef(..) + | DefiningTy::Const(..) + | DefiningTy::InlineConst(..) + | DefiningTy::GlobalAsm(_) => ty::List::empty(), } } @@ -152,7 +158,10 @@ impl<'tcx> DefiningTy<'tcx> { DefiningTy::Closure(..) | DefiningTy::CoroutineClosure(..) | DefiningTy::Coroutine(..) => 1, - DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => 0, + DefiningTy::FnDef(..) + | DefiningTy::Const(..) + | DefiningTy::InlineConst(..) + | DefiningTy::GlobalAsm(_) => 0, } } @@ -171,7 +180,8 @@ impl<'tcx> DefiningTy<'tcx> { | DefiningTy::Coroutine(def_id, ..) | DefiningTy::FnDef(def_id, ..) | DefiningTy::Const(def_id, ..) - | DefiningTy::InlineConst(def_id, ..) => def_id, + | DefiningTy::InlineConst(def_id, ..) + | DefiningTy::GlobalAsm(def_id) => def_id, } } } @@ -411,6 +421,7 @@ impl<'tcx> UniversalRegions<'tcx> { tcx.def_path_str_with_args(def_id, args), )); } + DefiningTy::GlobalAsm(_) => unreachable!(), } } @@ -633,6 +644,8 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { DefiningTy::InlineConst(self.mir_def.to_def_id(), args) } } + + BodyOwnerKind::GlobalAsm => DefiningTy::GlobalAsm(self.mir_def.to_def_id()), } } @@ -666,6 +679,8 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { } DefiningTy::FnDef(_, args) | DefiningTy::Const(_, args) => args, + + DefiningTy::GlobalAsm(_) => ty::List::empty(), }; let global_mapping = iter::once((tcx.lifetimes.re_static, fr_static)); @@ -802,6 +817,10 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let ty = args.as_inline_const().ty(); ty::Binder::dummy(tcx.mk_type_list(&[ty])) } + + DefiningTy::GlobalAsm(def_id) => { + ty::Binder::dummy(tcx.mk_type_list(&[tcx.type_of(def_id).instantiate_identity()])) + } }; // FIXME(#129952): We probably want a more principled approach here. diff --git a/compiler/rustc_codegen_cranelift/src/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs index 0a23f63d6ba9b..9ea92c300f898 100644 --- a/compiler/rustc_codegen_cranelift/src/global_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/global_asm.rs @@ -16,7 +16,7 @@ use crate::prelude::*; pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, item_id: ItemId) { let item = tcx.hir_item(item_id); - if let rustc_hir::ItemKind::GlobalAsm { asm } = item.kind { + if let rustc_hir::ItemKind::GlobalAsm { asm, .. } = item.kind { let is_x86 = matches!(tcx.sess.asm_arch.unwrap(), InlineAsmArch::X86 | InlineAsmArch::X86_64); @@ -55,7 +55,7 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, } } } - InlineAsmOperand::SymFn { anon_const } => { + InlineAsmOperand::SymFn { expr } => { if cfg!(not(feature = "inline_asm_sym")) { tcx.dcx().span_err( item.span, @@ -63,7 +63,7 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, ); } - let ty = tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id); + let ty = tcx.typeck(item_id.owner_id).expr_ty(expr); let instance = match ty.kind() { &ty::FnDef(def_id, args) => Instance::new(def_id, args), _ => span_bug!(op_sp, "asm sym is not a function"), diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs index a4d5f8bb7017a..f6af889fd6ecb 100644 --- a/compiler/rustc_codegen_ssa/src/mono_item.rs +++ b/compiler/rustc_codegen_ssa/src/mono_item.rs @@ -36,7 +36,7 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> { } MonoItem::GlobalAsm(item_id) => { let item = cx.tcx().hir_item(item_id); - if let hir::ItemKind::GlobalAsm { asm } = item.kind { + if let hir::ItemKind::GlobalAsm { asm, .. } = item.kind { let operands: Vec<_> = asm .operands .iter() @@ -71,11 +71,8 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> { } } } - hir::InlineAsmOperand::SymFn { ref anon_const } => { - let ty = cx - .tcx() - .typeck_body(anon_const.body) - .node_type(anon_const.hir_id); + hir::InlineAsmOperand::SymFn { expr } => { + let ty = cx.tcx().typeck(item_id.owner_id).expr_ty(expr); let instance = match ty.kind() { &ty::FnDef(def_id, args) => Instance::new(def_id, args), _ => span_bug!(*op_sp, "asm sym is not a function"), diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 7cd3037278326..61f64e62058fc 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1913,13 +1913,18 @@ pub enum BodyOwnerKind { /// Initializer of a `static` item. Static(Mutability), + + /// Fake body for a global asm to store its const-like value types. + GlobalAsm, } impl BodyOwnerKind { pub fn is_fn_or_closure(self) -> bool { match self { BodyOwnerKind::Fn | BodyOwnerKind::Closure => true, - BodyOwnerKind::Const { .. } | BodyOwnerKind::Static(_) => false, + BodyOwnerKind::Const { .. } | BodyOwnerKind::Static(_) | BodyOwnerKind::GlobalAsm => { + false + } } } } @@ -3420,7 +3425,7 @@ pub enum InlineAsmOperand<'hir> { anon_const: &'hir AnonConst, }, SymFn { - anon_const: &'hir AnonConst, + expr: &'hir Expr<'hir>, }, SymStatic { path: QPath<'hir>, @@ -3848,7 +3853,7 @@ impl<'hir> Item<'hir> { expect_foreign_mod, (ExternAbi, &'hir [ForeignItemRef]), ItemKind::ForeignMod { abi, items }, (*abi, items); - expect_global_asm, &'hir InlineAsm<'hir>, ItemKind::GlobalAsm { asm }, asm; + expect_global_asm, &'hir InlineAsm<'hir>, ItemKind::GlobalAsm { asm, .. }, asm; expect_ty_alias, (&'hir Ty<'hir>, &'hir Generics<'hir>), ItemKind::TyAlias(ty, generics), (ty, generics); @@ -4015,7 +4020,15 @@ pub enum ItemKind<'hir> { /// An external module, e.g. `extern { .. }`. ForeignMod { abi: ExternAbi, items: &'hir [ForeignItemRef] }, /// Module-level inline assembly (from `global_asm!`). - GlobalAsm { asm: &'hir InlineAsm<'hir> }, + GlobalAsm { + asm: &'hir InlineAsm<'hir>, + /// A fake body which stores typeck results for the global asm's sym_fn + /// operands, which are represented as path expressions. This body contains + /// a single [`ExprKind::InlineAsm`] which points to the asm in the field + /// above, and which is typechecked like a inline asm expr just for the + /// typeck results. + fake_body: BodyId, + }, /// A type alias, e.g., `type Foo = Bar`. TyAlias(&'hir Ty<'hir>, &'hir Generics<'hir>), /// An enum definition, e.g., `enum Foo {C, D}`. @@ -4540,6 +4553,10 @@ impl<'hir> Node<'hir> { .. }) => Some((owner_id.def_id, *body)), + Node::Item(Item { + owner_id, kind: ItemKind::GlobalAsm { asm: _, fake_body }, .. + }) => Some((owner_id.def_id, *fake_body)), + Node::Expr(Expr { kind: ExprKind::Closure(Closure { def_id, body, .. }), .. }) => { Some((*def_id, *body)) } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 5a002423a0c9e..89a58e947cb56 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -573,9 +573,13 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V:: try_visit!(visitor.visit_id(item.hir_id())); walk_list!(visitor, visit_foreign_item_ref, items); } - ItemKind::GlobalAsm { asm } => { + ItemKind::GlobalAsm { asm: _, fake_body } => { try_visit!(visitor.visit_id(item.hir_id())); - try_visit!(visitor.visit_inline_asm(asm, item.hir_id())); + // Visit the fake body, which contains the asm statement. + // Therefore we should not visit the asm statement again + // outside of the body, or some visitors won't have their + // typeck results set correctly. + try_visit!(visitor.visit_nested_body(fake_body)); } ItemKind::TyAlias(ref ty, ref generics) => { try_visit!(visitor.visit_id(item.hir_id())); @@ -1442,10 +1446,12 @@ pub fn walk_inline_asm<'v, V: Visitor<'v>>( try_visit!(visitor.visit_expr(in_expr)); visit_opt!(visitor, visit_expr, out_expr); } - InlineAsmOperand::Const { anon_const, .. } - | InlineAsmOperand::SymFn { anon_const, .. } => { + InlineAsmOperand::Const { anon_const, .. } => { try_visit!(visitor.visit_anon_const(anon_const)); } + InlineAsmOperand::SymFn { expr, .. } => { + try_visit!(visitor.visit_expr(expr)); + } InlineAsmOperand::SymStatic { path, .. } => { try_visit!(visitor.visit_qpath(path, id, *op_sp)); } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 0d34b657dfc30..3236e0a3644d9 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -15,7 +15,6 @@ use rustc_lint_defs::builtin::{ use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_bound_vars::ResolvedArg; use rustc_middle::middle::stability::EvalResult; -use rustc_middle::span_bug; use rustc_middle::ty::error::TypeErrorToStringExt; use rustc_middle::ty::fold::{BottomUpFolder, fold_regions}; use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES}; @@ -35,7 +34,6 @@ use {rustc_attr_parsing as attr, rustc_hir as hir}; use super::compare_impl_item::check_type_bounds; use super::*; -use crate::check::intrinsicck::InlineAsmCtxt; pub fn check_abi(tcx: TyCtxt<'_>, span: Span, abi: ExternAbi) { if !tcx.sess.target.is_abi_supported(abi) { @@ -895,13 +893,6 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { } } } - DefKind::GlobalAsm => { - let it = tcx.hir().expect_item(def_id); - let hir::ItemKind::GlobalAsm { asm } = it.kind else { - span_bug!(it.span, "DefKind::GlobalAsm but got {:#?}", it) - }; - InlineAsmCtxt::new_global_asm(tcx, def_id).check_asm(asm); - } _ => {} } } diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index 00f2d46931fa6..e1727fc48a833 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, LangItem}; use rustc_middle::bug; -use rustc_middle::ty::{self, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy}; +use rustc_middle::ty::{self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy}; use rustc_session::lint; use rustc_span::def_id::LocalDefId; use rustc_span::{Symbol, sym}; @@ -30,7 +30,11 @@ enum NonAsmTypeReason<'tcx> { } impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { - pub fn new_global_asm(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { + pub fn new( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, + get_operand_ty: impl Fn(&hir::Expr<'tcx>) -> Ty<'tcx> + 'a, + ) -> Self { InlineAsmCtxt { tcx, typing_env: ty::TypingEnv { @@ -38,23 +42,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { param_env: ty::ParamEnv::empty(), }, target_features: tcx.asm_target_features(def_id), - expr_ty: Box::new(|e| bug!("asm operand in global asm: {e:?}")), - } - } - - // FIXME(#132279): This likely causes us to incorrectly handle opaque types in their - // defining scope. - pub fn new_in_fn( - tcx: TyCtxt<'tcx>, - typing_env: ty::TypingEnv<'tcx>, - def_id: LocalDefId, - expr_ty: impl Fn(&hir::Expr<'tcx>) -> Ty<'tcx> + 'a, - ) -> Self { - InlineAsmCtxt { - tcx, - typing_env, - target_features: tcx.asm_target_features(def_id), - expr_ty: Box::new(expr_ty), + expr_ty: Box::new(get_operand_ty), } } @@ -492,11 +480,25 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { ); } // Typeck has checked that SymFn refers to a function. - hir::InlineAsmOperand::SymFn { anon_const } => { - debug_assert_matches!( - self.tcx.type_of(anon_const.def_id).instantiate_identity().kind(), - ty::Error(_) | ty::FnDef(..) - ); + hir::InlineAsmOperand::SymFn { expr } => { + let ty = self.expr_ty(expr); + match ty.kind() { + ty::FnDef(..) => {} + ty::Error(_) => {} + _ => { + self.tcx + .dcx() + .struct_span_err(op_sp, "invalid `sym` operand") + .with_span_label( + expr.span, + format!("is {} `{}`", ty.kind().article(), ty), + ) + .with_help( + "`sym` operands must refer to either a function or a static", + ) + .emit(); + } + } } // AST lowering guarantees that SymStatic points to a static. hir::InlineAsmOperand::SymStatic { .. } => {} diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index a363076b75ac1..2cdd9a3a9348a 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -189,8 +189,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { // Exclude `GlobalAsm` here which cannot have generics. Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. }) if asm.operands.iter().any(|(op, _op_sp)| match op { - hir::InlineAsmOperand::Const { anon_const } - | hir::InlineAsmOperand::SymFn { anon_const } => { + hir::InlineAsmOperand::Const { anon_const } => { anon_const.hir_id == hir_id } _ => false, diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 19b78f48cfc04..37c9e0610912f 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -35,13 +35,6 @@ fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx let parent_node_id = tcx.parent_hir_id(hir_id); let parent_node = tcx.hir_node(parent_node_id); - let find_sym_fn = |&(op, op_sp)| match op { - hir::InlineAsmOperand::SymFn { anon_const } if anon_const.hir_id == hir_id => { - Some((anon_const, op_sp)) - } - _ => None, - }; - let find_const = |&(op, op_sp)| match op { hir::InlineAsmOperand::Const { anon_const } if anon_const.hir_id == hir_id => { Some((anon_const, op_sp)) @@ -59,31 +52,7 @@ fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx // Anon consts outside the type system. Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. }) - | Node::Item(&Item { kind: ItemKind::GlobalAsm { asm }, .. }) - if let Some((anon_const, op_sp)) = asm.operands.iter().find_map(find_sym_fn) => - { - let ty = tcx.typeck(def_id).node_type(hir_id); - - match ty.kind() { - ty::Error(_) => ty, - ty::FnDef(..) => ty, - _ => { - let guar = tcx - .dcx() - .struct_span_err(op_sp, "invalid `sym` operand") - .with_span_label( - tcx.def_span(anon_const.def_id), - format!("is {} `{}`", ty.kind().article(), ty), - ) - .with_help("`sym` operands must refer to either a function or a static") - .emit(); - - Ty::new_error(tcx, guar) - } - } - } - Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. }) - | Node::Item(&Item { kind: ItemKind::GlobalAsm { asm }, .. }) + | Node::Item(&Item { kind: ItemKind::GlobalAsm { asm, .. }, .. }) if let Some((anon_const, op_sp)) = asm.operands.iter().find_map(find_const) => { let ty = tcx.typeck(def_id).node_type(hir_id); @@ -313,12 +282,12 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ let args = ty::GenericArgs::identity_for_item(tcx, def_id); Ty::new_adt(tcx, def, args) } + ItemKind::GlobalAsm { .. } => tcx.typeck(def_id).node_type(hir_id), ItemKind::Trait(..) | ItemKind::TraitAlias(..) | ItemKind::Macro(..) | ItemKind::Mod(..) | ItemKind::ForeignMod { .. } - | ItemKind::GlobalAsm { .. } | ItemKind::ExternCrate(..) | ItemKind::Use(..) => { span_bug!(item.span, "compute_type_of_item: unexpected item type: {:?}", item.kind); diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index b485b426c2882..b9cdf3ddc346a 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -692,7 +692,7 @@ impl<'a> State<'a> { } self.bclose(item.span); } - hir::ItemKind::GlobalAsm { asm } => { + hir::ItemKind::GlobalAsm { asm, .. } => { self.head("global_asm!"); self.print_inline_asm(asm); self.end() @@ -1431,10 +1431,10 @@ impl<'a> State<'a> { s.space(); s.print_anon_const(anon_const); } - hir::InlineAsmOperand::SymFn { ref anon_const } => { + hir::InlineAsmOperand::SymFn { ref expr } => { s.word("sym_fn"); s.space(); - s.print_anon_const(anon_const); + s.print_expr(expr); } hir::InlineAsmOperand::SymStatic { ref path, def_id: _ } => { s.word("sym_static"); diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 277396da19c13..0c71ef4655c5c 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -3763,7 +3763,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut diverge = asm.asm_macro.diverges(asm.options); for (op, _op_sp) in asm.operands { - match op { + match *op { hir::InlineAsmOperand::In { expr, .. } => { self.check_expr_asm_operand(expr, true); } @@ -3778,10 +3778,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_expr_asm_operand(out_expr, false); } } + hir::InlineAsmOperand::SymFn { expr } => { + self.check_expr(expr); + } // `AnonConst`s have their own body and is type-checked separately. // As they don't flow into the type system we don't need them to // be well-formed. - hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymFn { .. } => {} + hir::InlineAsmOperand::Const { .. } => {} hir::InlineAsmOperand::SymStatic { .. } => {} hir::InlineAsmOperand::Label { block } => { let previous_diverges = self.diverges.get(); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index bce9fbbd6d1f1..120a43576e814 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -110,13 +110,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.erase_regions(ty) } }; - InlineAsmCtxt::new_in_fn( - self.tcx, - self.infcx.typing_env(self.param_env), - enclosing_id, - expr_ty, - ) - .check_asm(asm); + InlineAsmCtxt::new(self.tcx, enclosing_id, expr_ty).check_asm(asm); } } diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index c1ed5b0aa5074..0130ad775d9e7 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -133,7 +133,12 @@ fn typeck_with_inspect<'tcx>( } let mut fcx = FnCtxt::new(&root_ctxt, param_env, def_id); - if let Some(hir::FnSig { header, decl, .. }) = node.fn_sig() { + if let hir::Node::Item(hir::Item { kind: hir::ItemKind::GlobalAsm { .. }, .. }) = node { + // Check the fake body of a global ASM. There's not much to do here except + // for visit the asm expr of the body. + let ty = fcx.check_expr(body.value); + fcx.write_ty(id, ty); + } else if let Some(hir::FnSig { header, decl, .. }) = node.fn_sig() { let fn_sig = if decl.output.is_suggestable_infer_ty().is_some() { // In the case that we're recovering `fn() -> W<_>` or some other return // type that has an infer in it, lower the type directly so that it'll @@ -277,12 +282,9 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti Some(fcx.next_ty_var(span)) } Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), span, .. }) - | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm { asm }, span, .. }) => { + | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm { asm, .. }, span, .. }) => { asm.operands.iter().find_map(|(op, _op_sp)| match op { - hir::InlineAsmOperand::Const { anon_const } - | hir::InlineAsmOperand::SymFn { anon_const } - if anon_const.hir_id == id => - { + hir::InlineAsmOperand::Const { anon_const } if anon_const.hir_id == id => { Some(fcx.next_ty_var(span)) } _ => None, diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 8c50cc59c1d5e..3e9ce0e11e402 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -48,13 +48,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for param in body.params { wbcx.visit_node_id(param.pat.span, param.hir_id); } - // Type only exists for constants and statics, not functions. match self.tcx.hir_body_owner_kind(item_def_id) { - hir::BodyOwnerKind::Const { .. } | hir::BodyOwnerKind::Static(_) => { + // Visit the type of a const or static, which is used during THIR building. + hir::BodyOwnerKind::Const { .. } + | hir::BodyOwnerKind::Static(_) + | hir::BodyOwnerKind::GlobalAsm => { let item_hir_id = self.tcx.local_def_id_to_hir_id(item_def_id); wbcx.visit_node_id(body.value.span, item_hir_id); } - hir::BodyOwnerKind::Closure | hir::BodyOwnerKind::Fn => (), + // For closures and consts, we already plan to visit liberated signatures. + hir::BodyOwnerKind::Closure | hir::BodyOwnerKind::Fn => {} } wbcx.visit_body(body); wbcx.visit_min_capture_map(); diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index b5f09ff346a7a..6c5a2dcd1460e 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2909,7 +2909,13 @@ enum AsmLabelKind { impl<'tcx> LateLintPass<'tcx> for AsmLabels { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { if let hir::Expr { - kind: hir::ExprKind::InlineAsm(hir::InlineAsm { template_strs, options, .. }), + kind: + hir::ExprKind::InlineAsm(hir::InlineAsm { + asm_macro: AsmMacro::Asm | AsmMacro::NakedAsm, + template_strs, + options, + .. + }), .. } = expr { diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index 832f802661450..ec046d82ef645 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -305,6 +305,7 @@ impl<'tcx> TyCtxt<'tcx> { DefKind::Static { safety: _, mutability, nested: false } => { BodyOwnerKind::Static(mutability) } + DefKind::GlobalAsm => BodyOwnerKind::GlobalAsm, dk => bug!("{:?} is not a body node: {:?}", def_id, dk), } } @@ -327,7 +328,7 @@ impl<'tcx> TyCtxt<'tcx> { ConstContext::ConstFn } BodyOwnerKind::Fn if self.is_const_default_method(def_id) => ConstContext::ConstFn, - BodyOwnerKind::Fn | BodyOwnerKind::Closure => return None, + BodyOwnerKind::Fn | BodyOwnerKind::Closure | BodyOwnerKind::GlobalAsm => return None, }; Some(ccx) diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 98cc00c367cfe..6a2672ac02b75 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -94,6 +94,7 @@ thir_with_elements! { pub enum BodyTy<'tcx> { Const(Ty<'tcx>), Fn(FnSig<'tcx>), + GlobalAsm(Ty<'tcx>), } /// Description of a type-checked function parameter. @@ -605,8 +606,7 @@ pub enum InlineAsmOperand<'tcx> { span: Span, }, SymFn { - value: mir::Const<'tcx>, - span: Span, + value: ExprId, }, SymStatic { def_id: DefId, diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index 13b8af55e518e..e347a64e45d0f 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -172,7 +172,7 @@ pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>( } Out { expr: None, reg: _, late: _ } | Const { value: _, span: _ } - | SymFn { value: _, span: _ } + | SymFn { value: _ } | SymStatic { def_id: _ } => {} Label { block } => visitor.visit_block(&visitor.thir()[*block]), } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 32a9e67f9ad53..361e204fb0f0f 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1472,7 +1472,11 @@ impl<'tcx> TyCtxt<'tcx> { self.codegen_fn_attrs(def_id) } else if matches!( def_kind, - DefKind::AnonConst | DefKind::AssocConst | DefKind::Const | DefKind::InlineConst + DefKind::AnonConst + | DefKind::AssocConst + | DefKind::Const + | DefKind::InlineConst + | DefKind::GlobalAsm ) { CodegenFnAttrs::EMPTY } else { diff --git a/compiler/rustc_mir_build/src/builder/expr/into.rs b/compiler/rustc_mir_build/src/builder/expr/into.rs index 65dd061003d8d..72443e2f60ddc 100644 --- a/compiler/rustc_mir_build/src/builder/expr/into.rs +++ b/compiler/rustc_mir_build/src/builder/expr/into.rs @@ -482,15 +482,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }), } } - thir::InlineAsmOperand::SymFn { value, span } => { - mir::InlineAsmOperand::SymFn { - value: Box::new(ConstOperand { - span, - user_ty: None, - const_: value, - }), - } - } + thir::InlineAsmOperand::SymFn { value } => mir::InlineAsmOperand::SymFn { + value: Box::new(this.as_constant(&this.thir[value])), + }, thir::InlineAsmOperand::SymStatic { def_id } => { mir::InlineAsmOperand::SymStatic { def_id } } @@ -518,10 +512,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } let asm_macro = match asm_macro { - AsmMacro::Asm => InlineAsmMacro::Asm, - AsmMacro::GlobalAsm => { - span_bug!(expr_span, "unexpected global_asm! in inline asm") - } + AsmMacro::Asm | AsmMacro::GlobalAsm => InlineAsmMacro::Asm, AsmMacro::NakedAsm => InlineAsmMacro::NakedAsm, }; diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index 4348b7a4b4cc9..949559549345f 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -61,7 +61,9 @@ pub fn build_mir<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Body<'tcx> { Ok((thir, expr)) => { let build_mir = |thir: &Thir<'tcx>| match thir.body_type { thir::BodyTy::Fn(fn_sig) => construct_fn(tcx, def, thir, expr, fn_sig), - thir::BodyTy::Const(ty) => construct_const(tcx, def, thir, expr, ty), + thir::BodyTy::Const(ty) | thir::BodyTy::GlobalAsm(ty) => { + construct_const(tcx, def, thir, expr, ty) + } }; // this must run before MIR dump, because @@ -576,6 +578,7 @@ fn construct_const<'a, 'tcx>( let span = tcx.def_span(def); (span, span) } + Node::Item(hir::Item { kind: hir::ItemKind::GlobalAsm { .. }, span, .. }) => (*span, *span), _ => span_bug!(tcx.def_span(def), "can't build MIR for {:?}", def), }; diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index d65c2097d226e..c2eafd0a74e65 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -2,6 +2,7 @@ use std::borrow::Cow; use std::mem; use std::ops::Bound; +use rustc_ast::AsmMacro; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::DiagArgValue; use rustc_hir::def::DefKind; @@ -559,7 +560,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { } } ExprKind::InlineAsm(box InlineAsmExpr { - asm_macro: _, + asm_macro: AsmMacro::Asm | AsmMacro::NakedAsm, ref operands, template: _, options: _, @@ -583,7 +584,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { } Out { expr: None, reg: _, late: _ } | Const { value: _, span: _ } - | SymFn { value: _, span: _ } + | SymFn { value: _ } | SymStatic { def_id: _ } => {} Label { block } => { // Label blocks are safe context. diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index d0fca76fcf05d..29bc1d6572dfa 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -739,13 +739,8 @@ impl<'tcx> ThirBuildCx<'tcx> { InlineAsmOperand::Const { value, span } } - hir::InlineAsmOperand::SymFn { ref anon_const } => { - let value = - mir::Const::from_unevaluated(tcx, anon_const.def_id.to_def_id()) - .instantiate_identity(); - let span = tcx.def_span(anon_const.def_id); - - InlineAsmOperand::SymFn { value, span } + hir::InlineAsmOperand::SymFn { expr } => { + InlineAsmOperand::SymFn { value: self.mirror_expr(expr) } } hir::InlineAsmOperand::SymStatic { path: _, def_id } => { InlineAsmOperand::SymStatic { def_id } diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index 7a9f6e4630456..c32082c609ec4 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -76,23 +76,29 @@ impl<'tcx> ThirBuildCx<'tcx> { let hir = tcx.hir(); let hir_id = tcx.local_def_id_to_hir_id(def); - let body_type = if tcx.hir_body_owner_kind(def).is_fn_or_closure() { - // fetch the fully liberated fn signature (that is, all bound - // types/lifetimes replaced) - BodyTy::Fn(typeck_results.liberated_fn_sigs()[hir_id]) - } else { - // Get the revealed type of this const. This is *not* the adjusted - // type of its body, which may be a subtype of this type. For - // example: - // - // fn foo(_: &()) {} - // static X: fn(&'static ()) = foo; - // - // The adjusted type of the body of X is `for<'a> fn(&'a ())` which - // is not the same as the type of X. We need the type of the return - // place to be the type of the constant because NLL typeck will - // equate them. - BodyTy::Const(typeck_results.node_type(hir_id)) + let body_type = match tcx.hir_body_owner_kind(def) { + rustc_hir::BodyOwnerKind::Fn | rustc_hir::BodyOwnerKind::Closure => { + // fetch the fully liberated fn signature (that is, all bound + // types/lifetimes replaced) + BodyTy::Fn(typeck_results.liberated_fn_sigs()[hir_id]) + } + rustc_hir::BodyOwnerKind::Const { .. } | rustc_hir::BodyOwnerKind::Static(_) => { + // Get the revealed type of this const. This is *not* the adjusted + // type of its body, which may be a subtype of this type. For + // example: + // + // fn foo(_: &()) {} + // static X: fn(&'static ()) = foo; + // + // The adjusted type of the body of X is `for<'a> fn(&'a ())` which + // is not the same as the type of X. We need the type of the return + // place to be the type of the constant because NLL typeck will + // equate them. + BodyTy::Const(typeck_results.node_type(hir_id)) + } + rustc_hir::BodyOwnerKind::GlobalAsm => { + BodyTy::GlobalAsm(typeck_results.node_type(hir_id)) + } }; Self { diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index 9ab87dd99ffc0..cd56d93afcf75 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -921,10 +921,10 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { print_indented!(self, format!("span: {:?}", span), depth_lvl + 1); print_indented!(self, "}", depth_lvl + 1); } - InlineAsmOperand::SymFn { value, span } => { + InlineAsmOperand::SymFn { value } => { print_indented!(self, "InlineAsmOperand::SymFn {", depth_lvl); - print_indented!(self, format!("value: {:?}", *value), depth_lvl + 1); - print_indented!(self, format!("span: {:?}", span), depth_lvl + 1); + print_indented!(self, "value: ", depth_lvl + 1); + self.print_expr(*value, depth_lvl + 2); print_indented!(self, "}", depth_lvl + 1); } InlineAsmOperand::SymStatic { def_id } => { diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index bf56f468179d8..694a4dd5b4c4c 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -479,24 +479,23 @@ fn collect_items_rec<'tcx>( recursion_depth_reset = None; let item = tcx.hir_item(item_id); - if let hir::ItemKind::GlobalAsm { asm } = item.kind { + if let hir::ItemKind::GlobalAsm { asm, .. } = item.kind { for (op, op_sp) in asm.operands { - match op { + match *op { hir::InlineAsmOperand::Const { .. } => { // Only constants which resolve to a plain integer // are supported. Therefore the value should not // depend on any other items. } - hir::InlineAsmOperand::SymFn { anon_const } => { - let fn_ty = - tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id); + hir::InlineAsmOperand::SymFn { expr } => { + let fn_ty = tcx.typeck(item_id.owner_id).expr_ty(expr); visit_fn_use(tcx, fn_ty, false, *op_sp, &mut used_items); } hir::InlineAsmOperand::SymStatic { path: _, def_id } => { - let instance = Instance::mono(tcx, *def_id); + let instance = Instance::mono(tcx, def_id); if tcx.should_codegen_locally(instance) { trace!("collecting static {:?}", def_id); - used_items.push(dummy_spanned(MonoItem::Static(*def_id))); + used_items.push(dummy_spanned(MonoItem::Static(def_id))); } } hir::InlineAsmOperand::In { .. } diff --git a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs index cda99a362dcae..c261fd9bd9cb0 100644 --- a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs +++ b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs @@ -82,7 +82,7 @@ impl Context { } self.const_span = Some(body_span); }, - hir::BodyOwnerKind::Fn | hir::BodyOwnerKind::Closure => (), + hir::BodyOwnerKind::Fn | hir::BodyOwnerKind::Closure | hir::BodyOwnerKind::GlobalAsm => (), } } diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 9ee30094d608c..0ac675345ae0c 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -968,7 +968,10 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_expr(out_expr); } }, - InlineAsmOperand::Const { anon_const } | InlineAsmOperand::SymFn { anon_const } => { + InlineAsmOperand::SymFn { expr } => { + self.hash_expr(expr); + } + InlineAsmOperand::Const { anon_const } => { self.hash_body(anon_const.body); }, InlineAsmOperand::SymStatic { path, def_id: _ } => self.hash_qpath(path), diff --git a/tests/crashes/111709-2.rs b/tests/crashes/111709-2.rs deleted file mode 100644 index 6c4fb9f28c7de..0000000000000 --- a/tests/crashes/111709-2.rs +++ /dev/null @@ -1,15 +0,0 @@ -//@ known-bug: #111709 -//@ edition: 2021 - -use core::arch::asm; - -extern "C" fn test() {} - -fn uwu() { - unsafe { - asm!( - "/* {0} */", - sym test::<&mut ()> - ); - } -} diff --git a/tests/crashes/111709.rs b/tests/crashes/111709.rs deleted file mode 100644 index eef375b8924b7..0000000000000 --- a/tests/crashes/111709.rs +++ /dev/null @@ -1,25 +0,0 @@ -//@ known-bug: #111709 -//@ edition:2021 - -use core::arch::asm; - -struct TrapFrame; - -unsafe extern "C" fn _rust_abi_shim1(arg: A, f: fn(A) -> R) -> R { - f(arg) -} - -unsafe extern "C" fn _start_trap() { - extern "Rust" { - fn interrupt(tf: &mut TrapFrame); - } - asm!( - " - la a1, {irq} - call {shim} - ", - shim = sym crate::_rust_abi_shim1::<&mut TrapFrame, ()>, - irq = sym interrupt, - options(noreturn) - ) -} diff --git a/tests/crashes/96304.rs b/tests/crashes/96304.rs deleted file mode 100644 index 637012f45858f..0000000000000 --- a/tests/crashes/96304.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ known-bug: #96304 - -#![feature(asm_sym)] -core::arch::global_asm!("/* {} */", sym<&'static ()>::clone); - -pub fn main() {} diff --git a/tests/ui/asm/asm-with-nested-closure.rs b/tests/ui/asm/asm-with-nested-closure.rs new file mode 100644 index 0000000000000..3a5cd48d5d4df --- /dev/null +++ b/tests/ui/asm/asm-with-nested-closure.rs @@ -0,0 +1,11 @@ +//@ build-pass +//@ needs-asm-support + +fn foo() {} + +core::arch::global_asm!("/* {} */", sym foo::<{ + || {}; + 0 +}>); + +fn main() {} diff --git a/tests/ui/asm/global-asm-with-lifetimes.rs b/tests/ui/asm/global-asm-with-lifetimes.rs new file mode 100644 index 0000000000000..2709ff90fe333 --- /dev/null +++ b/tests/ui/asm/global-asm-with-lifetimes.rs @@ -0,0 +1,8 @@ +//@ build-pass +//@ needs-asm-support + +fn foo() {} + +core::arch::global_asm!("/* {} */", sym foo::<&'static ()>); + +fn main() {} diff --git a/tests/ui/asm/inline-asm-with-lifetimes.bad.stderr b/tests/ui/asm/inline-asm-with-lifetimes.bad.stderr new file mode 100644 index 0000000000000..f04482f9c5916 --- /dev/null +++ b/tests/ui/asm/inline-asm-with-lifetimes.bad.stderr @@ -0,0 +1,17 @@ +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/inline-asm-with-lifetimes.rs:17:26 + | +LL | fn test<'a: 'a, T>() { + | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... +LL | unsafe { +LL | asm!("/* {} */", sym dep::<'a, T> ); + | ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | fn test<'a: 'a, T: 'a>() { + | ++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/asm/inline-asm-with-lifetimes.rs b/tests/ui/asm/inline-asm-with-lifetimes.rs new file mode 100644 index 0000000000000..79def03eeb232 --- /dev/null +++ b/tests/ui/asm/inline-asm-with-lifetimes.rs @@ -0,0 +1,22 @@ +//@ revisions: good bad +//@[good] build-pass +//@ needs-asm-support + +use std::arch::asm; + +// lifetime requirement, we should check it!! +#[cfg(bad)] +fn dep<'a, T: 'a>() {} + +// no lifetime requirement +#[cfg(good)] +fn dep<'a: 'a, T>() {} + +fn test<'a: 'a, T>() { + unsafe { + asm!("/* {} */", sym dep::<'a, T> ); + //[bad]~^ ERROR the parameter type `T` may not live long enough + } +} + +fn main() {} From a5d4c5ccf039ec3d0147294a2d11972579adc73a Mon Sep 17 00:00:00 2001 From: Daniel Paoliello Date: Wed, 13 Nov 2024 13:13:03 -0800 Subject: [PATCH 20/22] Reduce visibility of most items in `rustc_codegen_llvm` --- compiler/rustc_codegen_llvm/src/lib.rs | 6 +- .../rustc_codegen_llvm/src/llvm/archive_ro.rs | 6 +- .../rustc_codegen_llvm/src/llvm/diagnostic.rs | 20 +- .../rustc_codegen_llvm/src/llvm/enzyme_ffi.rs | 2 +- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 180 +++++++++--------- compiler/rustc_codegen_llvm/src/llvm/mod.rs | 20 +- 6 files changed, 121 insertions(+), 113 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index e9e1b644f183e..e5bbcb27d90c7 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -30,7 +30,7 @@ use std::mem::ManuallyDrop; use back::owned_target_machine::OwnedTargetMachine; use back::write::{create_informational_target_machine, create_target_machine}; use errors::{AutoDiffWithoutLTO, ParseTargetMachineConfig}; -pub(crate) use llvm_util::target_features_cfg; +use llvm_util::target_features_cfg; use rustc_ast::expand::allocator::AllocatorKind; use rustc_ast::expand::autodiff_attrs::AutoDiffItem; use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule}; @@ -72,9 +72,7 @@ mod debuginfo; mod declare; mod errors; mod intrinsic; -// FIXME(Zalathar): Fix all the unreachable-pub warnings that would occur if -// this isn't pub, then make it not pub. -pub mod llvm; +mod llvm; mod llvm_util; mod mono_item; mod type_; diff --git a/compiler/rustc_codegen_llvm/src/llvm/archive_ro.rs b/compiler/rustc_codegen_llvm/src/llvm/archive_ro.rs index 63b2b15c5145e..51bcc4d123d31 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/archive_ro.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/archive_ro.rs @@ -5,17 +5,17 @@ use std::{slice, str}; use rustc_fs_util::path_to_c_string; -pub struct ArchiveRO { +pub(crate) struct ArchiveRO { pub raw: &'static mut super::Archive, } unsafe impl Send for ArchiveRO {} -pub struct Iter<'a> { +pub(crate) struct Iter<'a> { raw: &'a mut super::ArchiveIterator<'a>, } -pub struct Child<'a> { +pub(crate) struct Child<'a> { pub raw: &'a mut super::ArchiveChild<'a>, } diff --git a/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs b/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs index 11043b664f526..0e0f2b0eab016 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs @@ -3,13 +3,13 @@ use libc::c_uint; use rustc_span::InnerSpan; -pub use self::Diagnostic::*; -pub use self::OptimizationDiagnosticKind::*; +pub(crate) use self::Diagnostic::*; +use self::OptimizationDiagnosticKind::*; use super::{DiagnosticInfo, SMDiagnostic}; use crate::value::Value; #[derive(Copy, Clone, Debug)] -pub enum OptimizationDiagnosticKind { +pub(crate) enum OptimizationDiagnosticKind { OptimizationRemark, OptimizationMissed, OptimizationAnalysis, @@ -19,9 +19,10 @@ pub enum OptimizationDiagnosticKind { OptimizationRemarkOther, } -pub struct OptimizationDiagnostic<'ll> { +pub(crate) struct OptimizationDiagnostic<'ll> { pub kind: OptimizationDiagnosticKind, pub pass_name: String, + #[expect(dead_code)] pub function: &'ll Value, pub line: c_uint, pub column: c_uint, @@ -73,14 +74,14 @@ impl<'ll> OptimizationDiagnostic<'ll> { } } -pub struct SrcMgrDiagnostic { +pub(crate) struct SrcMgrDiagnostic { pub level: super::DiagnosticLevel, pub message: String, pub source: Option<(String, Vec)>, } impl SrcMgrDiagnostic { - pub unsafe fn unpack(diag: &SMDiagnostic) -> SrcMgrDiagnostic { + pub(crate) unsafe fn unpack(diag: &SMDiagnostic) -> SrcMgrDiagnostic { // Recover the post-substitution assembly code from LLVM for better // diagnostics. let mut have_source = false; @@ -120,7 +121,7 @@ impl SrcMgrDiagnostic { } #[derive(Clone)] -pub struct InlineAsmDiagnostic { +pub(crate) struct InlineAsmDiagnostic { pub level: super::DiagnosticLevel, pub cookie: u64, pub message: String, @@ -158,7 +159,7 @@ impl InlineAsmDiagnostic { } } -pub enum Diagnostic<'ll> { +pub(crate) enum Diagnostic<'ll> { Optimization(OptimizationDiagnostic<'ll>), InlineAsm(InlineAsmDiagnostic), PGO(&'ll DiagnosticInfo), @@ -166,11 +167,12 @@ pub enum Diagnostic<'ll> { Unsupported(&'ll DiagnosticInfo), /// LLVM has other types that we do not wrap here. + #[expect(dead_code)] UnknownDiagnostic(&'ll DiagnosticInfo), } impl<'ll> Diagnostic<'ll> { - pub unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self { + pub(crate) unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self { use super::DiagnosticKind as Dk; unsafe { diff --git a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs index 39bac13a9680c..efd28a6b5535d 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs @@ -30,7 +30,7 @@ extern "C" { #[repr(C)] #[derive(Copy, Clone, PartialEq)] -pub enum LLVMRustVerifierFailureAction { +pub(crate) enum LLVMRustVerifierFailureAction { LLVMAbortProcessAction = 0, LLVMPrintMessageAction = 1, LLVMReturnStatusAction = 2, diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 3b0187b9d37b1..47ff82950517f 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -32,10 +32,10 @@ use crate::llvm; /// In the LLVM-C API, boolean values are passed as `typedef int LLVMBool`, /// which has a different ABI from Rust or C++ `bool`. -pub type Bool = c_int; +pub(crate) type Bool = c_int; -pub const True: Bool = 1 as Bool; -pub const False: Bool = 0 as Bool; +pub(crate) const True: Bool = 1 as Bool; +pub(crate) const False: Bool = 0 as Bool; /// Wrapper for a raw enum value returned from LLVM's C APIs. /// @@ -44,7 +44,7 @@ pub const False: Bool = 0 as Bool; /// value and returns it. Instead, return this raw wrapper, then convert to the /// Rust-side enum explicitly. #[repr(transparent)] -pub struct RawEnum { +pub(crate) struct RawEnum { value: u32, /// We don't own or consume a `T`, but we can produce one. _rust_side_type: PhantomData T>, @@ -64,7 +64,7 @@ impl> RawEnum { #[derive(Copy, Clone, PartialEq)] #[repr(C)] #[allow(dead_code)] // Variants constructed by C++. -pub enum LLVMRustResult { +pub(crate) enum LLVMRustResult { Success, Failure, } @@ -83,7 +83,7 @@ pub enum LLVMRustResult { /// C++ API. #[derive(Copy, Clone, PartialEq)] #[repr(C)] -pub enum ModuleFlagMergeBehavior { +pub(crate) enum ModuleFlagMergeBehavior { Error = 1, Warning = 2, Require = 3, @@ -101,7 +101,7 @@ pub enum ModuleFlagMergeBehavior { /// See #[derive(Copy, Clone, PartialEq, Debug, TryFromU32)] #[repr(C)] -pub enum CallConv { +pub(crate) enum CallConv { CCallConv = 0, FastCallConv = 8, ColdCallConv = 9, @@ -126,7 +126,7 @@ pub enum CallConv { /// Must match the layout of `LLVMLinkage`. #[derive(Copy, Clone, PartialEq, TryFromU32)] #[repr(C)] -pub enum Linkage { +pub(crate) enum Linkage { ExternalLinkage = 0, AvailableExternallyLinkage = 1, LinkOnceAnyLinkage = 2, @@ -153,7 +153,7 @@ pub enum Linkage { /// Must match the layout of `LLVMVisibility`. #[repr(C)] #[derive(Copy, Clone, PartialEq, TryFromU32)] -pub enum Visibility { +pub(crate) enum Visibility { Default = 0, Hidden = 1, Protected = 2, @@ -171,8 +171,9 @@ impl Visibility { /// LLVMUnnamedAddr #[repr(C)] -pub enum UnnamedAddr { +pub(crate) enum UnnamedAddr { No, + #[expect(dead_code)] Local, Global, } @@ -180,7 +181,7 @@ pub enum UnnamedAddr { /// LLVMDLLStorageClass #[derive(Copy, Clone)] #[repr(C)] -pub enum DLLStorageClass { +pub(crate) enum DLLStorageClass { #[allow(dead_code)] Default = 0, DllImport = 1, // Function to be imported from DLL. @@ -193,7 +194,8 @@ pub enum DLLStorageClass { /// though it is not ABI compatible (since it's a C++ enum) #[repr(C)] #[derive(Copy, Clone, Debug)] -pub enum AttributeKind { +#[expect(dead_code, reason = "Some variants are unused, but are kept to match the C++")] +pub(crate) enum AttributeKind { AlwaysInline = 0, ByVal = 1, Cold = 2, @@ -241,7 +243,7 @@ pub enum AttributeKind { /// LLVMIntPredicate #[derive(Copy, Clone)] #[repr(C)] -pub enum IntPredicate { +pub(crate) enum IntPredicate { IntEQ = 32, IntNE = 33, IntUGT = 34, @@ -275,7 +277,7 @@ impl IntPredicate { /// LLVMRealPredicate #[derive(Copy, Clone)] #[repr(C)] -pub enum RealPredicate { +pub(crate) enum RealPredicate { RealPredicateFalse = 0, RealOEQ = 1, RealOGT = 2, @@ -321,7 +323,8 @@ impl RealPredicate { /// LLVMTypeKind #[derive(Copy, Clone, PartialEq, Debug)] #[repr(C)] -pub enum TypeKind { +#[expect(dead_code, reason = "Some variants are unused, but are kept to match LLVM-C")] +pub(crate) enum TypeKind { Void = 0, Half = 1, Float = 2, @@ -373,7 +376,7 @@ impl TypeKind { /// LLVMAtomicRmwBinOp #[derive(Copy, Clone)] #[repr(C)] -pub enum AtomicRmwBinOp { +pub(crate) enum AtomicRmwBinOp { AtomicXchg = 0, AtomicAdd = 1, AtomicSub = 2, @@ -409,7 +412,7 @@ impl AtomicRmwBinOp { /// LLVMAtomicOrdering #[derive(Copy, Clone)] #[repr(C)] -pub enum AtomicOrdering { +pub(crate) enum AtomicOrdering { #[allow(dead_code)] NotAtomic = 0, Unordered = 1, @@ -438,7 +441,7 @@ impl AtomicOrdering { /// LLVMRustFileType #[derive(Copy, Clone)] #[repr(C)] -pub enum FileType { +pub(crate) enum FileType { AssemblyFile, ObjectFile, } @@ -446,7 +449,8 @@ pub enum FileType { /// LLVMMetadataType #[derive(Copy, Clone)] #[repr(C)] -pub enum MetadataType { +#[expect(dead_code, reason = "Some variants are unused, but are kept to match LLVM-C")] +pub(crate) enum MetadataType { MD_dbg = 0, MD_tbaa = 1, MD_prof = 2, @@ -470,7 +474,7 @@ pub enum MetadataType { /// LLVMRustAsmDialect #[derive(Copy, Clone, PartialEq)] #[repr(C)] -pub enum AsmDialect { +pub(crate) enum AsmDialect { Att, Intel, } @@ -478,7 +482,7 @@ pub enum AsmDialect { /// LLVMRustCodeGenOptLevel #[derive(Copy, Clone, PartialEq)] #[repr(C)] -pub enum CodeGenOptLevel { +pub(crate) enum CodeGenOptLevel { None, Less, Default, @@ -487,7 +491,7 @@ pub enum CodeGenOptLevel { /// LLVMRustPassBuilderOptLevel #[repr(C)] -pub enum PassBuilderOptLevel { +pub(crate) enum PassBuilderOptLevel { O0, O1, O2, @@ -499,7 +503,7 @@ pub enum PassBuilderOptLevel { /// LLVMRustOptStage #[derive(PartialEq)] #[repr(C)] -pub enum OptStage { +pub(crate) enum OptStage { PreLinkNoLTO, PreLinkThinLTO, PreLinkFatLTO, @@ -509,7 +513,7 @@ pub enum OptStage { /// LLVMRustSanitizerOptions #[repr(C)] -pub struct SanitizerOptions { +pub(crate) struct SanitizerOptions { pub sanitize_address: bool, pub sanitize_address_recover: bool, pub sanitize_cfi: bool, @@ -530,7 +534,7 @@ pub struct SanitizerOptions { /// LLVMRustRelocModel #[derive(Copy, Clone, PartialEq)] #[repr(C)] -pub enum RelocModel { +pub(crate) enum RelocModel { Static, PIC, DynamicNoPic, @@ -542,7 +546,7 @@ pub enum RelocModel { /// LLVMRustFloatABI #[derive(Copy, Clone, PartialEq)] #[repr(C)] -pub enum FloatAbi { +pub(crate) enum FloatAbi { Default, Soft, Hard, @@ -551,7 +555,7 @@ pub enum FloatAbi { /// LLVMRustCodeModel #[derive(Copy, Clone)] #[repr(C)] -pub enum CodeModel { +pub(crate) enum CodeModel { Tiny, Small, Kernel, @@ -564,7 +568,7 @@ pub enum CodeModel { #[derive(Copy, Clone)] #[repr(C)] #[allow(dead_code)] // Variants constructed by C++. -pub enum DiagnosticKind { +pub(crate) enum DiagnosticKind { Other, InlineAsm, StackSize, @@ -587,7 +591,7 @@ pub enum DiagnosticKind { #[derive(Copy, Clone)] #[repr(C)] #[allow(dead_code)] // Variants constructed by C++. -pub enum DiagnosticLevel { +pub(crate) enum DiagnosticLevel { Error, Warning, Note, @@ -597,7 +601,7 @@ pub enum DiagnosticLevel { /// LLVMRustArchiveKind #[derive(Copy, Clone)] #[repr(C)] -pub enum ArchiveKind { +pub(crate) enum ArchiveKind { K_GNU, K_BSD, K_DARWIN, @@ -607,15 +611,15 @@ pub enum ArchiveKind { unsafe extern "C" { // LLVMRustThinLTOData - pub type ThinLTOData; + pub(crate) type ThinLTOData; // LLVMRustThinLTOBuffer - pub type ThinLTOBuffer; + pub(crate) type ThinLTOBuffer; } /// LLVMRustThinLTOModule #[repr(C)] -pub struct ThinLTOModule { +pub(crate) struct ThinLTOModule { pub identifier: *const c_char, pub data: *const u8, pub len: usize, @@ -624,7 +628,8 @@ pub struct ThinLTOModule { /// LLVMThreadLocalMode #[derive(Copy, Clone)] #[repr(C)] -pub enum ThreadLocalMode { +pub(crate) enum ThreadLocalMode { + #[expect(dead_code)] NotThreadLocal, GeneralDynamic, LocalDynamic, @@ -635,7 +640,7 @@ pub enum ThreadLocalMode { /// LLVMRustChecksumKind #[derive(Copy, Clone)] #[repr(C)] -pub enum ChecksumKind { +pub(crate) enum ChecksumKind { None, MD5, SHA1, @@ -645,7 +650,7 @@ pub enum ChecksumKind { /// LLVMRustMemoryEffects #[derive(Copy, Clone)] #[repr(C)] -pub enum MemoryEffects { +pub(crate) enum MemoryEffects { None, ReadOnly, InaccessibleMemOnly, @@ -654,7 +659,8 @@ pub enum MemoryEffects { /// LLVMOpcode #[derive(Copy, Clone, PartialEq, Eq)] #[repr(C)] -pub enum Opcode { +#[expect(dead_code, reason = "Some variants are unused, but are kept to match LLVM-C")] +pub(crate) enum Opcode { Ret = 1, Br = 2, Switch = 3, @@ -735,48 +741,48 @@ struct InvariantOpaque<'a> { // Opaque pointer types unsafe extern "C" { - pub type Module; - pub type Context; - pub type Type; - pub type Value; - pub type ConstantInt; - pub type Attribute; - pub type Metadata; - pub type BasicBlock; - pub type Comdat; + pub(crate) type Module; + pub(crate) type Context; + pub(crate) type Type; + pub(crate) type Value; + pub(crate) type ConstantInt; + pub(crate) type Attribute; + pub(crate) type Metadata; + pub(crate) type BasicBlock; + pub(crate) type Comdat; } #[repr(C)] -pub struct Builder<'a>(InvariantOpaque<'a>); +pub(crate) struct Builder<'a>(InvariantOpaque<'a>); #[repr(C)] -pub struct PassManager<'a>(InvariantOpaque<'a>); +pub(crate) struct PassManager<'a>(InvariantOpaque<'a>); unsafe extern "C" { pub type TargetMachine; - pub type Archive; + pub(crate) type Archive; } #[repr(C)] -pub struct ArchiveIterator<'a>(InvariantOpaque<'a>); +pub(crate) struct ArchiveIterator<'a>(InvariantOpaque<'a>); #[repr(C)] -pub struct ArchiveChild<'a>(InvariantOpaque<'a>); +pub(crate) struct ArchiveChild<'a>(InvariantOpaque<'a>); unsafe extern "C" { - pub type Twine; - pub type DiagnosticInfo; - pub type SMDiagnostic; + pub(crate) type Twine; + pub(crate) type DiagnosticInfo; + pub(crate) type SMDiagnostic; } #[repr(C)] -pub struct RustArchiveMember<'a>(InvariantOpaque<'a>); +pub(crate) struct RustArchiveMember<'a>(InvariantOpaque<'a>); /// Opaque pointee of `LLVMOperandBundleRef`. #[repr(C)] pub(crate) struct OperandBundle<'a>(InvariantOpaque<'a>); #[repr(C)] -pub struct Linker<'a>(InvariantOpaque<'a>); +pub(crate) struct Linker<'a>(InvariantOpaque<'a>); unsafe extern "C" { - pub type DiagnosticHandler; + pub(crate) type DiagnosticHandler; } -pub type DiagnosticHandlerTy = unsafe extern "C" fn(&DiagnosticInfo, *mut c_void); +pub(crate) type DiagnosticHandlerTy = unsafe extern "C" fn(&DiagnosticInfo, *mut c_void); -pub mod debuginfo { +pub(crate) mod debuginfo { use std::ptr; use bitflags::bitflags; @@ -793,7 +799,7 @@ pub mod debuginfo { /// builder reference typically has a shorter lifetime than the LLVM /// session (`'ll`) that it participates in. #[repr(C)] - pub struct DIBuilder<'ll>(InvariantOpaque<'ll>); + pub(crate) struct DIBuilder<'ll>(InvariantOpaque<'ll>); /// Owning pointer to a `DIBuilder<'ll>` that will dispose of the builder /// when dropped. Use `.as_ref()` to get the underlying `&DIBuilder` @@ -822,22 +828,22 @@ pub mod debuginfo { } } - pub type DIDescriptor = Metadata; - pub type DILocation = Metadata; - pub type DIScope = DIDescriptor; - pub type DIFile = DIScope; - pub type DILexicalBlock = DIScope; - pub type DISubprogram = DIScope; - pub type DIType = DIDescriptor; - pub type DIBasicType = DIType; - pub type DIDerivedType = DIType; - pub type DICompositeType = DIDerivedType; - pub type DIVariable = DIDescriptor; - pub type DIGlobalVariableExpression = DIDescriptor; - pub type DIArray = DIDescriptor; - pub type DISubrange = DIDescriptor; - pub type DIEnumerator = DIDescriptor; - pub type DITemplateTypeParameter = DIDescriptor; + pub(crate) type DIDescriptor = Metadata; + pub(crate) type DILocation = Metadata; + pub(crate) type DIScope = DIDescriptor; + pub(crate) type DIFile = DIScope; + pub(crate) type DILexicalBlock = DIScope; + pub(crate) type DISubprogram = DIScope; + pub(crate) type DIType = DIDescriptor; + pub(crate) type DIBasicType = DIType; + pub(crate) type DIDerivedType = DIType; + pub(crate) type DICompositeType = DIDerivedType; + pub(crate) type DIVariable = DIDescriptor; + pub(crate) type DIGlobalVariableExpression = DIDescriptor; + pub(crate) type DIArray = DIDescriptor; + pub(crate) type DISubrange = DIDescriptor; + pub(crate) type DIEnumerator = DIDescriptor; + pub(crate) type DITemplateTypeParameter = DIDescriptor; bitflags! { /// Must match the layout of `LLVMDIFlags` in the LLVM-C API. @@ -846,7 +852,7 @@ pub mod debuginfo { /// assertions in `RustWrapper.cpp` used by `fromRust(LLVMDIFlags)`. #[repr(transparent)] #[derive(Clone, Copy, Default)] - pub struct DIFlags: u32 { + pub(crate) struct DIFlags: u32 { const FlagZero = 0; const FlagPrivate = 1; const FlagProtected = 2; @@ -886,7 +892,7 @@ pub mod debuginfo { bitflags! { #[repr(transparent)] #[derive(Clone, Copy, Default)] - pub struct DISPFlags: u32 { + pub(crate) struct DISPFlags: u32 { const SPFlagZero = 0; const SPFlagVirtual = 1; const SPFlagPureVirtual = 2; @@ -900,7 +906,7 @@ pub mod debuginfo { /// LLVMRustDebugEmissionKind #[derive(Copy, Clone)] #[repr(C)] - pub enum DebugEmissionKind { + pub(crate) enum DebugEmissionKind { NoDebug, FullDebug, LineTablesOnly, @@ -932,8 +938,9 @@ pub mod debuginfo { /// LLVMRustDebugNameTableKind #[derive(Clone, Copy)] #[repr(C)] - pub enum DebugNameTableKind { + pub(crate) enum DebugNameTableKind { Default, + #[expect(dead_code)] Gnu, None, } @@ -943,7 +950,7 @@ pub mod debuginfo { bitflags! { #[repr(transparent)] #[derive(Default)] - pub struct AllocKindFlags : u64 { + pub(crate) struct AllocKindFlags : u64 { const Unknown = 0; const Alloc = 1; const Realloc = 1 << 1; @@ -955,15 +962,16 @@ bitflags! { } unsafe extern "C" { - pub type ModuleBuffer; + pub(crate) type ModuleBuffer; } -pub type SelfProfileBeforePassCallback = +pub(crate) type SelfProfileBeforePassCallback = unsafe extern "C" fn(*mut c_void, *const c_char, *const c_char); -pub type SelfProfileAfterPassCallback = unsafe extern "C" fn(*mut c_void); +pub(crate) type SelfProfileAfterPassCallback = unsafe extern "C" fn(*mut c_void); -pub type GetSymbolsCallback = unsafe extern "C" fn(*mut c_void, *const c_char) -> *mut c_void; -pub type GetSymbolsErrorCallback = unsafe extern "C" fn(*const c_char) -> *mut c_void; +pub(crate) type GetSymbolsCallback = + unsafe extern "C" fn(*mut c_void, *const c_char) -> *mut c_void; +pub(crate) type GetSymbolsErrorCallback = unsafe extern "C" fn(*const c_char) -> *mut c_void; unsafe extern "C" { // Create and destroy contexts. diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index efc9cf2ef691b..e8e4eed0419e9 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -10,18 +10,18 @@ use libc::c_uint; use rustc_abi::{Align, Size, WrappingRange}; use rustc_llvm::RustString; -pub use self::CallConv::*; -pub use self::CodeGenOptSize::*; -pub use self::MetadataType::*; -pub use self::ffi::*; +pub(crate) use self::CallConv::*; +pub(crate) use self::CodeGenOptSize::*; +pub(crate) use self::MetadataType::*; +pub(crate) use self::ffi::*; use crate::common::AsCCharPtr; -pub mod archive_ro; -pub mod diagnostic; -pub mod enzyme_ffi; +pub(crate) mod archive_ro; +pub(crate) mod diagnostic; +pub(crate) mod enzyme_ffi; mod ffi; -pub use self::enzyme_ffi::*; +pub(crate) use self::enzyme_ffi::*; impl LLVMRustResult { pub(crate) fn into_result(self) -> Result<(), ()> { @@ -128,7 +128,7 @@ pub(crate) fn CreateRangeAttr(llcx: &Context, size: Size, range: WrappingRange) } #[derive(Copy, Clone)] -pub enum AttributePlace { +pub(crate) enum AttributePlace { ReturnValue, Argument(u32), Function, @@ -146,7 +146,7 @@ impl AttributePlace { #[derive(Copy, Clone, PartialEq)] #[repr(C)] -pub enum CodeGenOptSize { +pub(crate) enum CodeGenOptSize { CodeGenOptSizeNone = 0, CodeGenOptSizeDefault = 1, CodeGenOptSizeAggressive = 2, From c45463ec8b2675df903b2436d4baf959d801aa08 Mon Sep 17 00:00:00 2001 From: yukang Date: Sat, 22 Feb 2025 13:28:12 +0800 Subject: [PATCH 21/22] remove invalid suggestion of into_iter for extern macro --- .../rustc_hir_typeck/src/method/suggest.rs | 12 +++++++----- .../auxiliary/quote-issue-137345.rs | 19 +++++++++++++++++++ .../ui/proc-macro/valid-sugg-issue-137345.rs | 17 +++++++++++++++++ .../proc-macro/valid-sugg-issue-137345.stderr | 13 +++++++++++++ 4 files changed, 56 insertions(+), 5 deletions(-) create mode 100644 tests/ui/proc-macro/auxiliary/quote-issue-137345.rs create mode 100644 tests/ui/proc-macro/valid-sugg-issue-137345.rs create mode 100644 tests/ui/proc-macro/valid-sugg-issue-137345.stderr diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index c757d089478f5..93720a7a4675c 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -905,11 +905,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else if self.impl_into_iterator_should_be_iterator(rcvr_ty, span, unsatisfied_predicates) { err.span_label(span, format!("`{rcvr_ty}` is not an iterator")); - err.multipart_suggestion_verbose( - "call `.into_iter()` first", - vec![(span.shrink_to_lo(), format!("into_iter()."))], - Applicability::MaybeIncorrect, - ); + if !span.in_external_macro(self.tcx.sess.source_map()) { + err.multipart_suggestion_verbose( + "call `.into_iter()` first", + vec![(span.shrink_to_lo(), format!("into_iter()."))], + Applicability::MaybeIncorrect, + ); + } return err.emit(); } else if !unsatisfied_predicates.is_empty() && matches!(rcvr_ty.kind(), ty::Param(_)) { // We special case the situation where we are looking for `_` in diff --git a/tests/ui/proc-macro/auxiliary/quote-issue-137345.rs b/tests/ui/proc-macro/auxiliary/quote-issue-137345.rs new file mode 100644 index 0000000000000..f125a14669f79 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/quote-issue-137345.rs @@ -0,0 +1,19 @@ +extern crate proc_macro; +use proc_macro::TokenStream; + +fn items() -> impl IntoIterator { + vec![1, 2, 3] +} + +#[macro_export] +macro_rules! quote { + // Rule for any other number of tokens. + ($($tt:tt)*) => {{ + fn items() -> impl IntoIterator { + vec![1, 2, 3] + } + let _s = TokenStream::new(); + let other_items = items().map(|i| i + 1); + _s + }}; +} diff --git a/tests/ui/proc-macro/valid-sugg-issue-137345.rs b/tests/ui/proc-macro/valid-sugg-issue-137345.rs new file mode 100644 index 0000000000000..78674797b8da6 --- /dev/null +++ b/tests/ui/proc-macro/valid-sugg-issue-137345.rs @@ -0,0 +1,17 @@ +//@ aux-crate: quote=quote-issue-137345.rs + +extern crate proc_macro; +extern crate quote; + +use proc_macro::TokenStream; + +pub fn default_args_fn(_: TokenStream) -> TokenStream { + let decl_macro = TokenStream::new(); + + quote::quote! { + #(#decl_macro)* + } + .into() //~^^^ ERROR no method named `map` found for opaque type +} + +fn main() {} diff --git a/tests/ui/proc-macro/valid-sugg-issue-137345.stderr b/tests/ui/proc-macro/valid-sugg-issue-137345.stderr new file mode 100644 index 0000000000000..40336803f0dbc --- /dev/null +++ b/tests/ui/proc-macro/valid-sugg-issue-137345.stderr @@ -0,0 +1,13 @@ +error[E0599]: no method named `map` found for opaque type `impl IntoIterator` in the current scope + --> $DIR/valid-sugg-issue-137345.rs:11:5 + | +LL | / quote::quote! { +LL | | #(#decl_macro)* +LL | | } + | |_____^ `impl IntoIterator` is not an iterator + | + = note: this error originates in the macro `quote::quote` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0599`. From d1b34acb3bfa202704b5ab13e4b35eb569cf7d67 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 22 Feb 2025 14:12:55 +0100 Subject: [PATCH 22/22] make the new intrinsics safe --- .../rustc_hir_analysis/src/check/intrinsic.rs | 4 ++++ library/core/src/intrinsics/mod.rs | 16 ++++++++-------- library/std/src/f128.rs | 2 +- library/std/src/f16.rs | 2 +- library/std/src/f32.rs | 2 +- library/std/src/f64.rs | 2 +- 6 files changed, 16 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index acdd2facc24dc..5c0c7a86a0ccc 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -137,6 +137,10 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) - | sym::fmul_algebraic | sym::fdiv_algebraic | sym::frem_algebraic + | sym::round_ties_even_f16 + | sym::round_ties_even_f32 + | sym::round_ties_even_f64 + | sym::round_ties_even_f128 | sym::const_eval_select => hir::Safety::Safe, _ => hir::Safety::Unsafe, }; diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 320122a53e9dd..a52f2b20246d9 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -2748,13 +2748,13 @@ pub unsafe fn truncf128(_x: f128) -> f128 { #[rustc_intrinsic_must_be_overridden] #[rustc_nounwind] #[cfg(not(bootstrap))] -pub unsafe fn round_ties_even_f16(_x: f16) -> f16 { +pub fn round_ties_even_f16(_x: f16) -> f16 { unreachable!() } /// To be removed on next bootstrap bump. #[cfg(bootstrap)] -pub unsafe fn round_ties_even_f16(x: f16) -> f16 { +pub fn round_ties_even_f16(x: f16) -> f16 { #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] #[rustc_nounwind] @@ -2775,13 +2775,13 @@ pub unsafe fn round_ties_even_f16(x: f16) -> f16 { #[rustc_intrinsic_must_be_overridden] #[rustc_nounwind] #[cfg(not(bootstrap))] -pub unsafe fn round_ties_even_f32(_x: f32) -> f32 { +pub fn round_ties_even_f32(_x: f32) -> f32 { unreachable!() } /// To be removed on next bootstrap bump. #[cfg(bootstrap)] -pub unsafe fn round_ties_even_f32(x: f32) -> f32 { +pub fn round_ties_even_f32(x: f32) -> f32 { #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] #[rustc_nounwind] @@ -2802,13 +2802,13 @@ pub unsafe fn round_ties_even_f32(x: f32) -> f32 { #[rustc_intrinsic_must_be_overridden] #[rustc_nounwind] #[cfg(not(bootstrap))] -pub unsafe fn round_ties_even_f64(_x: f64) -> f64 { +pub fn round_ties_even_f64(_x: f64) -> f64 { unreachable!() } /// To be removed on next bootstrap bump. #[cfg(bootstrap)] -pub unsafe fn round_ties_even_f64(x: f64) -> f64 { +pub fn round_ties_even_f64(x: f64) -> f64 { #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] #[rustc_nounwind] @@ -2829,13 +2829,13 @@ pub unsafe fn round_ties_even_f64(x: f64) -> f64 { #[rustc_intrinsic_must_be_overridden] #[rustc_nounwind] #[cfg(not(bootstrap))] -pub unsafe fn round_ties_even_f128(_x: f128) -> f128 { +pub fn round_ties_even_f128(_x: f128) -> f128 { unreachable!() } /// To be removed on next bootstrap bump. #[cfg(bootstrap)] -pub unsafe fn round_ties_even_f128(x: f128) -> f128 { +pub fn round_ties_even_f128(x: f128) -> f128 { #[rustc_intrinsic] #[rustc_intrinsic_must_be_overridden] #[rustc_nounwind] diff --git a/library/std/src/f128.rs b/library/std/src/f128.rs index 615c4fd334846..d4aa174cee519 100644 --- a/library/std/src/f128.rs +++ b/library/std/src/f128.rs @@ -129,7 +129,7 @@ impl f128 { #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn round_ties_even(self) -> f128 { - unsafe { intrinsics::round_ties_even_f128(self) } + intrinsics::round_ties_even_f128(self) } /// Returns the integer part of `self`. diff --git a/library/std/src/f16.rs b/library/std/src/f16.rs index 85b82b91fabc3..c0678732365d7 100644 --- a/library/std/src/f16.rs +++ b/library/std/src/f16.rs @@ -129,7 +129,7 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub fn round_ties_even(self) -> f16 { - unsafe { intrinsics::round_ties_even_f16(self) } + intrinsics::round_ties_even_f16(self) } /// Returns the integer part of `self`. diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index da1f000278dad..bdcbd8b30b650 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -125,7 +125,7 @@ impl f32 { #[stable(feature = "round_ties_even", since = "1.77.0")] #[inline] pub fn round_ties_even(self) -> f32 { - unsafe { intrinsics::round_ties_even_f32(self) } + intrinsics::round_ties_even_f32(self) } /// Returns the integer part of `self`. diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index 8a9f693a7a821..11acc13d65709 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -125,7 +125,7 @@ impl f64 { #[stable(feature = "round_ties_even", since = "1.77.0")] #[inline] pub fn round_ties_even(self) -> f64 { - unsafe { intrinsics::round_ties_even_f64(self) } + intrinsics::round_ties_even_f64(self) } /// Returns the integer part of `self`.