diff --git a/compiler/rustc_codegen_llvm/src/back/mod.rs b/compiler/rustc_codegen_llvm/src/back/mod.rs index 6cb89f80ab89a..de6007c17bfff 100644 --- a/compiler/rustc_codegen_llvm/src/back/mod.rs +++ b/compiler/rustc_codegen_llvm/src/back/mod.rs @@ -1,5 +1,6 @@ pub(crate) mod archive; pub(crate) mod lto; +pub(crate) mod owned_mc_subtarget_info; pub(crate) mod owned_target_machine; mod profiling; pub(crate) mod write; diff --git a/compiler/rustc_codegen_llvm/src/back/owned_mc_subtarget_info.rs b/compiler/rustc_codegen_llvm/src/back/owned_mc_subtarget_info.rs new file mode 100644 index 0000000000000..f57368e755add --- /dev/null +++ b/compiler/rustc_codegen_llvm/src/back/owned_mc_subtarget_info.rs @@ -0,0 +1,49 @@ +use std::ffi::CStr; +use std::ptr::NonNull; + +use rustc_data_structures::small_c_str::SmallCStr; + +use crate::diagnostics::LlvmError; +use crate::llvm; + +/// Responsible for safely creating and disposing llvm::MCSubtargetInfo via ffi functions. +/// Not cloneable as there is no clone function for llvm::MCSubtargetInfo. +pub(crate) struct OwnedMCSubtargetInfo { + info_unique: NonNull, +} + +impl OwnedMCSubtargetInfo { + pub(crate) fn new( + triple: &CStr, + cpu: &CStr, + features: &CStr, + ) -> Result> { + // SAFETY: llvm::LLVMRustCreateMCSubtargetInfo copies pointed-to data. + let info_ptr = unsafe { + llvm::LLVMRustCreateMCSubtargetInfo(triple.as_ptr(), cpu.as_ptr(), features.as_ptr()) + }; + + NonNull::new(info_ptr) + .map(|info_unique| Self { info_unique }) + .ok_or_else(|| LlvmError::CreateMCSubtargetInfo { triple: SmallCStr::from(triple) }) + } + + pub(crate) fn has_feature(&self, feature: &CStr) -> bool { + // SAFETY: `new` ensures we have a valid pointer created by + // `llvm::LLVMRustCreateMCSubtargetInfo`. + unsafe { + llvm::LLVMRustMCSubtargetInfoHasFeature(self.info_unique.as_ref(), feature.as_ptr()) + } + } +} + +impl Drop for OwnedMCSubtargetInfo { + fn drop(&mut self) { + // SAFETY: `new` ensures we have a valid pointer created by + // `llvm::LLVMRustCreateMCSubtargetInfo` and `OwnedMCSubtargetInfo` is not copyable so + // there is no double free or use after free. + unsafe { + llvm::LLVMRustDisposeMCSubtargetInfo(self.info_unique); + } + } +} diff --git a/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs b/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs index 350d4ce9ee331..5a1dc8080c2c1 100644 --- a/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs +++ b/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs @@ -1,5 +1,4 @@ use std::ffi::CStr; -use std::marker::PhantomData; use std::ptr::NonNull; use rustc_data_structures::small_c_str::SmallCStr; @@ -9,10 +8,8 @@ use crate::llvm; /// Responsible for safely creating and disposing llvm::TargetMachine via ffi functions. /// Not cloneable as there is no clone function for llvm::TargetMachine. -#[repr(transparent)] pub struct OwnedTargetMachine { tm_unique: NonNull, - phantom: PhantomData, } impl OwnedTargetMachine { @@ -41,7 +38,7 @@ impl OwnedTargetMachine { use_wasm_eh: bool, large_data_threshold: u64, ) -> Result> { - // SAFETY: llvm::LLVMRustCreateTargetMachine copies pointed to data + // SAFETY: llvm::LLVMRustCreateTargetMachine copies pointed-to data. let tm_ptr = unsafe { llvm::LLVMRustCreateTargetMachine( triple.as_ptr(), @@ -71,7 +68,7 @@ impl OwnedTargetMachine { }; NonNull::new(tm_ptr) - .map(|tm_unique| Self { tm_unique, phantom: PhantomData }) + .map(|tm_unique| Self { tm_unique }) .ok_or_else(|| LlvmError::CreateTargetMachine { triple: SmallCStr::from(triple) }) } diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 90b2cab5b63e2..bdf1bb2f24f6d 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -100,17 +100,12 @@ fn write_output_file<'ll>( result.into_result().unwrap_or_else(|()| llvm_err(dcx, LlvmError::WriteOutput { path: output })) } -/// If `for_cfg` is `true` then we are creating this machine for the purpose of populating -/// [`rustc_codegen_ssa::TargetConfig`] based on what LLVM actually enables in this configuration. -/// `-Ctarget-feature` should be ignored in that case since it is already processed separately. -pub(crate) fn create_informational_target_machine( - sess: &Session, - for_cfg: bool, -) -> OwnedTargetMachine { +pub(crate) fn create_informational_target_machine(sess: &Session) -> OwnedTargetMachine { let config = TargetMachineFactoryConfig { split_dwarf_file: None, output_obj_file: None }; // Can't use query system here quite yet because this function is invoked before the query // system/tcx is set up. - let features = llvm_util::global_llvm_features(sess, for_cfg); + let features = llvm_util::global_llvm_features(sess, /* for_cfg */ false); + target_machine_factory(sess, config::OptLevel::No, &features)(sess.dcx(), config) } @@ -212,7 +207,6 @@ pub(crate) fn target_machine_factory( let code_model = to_llvm_code_model(sess.code_model()); - // This is used to set cfg_has_threads, so all logic must be in this method. let singlethread = sess.target.singlethread(&sess.internal_target_features); let triple = SmallCStr::new(&versioned_llvm_target(sess)); diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 3b58a7f00146b..d4d1c950ec3f8 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -232,7 +232,7 @@ pub(crate) unsafe fn create_module<'ll>( // Ensure the data-layout values hardcoded remain the defaults. { - let tm = crate::back::write::create_informational_target_machine(sess, false); + let tm = crate::back::write::create_informational_target_machine(sess); unsafe { llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, tm.raw()); } diff --git a/compiler/rustc_codegen_llvm/src/diagnostics.rs b/compiler/rustc_codegen_llvm/src/diagnostics.rs index 70a14288aec0c..c471d417f0825 100644 --- a/compiler/rustc_codegen_llvm/src/diagnostics.rs +++ b/compiler/rustc_codegen_llvm/src/diagnostics.rs @@ -123,6 +123,8 @@ pub(crate) enum LlvmError<'a> { WriteOutput { path: &'a Path }, #[diag("could not create LLVM TargetMachine for triple: {$triple}")] CreateTargetMachine { triple: SmallCStr }, + #[diag("could not create LLVM MCSubtargetInfo for triple: {$triple}")] + CreateMCSubtargetInfo { triple: SmallCStr }, #[diag("failed to run LLVM passes")] RunLlvmPasses, #[diag("failed to write LLVM IR to {$path}")] @@ -149,6 +151,9 @@ impl Diagnostic<'_, G> for WithLlvmError<'_> { CreateTargetMachine { .. } => { msg!("could not create LLVM TargetMachine for triple: {$triple}: {$llvm_err}") } + CreateMCSubtargetInfo { .. } => { + msg!("could not create LLVM MCSubtargetInfo for triple: {$triple}: {$llvm_err}") + } RunLlvmPasses => msg!("failed to run LLVM passes: {$llvm_err}"), WriteIr { .. } => msg!("failed to write LLVM IR to {$path}: {$llvm_err}"), PrepareThinLtoContext => { diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index ca16d33b90256..ddc5db619ea5f 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -248,7 +248,7 @@ impl CodegenBackend for LlvmCodegenBackend { fn provide(&self, providers: &mut Providers) { providers.queries.global_backend_features = - |tcx, ()| llvm_util::global_llvm_features(tcx.sess, false) + |tcx, ()| llvm_util::global_llvm_features(tcx.sess, /* for_cfg */ false) } fn print(&self, req: &PrintRequest, out: &mut String, sess: &Session) { @@ -496,7 +496,7 @@ impl ModuleLlvm { ModuleLlvm { llmod_raw, llcx, - tm: ManuallyDrop::new(create_informational_target_machine(tcx.sess, false)), + tm: ManuallyDrop::new(create_informational_target_machine(tcx.sess)), } } } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index abacef3710f4e..d1cdf7bada0b1 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -720,6 +720,7 @@ unsafe extern "C" { pub type TargetMachine; } unsafe extern "C" { + pub(crate) type MCSubtargetInfo; pub(crate) type Twine; pub(crate) type DiagnosticInfo; pub(crate) type SMDiagnostic; @@ -2372,7 +2373,6 @@ unsafe extern "C" { pub(crate) fn LLVMRustWriteTypeToString(Type: &Type, s: &RustString); pub(crate) fn LLVMRustWriteValueToString(value_ref: &Value, s: &RustString); - pub(crate) fn LLVMRustHasFeature(T: &TargetMachine, s: *const c_char) -> bool; pub(crate) fn LLVMRustTargetHasMnemonic(T: &TargetMachine, s: *const c_char) -> bool; pub(crate) fn LLVMRustPrintTargetCPUs(TM: &TargetMachine, OutStr: &RustString); @@ -2414,6 +2414,19 @@ unsafe extern "C" { LargeDataThreshold: u64, ) -> *mut TargetMachine; + pub(crate) fn LLVMRustCreateMCSubtargetInfo( + TripleStr: *const c_char, + CPU: *const c_char, + Features: *const c_char, + ) -> *mut MCSubtargetInfo; + + pub(crate) fn LLVMRustMCSubtargetInfoHasFeature( + MCInfo: &MCSubtargetInfo, + Feature: *const c_char, + ) -> bool; + + pub(crate) fn LLVMRustDisposeMCSubtargetInfo(MCInfo: ptr::NonNull); + pub(crate) fn LLVMRustAddLibraryInfo<'a>( T: &TargetMachine, PM: &PassManager<'a>, diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 223cbf2aae31f..677058ff80d67 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -6,6 +6,7 @@ use std::sync::Once; use std::{ptr, slice, str}; use libc::c_int; +use rustc_codegen_ssa::back::versioned_llvm_target; use rustc_codegen_ssa::base::wants_wasm_eh; use rustc_codegen_ssa::target_features::internal_target_features; use rustc_codegen_ssa::{TargetConfig, target_features}; @@ -20,7 +21,8 @@ use rustc_target::spec::{ }; use smallvec::{SmallVec, smallvec}; -use crate::back::write::create_informational_target_machine; +use crate::back::owned_mc_subtarget_info::OwnedMCSubtargetInfo; +use crate::back::write::{create_informational_target_machine, llvm_err}; use crate::{diagnostics, llvm}; static INIT: Once = Once::new(); @@ -337,7 +339,14 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option TargetConfig { - let target_machine = create_informational_target_machine(sess, true); + require_inited(); + let target_features = global_llvm_features(sess, /* for_cfg */ true); + + let triple = SmallCStr::new(&versioned_llvm_target(sess)); + let cpu = SmallCStr::new(target_cpu(sess)); + let features = CString::new(target_features.join(",")).unwrap(); + let mc_subtarget_info = OwnedMCSubtargetInfo::new(&triple, &cpu, &features) + .unwrap_or_else(|err| llvm_err(sess.dcx(), err)); let internal_target_features = internal_target_features( sess, @@ -348,16 +357,17 @@ pub(crate) fn target_config(sess: &Session) -> TargetConfig { }, |feature| { // This closure determines whether the target CPU has the feature according to LLVM. We - // do *not* consider the `-Ctarget-feature`s here, as that will be handled later in + // do *not* consider the `-Ctarget-feature`s here (that's why we passed `for_cfg: true` + // to `global_llvm_features` above) because that will be handled later in // `internal_target_features`. if let Some(feat) = to_llvm_features(sess, feature) { // All the LLVM features this expands to must be enabled. for llvm_feature in feat { let cstr = SmallCStr::new(llvm_feature); - // `LLVMRustHasFeature` is moderately expensive. On targets with many + // `has_feature` is moderately expensive. On targets with many // features (e.g. x86) these calls take a non-trivial fraction of runtime // when compiling very small programs. - if !unsafe { llvm::LLVMRustHasFeature(target_machine.raw(), cstr.as_ptr()) } { + if !mc_subtarget_info.has_feature(&cstr) { return false; } } @@ -500,7 +510,7 @@ fn llvm_target_features(tm: &llvm::TargetMachine) -> Vec<(&str, &str)> { pub(crate) fn print(req: &PrintRequest, out: &mut String, sess: &Session) { require_inited(); - let tm = create_informational_target_machine(sess, false); + let tm = create_informational_target_machine(sess); match req.kind { PrintKind::TargetCPUs => print_target_cpus(sess, tm.raw(), out), PrintKind::TargetFeatures => print_target_features(sess, tm.raw(), out), @@ -518,10 +528,11 @@ fn print_target_cpus(sess: &Session, tm: &llvm::TargetMachine, out: &mut String) cpu_name: &'a str, remark: String, } - // Compare CPU against current target to label the default. + // Compare CPU against current target to label the default. Do not print it if + // `need_explicit_cpu` is set, because in that case the concept of default makes less sense. let target_cpu = handle_native(&sess.target.cpu); let make_remark = |cpu_name| { - if cpu_name == target_cpu { + if cpu_name == target_cpu && !sess.target.need_explicit_cpu { // FIXME(#132514): This prints the LLVM target string, which can be // different from the Rust target string. Is that intended? let target = &sess.target.llvm_target; @@ -797,7 +808,7 @@ pub(crate) fn tune_cpu(sess: &Session) -> Option<&str> { pub(crate) fn target_has_mnemonic(sess: &Session, mnemonic: &str) -> bool { require_inited(); - let tm = create_informational_target_machine(sess, false); + let tm = create_informational_target_machine(sess); let cstr = SmallCStr::new(mnemonic); unsafe { llvm::LLVMRustTargetHasMnemonic(tm.raw(), cstr.as_ptr()) } } diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 1bd5094c38f02..d181891cdfa54 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -89,15 +89,31 @@ extern "C" void LLVMRustTimeTraceProfilerFinish(const char *FileName) { timeTraceProfilerCleanup(); } -extern "C" bool LLVMRustHasFeature(LLVMTargetMachineRef TM, - const char *Feature) { - TargetMachine *Target = unwrap(TM); -#if LLVM_VERSION_GE(23, 0) - const MCSubtargetInfo &MCInfo = Target->getMCSubtargetInfo(); +extern "C" MCSubtargetInfo * +LLVMRustCreateMCSubtargetInfo(const char *TripleStr, const char *CPU, + const char *Features) { + std::string Error; + auto Trip = Triple(Triple::normalize(TripleStr)); + const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Trip, Error); + if (TheTarget == nullptr) { + LLVMRustSetLastError(Error.c_str()); + return nullptr; + } + +#if LLVM_VERSION_GE(22, 0) + return TheTarget->createMCSubtargetInfo(Trip, CPU, Features); #else - const MCSubtargetInfo &MCInfo = *Target->getMCSubtargetInfo(); + return TheTarget->createMCSubtargetInfo(Trip.str(), CPU, Features); #endif - return MCInfo.checkFeatures(std::string("+") + Feature); +} + +extern "C" bool LLVMRustMCSubtargetInfoHasFeature(MCSubtargetInfo *MCInfo, + const char *Feature) { + return MCInfo->checkFeatures(std::string("+") + Feature); +} + +extern "C" void LLVMRustDisposeMCSubtargetInfo(MCSubtargetInfo *MCInfo) { + delete MCInfo; } /// Check whether the target has a specific assembly mnemonic like `ret` or diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 0f192379ce7fc..9f97a33bfdc75 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2262,11 +2262,12 @@ pub struct TargetOptions { /// Extra arguments to pass to the external assembler (when used) pub asm_args: StaticCow<[StaticCow]>, - /// Default CPU to pass to LLVM. Corresponds to `llc -mcpu=$cpu`. Defaults - /// to "generic". + /// Default CPU to pass to LLVM. Corresponds to `llc -mcpu=$cpu`. Must be a name the backend + /// accepts. Defaults to "generic" (which some backends won't accept). pub cpu: StaticCow, - /// Whether a cpu needs to be explicitly set. - /// Set to true if there is no default cpu. Defaults to false. + /// Whether a cpu needs to be explicitly set via `-Ctarget-cpu` for codegen to run. (Even if + /// true, `cpu` is still consulted on non-codegen paths such as cfg/feature computation.) + /// Defaults to false. pub need_explicit_cpu: bool, /// Whether `-Ctarget-cpu` is treated as a target modifier. If this is set /// all crates that are linked together must have been compiled with the diff --git a/compiler/rustc_target/src/spec/targets/avr_none.rs b/compiler/rustc_target/src/spec/targets/avr_none.rs index 0dcd2428fc703..d4b0bf64206c7 100644 --- a/compiler/rustc_target/src/spec/targets/avr_none.rs +++ b/compiler/rustc_target/src/spec/targets/avr_none.rs @@ -14,6 +14,7 @@ pub(crate) fn target() -> Target { pointer_width: 16, options: TargetOptions { c_int_width: 16, + cpu: "avr2".into(), exe_suffix: ".elf".into(), linker: Some("avr-gcc".into()), eh_frame_header: false, diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index bf77b477eef70..734c114d74d91 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -448,10 +448,7 @@ impl Box { #[unstable(feature = "allocator_api", issue = "32838")] #[must_use] #[inline] - pub fn new_in(x: T, alloc: A) -> Self - where - A: Allocator, - { + pub fn new_in(x: T, alloc: A) -> Self { let mut boxed = Self::new_uninit_in(alloc); boxed.write(x); // SAFETY: Initialised by the above. @@ -475,10 +472,7 @@ impl Box { /// ``` #[unstable(feature = "allocator_api", issue = "32838")] #[inline] - pub fn try_new_in(x: T, alloc: A) -> Result - where - A: Allocator, - { + pub fn try_new_in(x: T, alloc: A) -> Result { let mut boxed = Self::try_new_uninit_in(alloc)?; boxed.write(x); // SAFETY: Initialised by the above. @@ -504,10 +498,7 @@ impl Box { #[unstable(feature = "allocator_api", issue = "32838")] #[cfg(not(no_global_oom_handling))] #[must_use] - pub fn new_uninit_in(alloc: A) -> Box, A> - where - A: Allocator, - { + pub fn new_uninit_in(alloc: A) -> Box, A> { let layout = Layout::new::>(); // NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable. // That would make code size bigger. @@ -536,10 +527,7 @@ impl Box { /// # Ok::<(), std::alloc::AllocError>(()) /// ``` #[unstable(feature = "allocator_api", issue = "32838")] - pub fn try_new_uninit_in(alloc: A) -> Result, A>, AllocError> - where - A: Allocator, - { + pub fn try_new_uninit_in(alloc: A) -> Result, A>, AllocError> { let ptr = if T::IS_ZST { NonNull::dangling() } else { @@ -573,10 +561,7 @@ impl Box { #[unstable(feature = "allocator_api", issue = "32838")] #[cfg(not(no_global_oom_handling))] #[must_use] - pub fn new_zeroed_in(alloc: A) -> Box, A> - where - A: Allocator, - { + pub fn new_zeroed_in(alloc: A) -> Box, A> { let layout = Layout::new::>(); // NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable. // That would make code size bigger. @@ -609,10 +594,7 @@ impl Box { /// /// [zeroed]: mem::MaybeUninit::zeroed #[unstable(feature = "allocator_api", issue = "32838")] - pub fn try_new_zeroed_in(alloc: A) -> Result, A>, AllocError> - where - A: Allocator, - { + pub fn try_new_zeroed_in(alloc: A) -> Result, A>, AllocError> { let ptr = if T::IS_ZST { NonNull::dangling() } else { diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 9b55d70fecb9a..a30940bf2db71 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -10,6 +10,30 @@ //! and , //! and for const evaluation in . //! +//! Intrinsics don't need a body. However, they optionally can have a body, which we call the +//! "fallback body". This will be used by codegen backends that do not have a dedicated +//! implementation of the intrinsic, making it easier to add new intrinsics for specific operations +//! without having to implement them in each codegen backend. The fallback body obviously has to be +//! a valid implementation of the documented specification of the intrinsic. In some cases, the +//! fallback body will be *equivalent* to the specification. Note that this is a strong requirement: +//! if the spec says "UB if input `x` is even", then a valid implementation can just ignore this and +//! do whatever it wants in that case; an *equivalent* implementation needs to actually check this +//! condition and trigger UB in that case (e.g. by using `hint::assert_unchecked()`). Similar, if +//! the spec says "returns `x` or `y` non-deterministically", then an *equivalent* implementation +//! must actually do non-deterministic choice and return either value (e.g. by invoking some other +//! language operation that has the same non-determinism). Intrinsics with such a fallback body that +//! is equivalent to the spec may be marked with `#[miri::intrinsic_fallback_is_spec]`; the fallback +//! body will then also be used by Miri for UB checking. When in doubt, do not use this attribute or +//! ask the Miri maintainers for advice. +//! +//! Intrinsics are, in general, language extensions. Therefore, t-lang should be involved whenever a +//! new intrinsic is exposed to stable code. However, if an intrinsic is marked +//! `#[miri::intrinsic_fallback_is_spec]` with a fallback body that only uses stable features (or if +//! such a fallback body could be written, but for one reason or another the actual fallback body is +//! different), and if it also does not make other promises that go beyond observable program +//! behavior (such as steering the optimizer in a particular direction), then an intrinsic may be +//! used without t-lang involvement. +//! //! # Const intrinsics //! //! In order to make an intrinsic unstable usable at compile-time, copy the implementation from @@ -19,9 +43,10 @@ //! wg-const-eval. //! //! If an intrinsic is supposed to be used from a `const fn` with a `rustc_const_stable` attribute, -//! `#[rustc_intrinsic_const_stable_indirect]` needs to be added to the intrinsic. Such a change requires -//! T-lang approval, because it may bake a feature into the language that cannot be replicated in -//! user code without compiler support. +//! `#[rustc_intrinsic_const_stable_indirect]` needs to be added to the intrinsic. Such a change +//! requires T-lang approval, because it may bake a feature into the language that cannot be +//! replicated in user code without compiler support. The same exception as above applies for +//! `#[miri::intrinsic_fallback_is_spec]` intrinsics. //! //! # Volatiles //! diff --git a/src/tools/rust-analyzer/.github/workflows/gen-lints.yml b/src/tools/rust-analyzer/.github/workflows/gen-lints.yml index c978e3571c40d..05dfdc2fc4534 100644 --- a/src/tools/rust-analyzer/.github/workflows/gen-lints.yml +++ b/src/tools/rust-analyzer/.github/workflows/gen-lints.yml @@ -11,6 +11,7 @@ defaults: jobs: lints-gen: + if: ${{ github.repository == 'rust-lang/rust-analyzer' || github.event_name == 'workflow_dispatch' }} name: Generate lints runs-on: ubuntu-latest permissions: diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 5835ed9e552e7..cf4ba4404b367 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -1889,6 +1889,7 @@ dependencies = [ "line-index 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "paths", "proc-macro-test", + "rustc-hash 2.1.2", "span", "stdx", ] diff --git a/src/tools/rust-analyzer/clippy.toml b/src/tools/rust-analyzer/clippy.toml index 1046cb3d56bc6..f0a8a6132c6a2 100644 --- a/src/tools/rust-analyzer/clippy.toml +++ b/src/tools/rust-analyzer/clippy.toml @@ -1,9 +1,9 @@ disallowed-types = [ - { path = "std::collections::HashMap", reason = "use FxHashMap" }, - { path = "std::collections::HashSet", reason = "use FxHashSet" }, - { path = "std::collections::hash_map::RandomState", reason = "use BuildHasherDefault"} + { path = "std::collections::HashMap", replacement = "rustc_hash::FxHashMap" }, + { path = "std::collections::HashSet", replacement = "rustc_hash::FxHashSet" }, + { path = "std::collections::hash_map::RandomState", replacement = "std::hash::BuildHasherDefault"} ] disallowed-methods = [ - { path = "std::process::Command::new", reason = "use `toolchain::command` instead as it forces the choice of a working directory" }, + { path = "std::process::Command::new", replacement = "toolchain::command", reason = "the latter forces the choice of a working directory" }, ] diff --git a/src/tools/rust-analyzer/crates/base-db/src/input.rs b/src/tools/rust-analyzer/crates/base-db/src/input.rs index 230b7cbed680f..229ed82e06cc2 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/input.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/input.rs @@ -8,6 +8,7 @@ use std::error::Error; use std::hash::BuildHasherDefault; +use std::str::FromStr; use std::{fmt, mem, ops}; use cfg::{CfgOptions, HashableCfgOptions}; @@ -315,14 +316,17 @@ impl ReleaseChannel { ReleaseChannel::Nightly => "nightly", } } +} + +impl FromStr for ReleaseChannel { + type Err = (); - #[allow(clippy::should_implement_trait)] - pub fn from_str(str: &str) -> Option { - Some(match str { + fn from_str(str: &str) -> Result { + Ok(match str { "" | "stable" => ReleaseChannel::Stable, "nightly" => ReleaseChannel::Nightly, _ if str.starts_with("beta") => ReleaseChannel::Beta, - _ => return None, + _ => return Err(()), }) } } diff --git a/src/tools/rust-analyzer/crates/base-db/src/lib.rs b/src/tools/rust-analyzer/crates/base-db/src/lib.rs index 0da1faba676c0..1ce5f17e0e26c 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/lib.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/lib.rs @@ -19,6 +19,7 @@ use std::{ cell::RefCell, hash::BuildHasherDefault, panic, + str::FromStr as _, sync::{Once, atomic::AtomicUsize}, }; @@ -327,7 +328,7 @@ impl CrateWorkspaceData { } pub fn toolchain_channel(db: &dyn salsa::Database, krate: Crate) -> Option { - krate.workspace_data(db).toolchain.as_ref().and_then(|v| ReleaseChannel::from_str(&v.pre)) + krate.workspace_data(db).toolchain.as_ref().and_then(|v| ReleaseChannel::from_str(&v.pre).ok()) } #[salsa::input(singleton, debug)] diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attrs/docs.rs b/src/tools/rust-analyzer/crates/hir-def/src/attrs/docs.rs index ac8ca70ccc4b9..583bde92679dd 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attrs/docs.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attrs/docs.rs @@ -608,6 +608,7 @@ fn expand_doc_macro_call<'db>( ExpandTo::Expr, expander.krate, expander.macro_depth + 1, + expander.recursion_limit, |path| { expander.resolver.resolve_path_as_macro_def(expander.db, path, Some(MacroSubNs::Bang)) }, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs b/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs index c38ceccd1fc09..92400d0715395 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs @@ -119,10 +119,6 @@ pub struct Key { } impl Key { - #[allow( - clippy::new_without_default, - reason = "this a const fn, so it can't be default yet. See " - )] pub(crate) const fn new() -> Key { Key { _phantom: PhantomData } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs index 3a63ca80ffc68..7d01a7c436e28 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs @@ -624,7 +624,6 @@ impl ExpressionStore { visitor.on_expr_opt(*end); } Pat::Lit(expr) | Pat::Expr(expr) => visitor.on_expr(*expr), - Pat::ConstBlock(expr) => visitor.on_anon_const_expr(*expr), Pat::Path(path) => visitor.on_path(path), Pat::Wild | Pat::Missing | Pat::Rest | Pat::NotNull => {} &Pat::Bind { subpat, id: _ } => visitor.on_pat_opt(subpat), diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/expander.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/expander.rs index a974815cc6423..12a2263697908 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/expander.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/expander.rs @@ -111,7 +111,8 @@ impl<'db> Expander<'db> { call_site.ctx, expands_to, krate, - this.macro_depth, + this.macro_depth + 1, + this.recursion_limit, |path| resolver(path).map(|it| it.definition(db)), eager_callback, ) { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs index bb60766197b37..b5d5145927702 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs @@ -3082,16 +3082,7 @@ impl<'db> ExprCollector<'db> { Pat::Deref { inner } } ast::Pat::NotNull(_) => Pat::NotNull, - ast::Pat::ConstBlockPat(const_block_pat) => { - if let Some(block) = const_block_pat.block_expr() { - let expr_id = self.with_label_rib(RibKind::Constant, |this| { - this.with_binding_owner(|this| this.collect_block(block)) - }); - Pat::ConstBlock(expr_id) - } else { - Pat::Missing - } - } + ast::Pat::ConstBlockPat(_) => Pat::Missing, ast::Pat::MacroPat(mac) => { return self.collect_macro_pat_with(mac.clone(), |this, expanded_pat| { this.collect_pat(expanded_pat, binding_list) @@ -3277,16 +3268,6 @@ impl<'db> ExprCollector<'db> { let Some((literal, _)) = pat_literal_to_hir(it) else { return self.missing_expr() }; self.alloc_expr_from_pat(Expr::Literal(literal), ptr) } - ast::Pat::ConstBlockPat(it) => { - if let Some(block) = it.block_expr() { - let expr_id = self.with_label_rib(RibKind::Constant, |this| { - this.with_binding_owner(|this| this.collect_block(block)) - }); - self.alloc_expr_from_pat(Expr::Const(expr_id), ptr) - } else { - self.missing_expr() - } - } ast::Pat::PathPat(it) => { let path = it .path() diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs index 7d7b948d34149..1d01605695a74 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs @@ -1033,10 +1033,6 @@ impl Printer<'_> { self.print_pat(*inner); w!(self, ")"); } - Pat::ConstBlock(c) => { - w!(self, "const "); - self.print_expr(*c); - } Pat::Expr(expr) => { self.print_expr_in(prec, *expr); } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/scope.rs index 24baa0f8c8d89..a7403a0e555b9 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/scope.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/scope.rs @@ -115,7 +115,10 @@ impl ExprScopes { } /// If `scope` refers to a macro def scope, returns the corresponding `MacroId`. - #[allow(clippy::borrowed_box)] // If we return `&MacroDefId` we need to move it, this way we just clone the `Box`. + #[expect( + clippy::borrowed_box, + reason = "If we return `&MacroDefId` we need to move it, this way we just clone the `Box`." + )] pub fn macro_def(&self, scope: ScopeId) -> Option<&Box> { match &self.scopes[scope].kind { ScopeKind::MacroDef(macro_def) => Some(macro_def), @@ -818,66 +821,4 @@ fn test() { 100, ); } - #[test] - fn pattern_const_block_expressions_have_scopes() { - do_check( - r#" -fn foo() { - match () { - const { |x: i32| { let y = x; $0 } } => (), - } -} -"#, - &["y", "x"], - ); - } - - #[test] - fn let_pattern_expr_scope() { - do_check( - r#" -fn foo(param: usize) { - let local = 0; - let const { $0 } = (); -} -"#, - &["param"], - ); - } - - #[test] - fn closure_param_pattern_expr_scope() { - do_check( - r#" -fn foo(param: usize) { - let local = 0; - let _ = |const { $0 }: ()| (); -} -"#, - &["param"], - ); - } - - #[test] - fn fn_param_pattern_expr_scope() { - do_check( - r#" -fn foo(param: usize, const { $0 }: ()) {} -"#, - &["param"], - ); - } - - #[test] - fn if_let_pattern_expr_scope() { - do_check( - r#" -fn foo(param: usize) { - let local = 0; - if let const { $0 } = () {} -} -"#, - &["param"], - ); - } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir.rs index 5785a546513c9..85a41c6495159 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/hir.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/hir.rs @@ -800,7 +800,6 @@ pub enum Pat { inner: PatId, }, NotNull, - ConstBlock(ExprId), /// An expression inside a pattern. That can only occur inside assignments. /// /// E.g. in `(a, *b) = (1, &mut 2)`, `*b` is an expression. @@ -813,7 +812,6 @@ impl Pat { Pat::Range { .. } | Pat::Lit(..) | Pat::Path(..) - | Pat::ConstBlock(..) | Pat::Wild | Pat::Missing | Pat::Rest diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs index 366857f233168..855b16bc28673 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs @@ -169,7 +169,6 @@ enum PositionUsedAs { } use PositionUsedAs::*; -#[allow(clippy::unnecessary_lazy_evaluations)] pub(crate) fn parse( s: &ast::String, string_ptr: AstPtr, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs index 0712a025b49cb..77d00072fd2df 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs @@ -1442,6 +1442,7 @@ pub fn macro_call_as_call_id( expand_to: ExpandTo, krate: Crate, macro_depth: u32, + recursion_limit: u32, resolver: impl Fn(&ModPath) -> Option + Copy, eager_callback: &mut dyn FnMut( InFile<(syntax::AstPtr, span::FileAstId)>, @@ -1459,6 +1460,7 @@ pub fn macro_call_as_call_id( def, call_site, macro_depth, + recursion_limit, &|path| resolver(path).filter(MacroDefId::is_fn_like), eager_callback, ), diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs index 7120980dd30cf..1ba636ee901c5 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs @@ -628,3 +628,34 @@ const _: bool = foo::<(), fn() -> Foo>(1, ); "#]], ); } + +#[test] +fn eager_recursion_limit() { + check( + r#" +//- minicore: concat + +macro_rules! concat_separator { + () => { + concat!("", concat_separator!()) + }; +} + +fn main() { + concat_separator!() +} + "#, + expect![[r#" + +macro_rules! concat_separator { + () => { + concat!("", concat_separator!()) + }; +} + +fn main() { + concat!("", concat_separator!()) +} + "#]], + ); +} diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs index 8dea9a4eda1da..0e27d74516007 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs @@ -323,6 +323,7 @@ impl<'db> AssocItemCollector<'db> { ExpandTo::Items, self.module_id.krate(self.db), self.macro_depth + 1, + self.def_map.recursion_limit(), resolver, &mut |ptr, call_id| { self.macro_calls.push((ptr.map(|(_, it)| it.upcast()), call_id)) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs index ce359ebda6af2..e40e4d99bdbd0 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs @@ -1360,6 +1360,7 @@ impl<'db> DefCollector<'db> { *expand_to, self.def_map.krate, directive.depth, + self.def_map.recursion_limit(), resolver_def_id, &mut |ptr, call_id| { eager_callback_buffer.push((directive.module_id, ptr, call_id)); @@ -1793,6 +1794,7 @@ impl<'db> DefCollector<'db> { *expand_to, self.def_map.krate, directive.depth, + self.def_map.recursion_limit(), |path| { let resolved_res = self.def_map.resolve_path_fp_with_macro( self.crate_local_def_map.unwrap_or(&self.local_def_map), @@ -2698,6 +2700,7 @@ impl ModCollector<'_, '_> { expand_to, self.def_collector.def_map.krate, self.macro_depth + 1, + self.def_collector.def_map.recursion_limit(), |path| { path.as_ident().and_then(|name| { let def_map = &self.def_collector.def_map; diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs index d84756377fc75..a7fcbc6f9f535 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs @@ -1,5 +1,4 @@ //! A simplified version of quote-crate like quasi quote macro -#![allow(clippy::crate_in_macro_def)] use intern::{Symbol, sym}; use span::Span; @@ -185,7 +184,7 @@ macro_rules! impl_to_to_tokentrees { $( impl ToTokenTree for $ty { fn to_tokens($this, $span: Span, builder: &mut TopSubtreeBuilder) { - let leaf: crate::tt::Leaf = $im.into(); + let leaf: $crate::tt::Leaf = $im.into(); builder.push(leaf); } } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs b/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs index 7002b70a7687b..bddec50c91c04 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs @@ -26,8 +26,8 @@ use syntax::{ use syntax_bridge::DocCommentDesugarMode; use crate::{ - AstId, EagerCallInfo, ExpandError, ExpandResult, ExpandTo, ExpansionSpanMap, InFile, - MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind, + AstId, EagerCallInfo, ExpandError, ExpandErrorKind, ExpandResult, ExpandTo, ExpansionSpanMap, + InFile, MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind, ast::{self, AstNode}, mod_path::ModPath, }; @@ -45,6 +45,7 @@ pub fn expand_eager_macro_input( def: MacroDefId, call_site: SyntaxContext, macro_depth: u32, + recursion_limit: u32, resolver: &dyn Fn(&ModPath) -> Option, eager_callback: EagerCallBackFn<'_>, ) -> ExpandResult> { @@ -62,7 +63,7 @@ pub fn expand_eager_macro_input( macro_depth, }; let arg_id = MacroCallId::new(db, loc); - #[allow(deprecated)] // builtin eager macros are never derives + #[expect(deprecated, reason = "builtin eager macros are never derives")] let (_, _, span) = arg_id.macro_arg(db); let ExpandResult { value: (arg_exp, arg_exp_map), err: parse_err } = arg_id.parse_macro_expansion(db); @@ -79,6 +80,7 @@ pub fn expand_eager_macro_input( krate, call_site, macro_depth, + recursion_limit, resolver, eager_callback, ) @@ -155,6 +157,7 @@ fn eager_macro_recur( krate: Crate, call_site: SyntaxContext, macro_depth: u32, + recursion_limit: u32, macro_resolver: &dyn Fn(&ModPath) -> Option, eager_callback: EagerCallBackFn<'_>, ) -> ExpandResult> { @@ -213,6 +216,14 @@ fn eager_macro_recur( } }; let ast_id = curr.file_id.ast_id_map(db).ast_id(&call); + + if macro_depth > recursion_limit { + return ExpandResult::only_err(ExpandError::new( + span_map.span_at(call.syntax().text_range().start()), + ExpandErrorKind::RecursionOverflow, + )); + } + let ExpandResult { value, err } = match def.kind { MacroDefKind::BuiltInEager(..) => { let ExpandResult { value, err } = expand_eager_macro_input( @@ -223,6 +234,7 @@ fn eager_macro_recur( def, call_site, macro_depth + 1, + recursion_limit, macro_resolver, eager_callback, ); @@ -277,6 +289,7 @@ fn eager_macro_recur( krate, call_site, macro_depth + 1, + recursion_limit, macro_resolver, eager_callback, ); diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs b/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs index 8781358822064..2fda00d6af8d0 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs @@ -343,7 +343,6 @@ pub(crate) fn reverse_fixups(tt: &mut TopSubtree, undo_info: &SyntaxFixupUndoInf let top_subtree = tt.top_subtree(); let open_span = top_subtree.delimiter.open; let close_span = top_subtree.delimiter.close; - #[allow(deprecated)] if never!( close_span.anchor.ast_id == FIXUP_DUMMY_AST_ID || open_span.anchor.ast_id == FIXUP_DUMMY_AST_ID diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs index f7ac3f1c02694..e646c21ec8c5e 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs @@ -519,7 +519,7 @@ impl MacroCallId { /// This is not connected to the database so it does not cache the result. However, the inner [macro_arg] query is /// /// [macro_arg]: Self::macro_arg - #[allow(deprecated)] // we are macro_arg_considering_derives + #[expect(deprecated, reason = "we are `macro_arg_considering_derives`")] pub fn macro_arg_considering_derives<'db>( self, db: &'db dyn SourceDatabase, @@ -537,6 +537,12 @@ impl MacroCallId { /// query, only typing in the macro call itself changes the returned /// subtree. #[salsa::tracked(returns(ref))] + #[allow( + useless_deprecated, + unused_attributes, + reason = "salsa bug, see https://github.com/salsa-rs/salsa/issues/1307" + )] + #[deprecated = "calling this is incorrect, call `macro_arg_considering_derives` instead"] fn macro_arg(self, db: &dyn SourceDatabase) -> MacroArgResult { let loc = self.loc(db); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/builtin_derive.rs b/src/tools/rust-analyzer/crates/hir-ty/src/builtin_derive.rs index baa7b87e457f9..53a232adfc7ac 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/builtin_derive.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/builtin_derive.rs @@ -195,7 +195,7 @@ pub fn predicates(db: &dyn HirDatabase, impl_: BuiltinDeriveImplId) -> GenericPr else { // Malformed derive. return GenericPredicates::from_explicit_own_predicates(StoredEarlyBinder::bind( - Clauses::empty(interner).store(), + Clauses::empty().store(), )); }; let duplicated_bounds = diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs index d65f76cdf1ceb..a1ed1e71aecc3 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs @@ -253,7 +253,7 @@ pub fn try_const_usize<'db>(db: &'db dyn HirDatabase, c: Const<'db>) -> Option { - if val.ty == default_types(db).types.usize { + if val.ty == default_types().types.usize { Some(val.value.inner().to_leaf().to_uint_unchecked()) } else { None @@ -291,7 +291,7 @@ pub fn try_const_isize<'db>(db: &'db dyn HirDatabase, c: Const<'db>) -> Option { - if val.ty == default_types(db).types.isize { + if val.ty == default_types().types.isize { Some(val.value.inner().to_leaf().to_int_unchecked()) } else { None @@ -347,7 +347,7 @@ pub(crate) fn path_to_const<'a, 'db>( | ValueNs::StructId(_) | ValueNs::EnumVariantId(_) => return Err(CreateConstError::ResolveToNonConst), }; - let args = GenericArgs::empty(interner); + let args = GenericArgs::empty(); Ok(Const::new_unevaluated(interner, UnevaluatedConst { def: konst.into(), args })) } @@ -411,7 +411,7 @@ pub(crate) fn create_anon_const<'a, 'db>( let args = if allow_using_generic_params { GenericArgs::identity_for_item(interner, owner.generic_def(interner.db).into()) } else { - GenericArgs::empty(interner) + GenericArgs::empty() }; Ok(Const::new_unevaluated( interner, @@ -426,7 +426,6 @@ pub(crate) fn const_eval_discriminant_variant<'db>( db: &'db dyn HirDatabase, variant_id: EnumVariantId, ) -> Result> { - let interner = DbInterner::new_no_crate(db); let def = variant_id.into(); let body = Body::of(db, def); let loc = variant_id.lookup(db); @@ -446,7 +445,7 @@ pub(crate) fn const_eval_discriminant_variant<'db>( let mir_body = db.monomorphized_mir_body( def.into(), - GenericArgs::empty(interner).store(), + GenericArgs::empty().store(), ParamEnvAndCrate { param_env: db.trait_environment(def.generic_def(db)), krate: def.krate(db), @@ -561,10 +560,9 @@ pub(crate) fn const_eval_static<'db>( db: &'db dyn HirDatabase, def: StaticId, ) -> Result> { - let interner = DbInterner::new_no_crate(db); let body = db.monomorphized_mir_body( def.into(), - GenericArgs::empty(interner).store(), + GenericArgs::empty().store(), ParamEnvAndCrate { param_env: db.trait_environment(def.into()), krate: def.krate(db) } .store(), )?; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs index 6ea8376e48743..b17df991f7afe 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs @@ -14,7 +14,7 @@ use crate::{ db::HirDatabase, display::DisplayTarget, mir::{IsSigned, pad16}, - next_solver::{Allocation, DbInterner, GenericArgs}, + next_solver::{Allocation, GenericArgs}, setup_tracing, test_db::TestDB, }; @@ -120,7 +120,6 @@ fn pretty_print_err(e: ConstEvalError<'_>, db: &TestDB) -> String { fn eval_goal(db: &TestDB, file_id: EditionedFileId) -> Result, ConstEvalError<'_>> { let _tracing = setup_tracing(); - let interner = DbInterner::new_no_crate(db); let module_id = db.module_for_file(file_id.file_id(db)); let def_map = module_id.def_map(db); let scope = &def_map[module_id].scope; @@ -143,7 +142,7 @@ fn eval_goal(db: &TestDB, file_id: EditionedFileId) -> Result, Co _ => None, }) .expect("No const named GOAL found in the test"); - db.const_eval(const_id, GenericArgs::empty(interner), None) + db.const_eval(const_id, GenericArgs::empty(), None) } #[test] diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests/intrinsics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests/intrinsics.rs index 898d9ea8edf3d..ab6294cb375df 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests/intrinsics.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests/intrinsics.rs @@ -469,7 +469,8 @@ fn floating_point() { IsSigned::Yes, )), ); - #[allow(unknown_lints, clippy::unnecessary_min_or_max)] + // FIXME: this should be an `expect`, but that currently results in `lint_expectation_unfulfilled` + #[allow(clippy::unnecessary_min_or_max, reason = "for symmetry with the expression in `GOAL`")] check_number( r#" #[rustc_intrinsic] diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics.rs index 047a348fb09a7..17ec211bb579c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics.rs @@ -9,8 +9,5 @@ pub use crate::diagnostics::{ expr::{ BodyValidationDiagnostic, record_literal_missing_fields, record_pattern_missing_fields, }, - unsafe_check::{ - InsideUnsafeBlock, UnsafetyReason, missing_unsafe, unsafe_operations, - unsafe_operations_for_body, - }, + unsafe_check::{InsideUnsafeBlock, UnsafetyReason, missing_unsafe, unsafe_operations}, }; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs index a465f8be4e175..cccefbc8639ac 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs @@ -507,17 +507,14 @@ impl<'a> DeclValidator<'a> { self.validate_enum_variant_fields(*variant_id); } - let edition = self.edition(enum_id); let mut enum_variants_replacements = data .variants .keys() .filter_map(|name| { - to_camel_case(&name.display_no_db(edition).to_smolstr()).map(|new_name| { - Replacement { - current_name: name.clone(), - suggested_text: new_name, - expected_case: CaseType::UpperCamelCase, - } + to_camel_case(name.as_str()).map(|new_name| Replacement { + current_name: name.clone(), + suggested_text: new_name, + expected_case: CaseType::UpperCamelCase, }) }) .peekable(); @@ -717,11 +714,12 @@ impl<'a> DeclValidator<'a> { CaseType::UpperCamelCase => to_camel_case, }; let edition = self.edition(item_id); - let Some(replacement) = - to_expected_case_type(&name.display(self.db, edition).to_smolstr()).map(|new_name| { - Replacement { current_name: name.clone(), suggested_text: new_name, expected_case } - }) - else { + let Some(replacement) = to_expected_case_type(name.as_str()).map(|mut new_name| { + if is_raw_identifier(&new_name, edition) { + new_name.insert_str(0, "r#"); + } + Replacement { current_name: name.clone(), suggested_text: new_name, expected_case } + }) else { return; }; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs index 94b1ec331f87d..1eb2bf0f85bff 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs @@ -703,7 +703,7 @@ fn types_of_subpatterns_do_match(pat: PatId, body: &Body, infer: &InferenceResul false if *has_type_mismatches => (), false => { let pat = &body[pat]; - if let Pat::ConstBlock(expr) | Pat::Lit(expr) = *pat { + if let Pat::Lit(expr) = *pat { *has_type_mismatches |= infer.expr_has_type_mismatch(expr); if *has_type_mismatches { return; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs index ca843c8690f28..4818b2f49bf73 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs @@ -101,25 +101,6 @@ enum UnsafeDiagnostic { DeprecatedSafe2024 { node: ExprId, inside_unsafe_block: InsideUnsafeBlock }, } -pub fn unsafe_operations_for_body( - db: &dyn HirDatabase, - infer: &InferenceResult<'_>, - def: DefWithBodyId, - body: &Body, - callback: &mut dyn FnMut(ExprOrPatId), -) { - let mut visitor_callback = |diag| { - if let UnsafeDiagnostic::UnsafeOperation { node, .. } = diag { - callback(node); - } - }; - let mut visitor = UnsafeVisitor::new(db, infer, body, def.into(), &mut visitor_callback); - visitor.walk_expr(body.root_expr()); - for param in &body.params { - visitor.walk_pat(param.formal); - } -} - pub fn unsafe_operations( db: &dyn HirDatabase, infer: &InferenceResult<'_>, @@ -258,7 +239,6 @@ impl<'db> UnsafeVisitor<'db> { | Pat::Box { .. } | Pat::Deref { .. } | Pat::Expr(..) - | Pat::ConstBlock(..) | Pat::NotNull => self.on_unsafe_op(current.into(), UnsafetyReason::UnionField), // `Or` only wraps other patterns, and `Missing`/`Wild` do not constitute a read. Pat::Missing | Pat::Rest | Pat::Wild | Pat::Or(_) => {} @@ -276,11 +256,6 @@ impl<'db> UnsafeVisitor<'db> { } } Pat::Path(path) => self.mark_unsafe_path(current.into(), path), - &Pat::ConstBlock(expr) => { - let old_inside_assignment = mem::replace(&mut self.inside_assignment, false); - self.walk_expr(expr); - self.inside_assignment = old_inside_assignment; - } &Pat::Expr(expr) => self.walk_expr(expr), _ => {} } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs index a87a55b3c8980..e83962ec25ec2 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs @@ -811,7 +811,7 @@ fn render_const_scalar<'db>( memory_map: &MemoryMap<'db>, ty: Ty<'db>, ) -> Result { - let param_env = ParamEnv::empty(f.interner); + let param_env = ParamEnv::empty(); let infcx = f.interner.infer_ctxt().build(TypingMode::PostAnalysis); let ty = infcx.at(&ObligationCause::dummy(), param_env).deeply_normalize(ty).unwrap_or(ty); render_const_scalar_inner(f, b, memory_map, ty, param_env) @@ -1086,7 +1086,7 @@ fn render_const_scalar_from_valtree<'db>( ty: Ty<'db>, valtree: ValTree<'db>, ) -> Result { - let param_env = ParamEnv::empty(f.interner); + let param_env = ParamEnv::empty(); let infcx = f.interner.infer_ctxt().build(TypingMode::PostAnalysis); let ty = infcx.at(&ObligationCause::dummy(), param_env).deeply_normalize(ty).unwrap_or(ty); render_const_scalar_from_valtree_inner(f, ty, valtree, param_env) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs index a70f98a0fe7bb..241beea6779e7 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs @@ -14,14 +14,13 @@ use super::{ use DynCompatibilityViolationKind::*; -#[allow(clippy::upper_case_acronyms)] #[derive(Debug, Clone, PartialEq, Eq, Hash)] enum DynCompatibilityViolationKind { SizedSelf, SelfReferential, Method(MethodViolationCode), AssocConst, - GAT, + Gat, HasNonCompatibleSuperTrait, } @@ -63,7 +62,7 @@ fn check_dyn_compatibility<'a>( DynCompatibilityViolation::SelfReferential => SelfReferential, DynCompatibilityViolation::Method(_, mvc) => Method(mvc), DynCompatibilityViolation::AssocConst(_) => AssocConst, - DynCompatibilityViolation::GAT(_) => GAT, + DynCompatibilityViolation::GAT(_) => Gat, DynCompatibilityViolation::HasNonCompatibleSuperTrait(_) => { HasNonCompatibleSuperTrait } @@ -236,7 +235,7 @@ trait GatTrait { trait SuperTrait: GatTrait {} "#, - [("GatTrait", vec![GAT]), ("SuperTrait", vec![HasNonCompatibleSuperTrait])], + [("GatTrait", vec![Gat]), ("SuperTrait", vec![HasNonCompatibleSuperTrait])], ); } @@ -396,6 +395,6 @@ trait Foo { type Bar<'a>; } "#, - [("Foo", vec![DynCompatibilityViolationKind::GAT])], + [("Foo", vec![DynCompatibilityViolationKind::Gat])], ); } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs index 0ab147096a749..cbe5b671fe83a 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs @@ -109,12 +109,7 @@ use crate::{ utils::TargetFeatureIsSafeInTarget, }; -// This lint has a false positive here. See the link below for details. -// -// https://github.com/rust-lang/rust/issues/57411 -#[allow(unreachable_pub)] pub use coerce::could_coerce; -#[allow(unreachable_pub)] pub use unify::{could_unify, could_unify_deeply}; use cast::{CastCheck, CastError}; @@ -1429,7 +1424,7 @@ impl<'db> InferenceContext<'db> { ) -> Self { let trait_env = db.trait_environment(generic_def); let table = unify::InferenceTable::new(db, trait_env, resolver.krate(), owner); - let types = crate::next_solver::default_types(db); + let types = crate::next_solver::default_types(); InferenceContext { result: InferenceResult::new(types.types.error), return_ty: types.types.error, // set in collect_* calls diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure/analysis/expr_use_visitor.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure/analysis/expr_use_visitor.rs index da9c5ab10fc46..6a4e38c5264a7 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure/analysis/expr_use_visitor.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure/analysis/expr_use_visitor.rs @@ -976,7 +976,7 @@ impl<'a, 'db, D: Delegate<'db>> ExprUseVisitor<'a, 'db, D> { read_discriminant(this); } } - Pat::Lit(_) | Pat::ConstBlock(_) | Pat::Range { .. } => { + Pat::Lit(_) | Pat::Range { .. } => { // When matching against a literal or range, we need to // borrow the place to compare it against the pattern. // @@ -1690,7 +1690,6 @@ impl<'db, D: Delegate<'db>> ExprUseVisitor<'_, 'db, D> { | Pat::Expr(..) | Pat::Path(_) | Pat::Lit(..) - | Pat::ConstBlock(..) | Pat::Range { .. } | Pat::Missing | Pat::Rest diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs index af301731c7156..8c9e814015897 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs @@ -192,7 +192,6 @@ impl<'db> InferenceContext<'db> { | Pat::Lit(_) | Pat::Range { .. } | Pat::Slice { .. } - | Pat::ConstBlock(_) | Pat::Record { .. } | Pat::NotNull | Pat::Missing => true, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs index 09b0d3c03d5b8..9d55bf36e5468 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs @@ -171,7 +171,6 @@ impl<'db> InferenceContext<'db> { &Expr::Assignment { target, value } => { self.store.walk_pats(target, &mut |pat| match self.store[pat] { Pat::Expr(expr) => self.infer_mut_expr(expr, Mutability::Mut), - Pat::ConstBlock(block) => self.infer_mut_expr(block, Mutability::Not), _ => {} }); self.infer_mut_expr(value, Mutability::Not); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs index 3a867286eec53..17c198879f265 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs @@ -530,9 +530,6 @@ impl<'db> InferenceContext<'db> { self.infer_slice_pat(pat, before, slice, after, expected, pat_info) } Pat::Expr(expr) => self.infer_destructuring_assignment_expr(expr, expected), - Pat::ConstBlock(expr) => { - self.infer_expr(expr, &Expectation::has_type(expected), ExprIsRead::Yes) - } } } @@ -634,9 +631,8 @@ impl<'db> InferenceContext<'db> { // All other literals result in non-reference types. // As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo" {}` unless // `deref_patterns` is enabled. - &Pat::Lit(expr) | &Pat::ConstBlock(expr) => { + &Pat::Lit(expr) => { let lit_ty = self.infer_expr_pat_unadjusted(expr); - // Call `resolve_vars_if_possible` here for inline const blocks. let lit_ty = self.infcx().resolve_vars_if_possible(lit_ty); // If `deref_patterns` is enabled, allow `if let "foo" = &&"foo" {}`. if self.features.deref_patterns { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs index 5098b38c4380c..2a6e8a396279b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs @@ -211,9 +211,7 @@ macro_rules! size_and_align { macro_rules! size_and_align_expr { (minicore: $($x:tt),*; stmts: [$($s:tt)*] $($t:tt)*) => { { - #[allow(dead_code)] - #[allow(unused_must_use)] - #[allow(path_statements)] + #[allow(dead_code, unused_must_use, path_statements)] { $($s)* let val = { $($t)* }; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs index b86585231cca1..04e453fde3b93 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs @@ -252,7 +252,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { db, // Can provide no block since we don't use it for trait solving. interner, - types: crate::next_solver::default_types(db), + types: crate::next_solver::default_types(), lang_items: interner.lang_items(), resolver, def, @@ -635,7 +635,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { // place even if we encounter more opaque types while // lowering the bounds let idx = self.impl_trait_mode.opaque_type_data.alloc(ImplTrait { - predicates: StoredEarlyBinder::bind(Clauses::empty(interner).store()), + predicates: StoredEarlyBinder::bind(Clauses::empty().store()), assoc_ty_bounds_start: 0, }); @@ -2372,12 +2372,12 @@ impl<'db> GenericPredicates { /// A cycle can occur from malformed code. fn generic_predicates_cycle_result<'db>( - db: &'db dyn HirDatabase, + _db: &'db dyn HirDatabase, _: salsa::Id, _def: GenericDefId, ) -> TyLoweringResult<'db, GenericPredicates> { TyLoweringResult::empty(GenericPredicates::from_explicit_own_predicates( - StoredEarlyBinder::bind(Clauses::empty(DbInterner::new_no_crate(db)).store()), + StoredEarlyBinder::bind(Clauses::empty().store()), )) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs index c67c69520db10..7e55ef2963169 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs @@ -576,7 +576,6 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { lowering_assoc_type_generics: bool, span: Span, ) -> GenericArgs<'db> { - let interner = self.ctx.interner; let prev_current_segment_idx = self.current_segment_idx; let prev_current_segment = self.current_or_prev_segment; @@ -586,7 +585,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { ValueTyDefId::UnionId(it) => it.into(), ValueTyDefId::ConstId(it) => it.into(), ValueTyDefId::StaticId(_) => { - return GenericArgs::empty(interner); + return GenericArgs::empty(); } ValueTyDefId::EnumVariantId(var) => { // the generic args for an enum variant may be either specified diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs index d6db51dec52b9..37f3e27631810 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs @@ -309,7 +309,6 @@ const STACK_OFFSET: usize = 1 << 30; const HEAP_OFFSET: usize = 1 << 29; impl Address { - #[allow(clippy::double_parens)] fn from_bytes<'db>(it: &[u8]) -> Result<'db, Self> { Ok(Address::from_usize(from_bytes!(usize, it))) } @@ -1504,8 +1503,7 @@ impl<'a, 'db> Evaluator<'a, 'db> { )?) } AggregateKind::Union(it, f) => { - let layout = - self.layout_adt((*it).into(), GenericArgs::empty(self.interner()))?; + let layout = self.layout_adt((*it).into(), GenericArgs::empty())?; let offset = layout .fields .offset(u32::from(f.local_id.into_raw()) as usize) @@ -2093,7 +2091,6 @@ impl<'a, 'db> Evaluator<'a, 'db> { } } - #[allow(clippy::double_parens)] fn allocate_const_in_heap( &mut self, locals: &Locals<'a, 'db>, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs index 5a43696233079..ca7c5c7366803 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs @@ -1246,7 +1246,7 @@ impl<'a, 'db> Evaluator<'a, 'db> { def, &args, // FIXME: wrong for manual impls of `FnOnce` - GenericArgs::empty(self.interner()), + GenericArgs::empty(), locals, destination, None, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs index f09ac6f20d271..2ac3811f1769a 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs @@ -5,19 +5,14 @@ use syntax::{TextRange, TextSize}; use test_fixture::WithFixture; use crate::{ - db::HirDatabase, - display::DisplayTarget, - mir::MirLowerError, - next_solver::{DbInterner, GenericArgs}, - setup_tracing, - test_db::TestDB, + db::HirDatabase, display::DisplayTarget, mir::MirLowerError, next_solver::GenericArgs, + setup_tracing, test_db::TestDB, }; use super::{MirEvalError, interpret_mir}; fn eval_main(db: &TestDB, file_id: EditionedFileId) -> Result<(String, String), MirEvalError<'_>> { crate::attach_db(db, || { - let interner = DbInterner::new_no_crate(db); let module_id = db.module_for_file(file_id.file_id(db)); let def_map = module_id.def_map(db); let scope = &def_map[module_id].scope; @@ -39,7 +34,7 @@ fn eval_main(db: &TestDB, file_id: EditionedFileId) -> Result<(String, String), let body = db .monomorphized_mir_body( func_id.into(), - GenericArgs::empty(interner).store(), + GenericArgs::empty().store(), crate::ParamEnvAndCrate { param_env: db.trait_environment(func_id.into()), krate: func_id.krate(db), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs index da631c0d595ea..3b82ed6f798e4 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs @@ -324,7 +324,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { db, infer, store, - types: crate::next_solver::default_types(db), + types: crate::next_solver::default_types(), owner, store_owner, resolver, @@ -547,7 +547,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { const_id.into(), current, place, - GenericArgs::empty(self.interner()), + GenericArgs::empty(), expr_id.into(), )?; Ok(Some(current)) @@ -1377,10 +1377,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { match pr { ResolveValueResult::ValueNs(v) => { if let ValueNs::ConstId(c) = v { - self.lower_const_to_operand( - GenericArgs::empty(self.interner()), - c.into(), - ) + self.lower_const_to_operand(GenericArgs::empty(), c.into()) } else { not_supported!("bad path in range pattern"); } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs index 682ae827db67d..ecc013506689d 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs @@ -413,7 +413,7 @@ impl<'db> MirLowerCtx<'_, 'db> { break 'b (c, x.1); } if let ResolveValueResult::ValueNs(ValueNs::ConstId(c)) = pr { - break 'b (c, GenericArgs::empty(self.interner())); + break 'b (c, GenericArgs::empty()); } not_supported!("path in pattern position that is not const or variant") }; @@ -519,7 +519,6 @@ impl<'db> MirLowerCtx<'_, 'db> { } Pat::Box { .. } => not_supported!("box pattern"), Pat::Deref { .. } => not_supported!("deref pattern"), - Pat::ConstBlock(_) => not_supported!("const block pattern"), }) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver.rs index 42fd31f2594da..6263571286721 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver.rs @@ -43,7 +43,6 @@ use rustc_type_ir::MayBeErased; pub use solver::*; pub use ty::*; -use crate::db::HirDatabase; pub use crate::lower::ImplTraitIdx; pub use rustc_ast_ir::Mutability; @@ -143,25 +142,24 @@ impl std::fmt::Debug for DefaultAny<'_> { } #[inline] -pub fn default_types<'db>(db: &'db dyn HirDatabase) -> &'db DefaultAny<'db> { +pub fn default_types<'db>() -> &'db DefaultAny<'db> { static TYPES: OnceLock> = OnceLock::new(); - let interner = DbInterner::new_no_crate(db); TYPES.get_or_init(|| { let create_ty = |kind| { - let ty = Ty::new(interner, kind); + let ty = Ty::new_without_interner(kind); // We need to increase the refcount (forever), so that the types won't be freed. let ty = ManuallyDrop::new(ty.store()); ty.as_ref() }; let create_const = |kind| { - let ty = Const::new(interner, kind); + let ty = Const::new_without_interner(kind); // We need to increase the refcount (forever), so that the types won't be freed. let ty = ManuallyDrop::new(ty.store()); ty.as_ref() }; let create_region = |kind| { - let ty = Region::new(interner, kind); + let ty = Region::new_without_interner(kind); // We need to increase the refcount (forever), so that the types won't be freed. let ty = ManuallyDrop::new(ty.store()); ty.as_ref() diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/consts.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/consts.rs index 1cabafa89bc4e..a9cfafb2e4890 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/consts.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/consts.rs @@ -48,7 +48,10 @@ const _: () = { }; impl<'db> Const<'db> { - pub fn new(_interner: DbInterner<'db>, kind: ConstKind<'db>) -> Self { + /// You should avoid using this if you can, since we want `Ty` to be defined in `rustc_type_ir` and then this method + /// will become more difficult to use. + #[inline] + pub fn new_without_interner(kind: ConstKind<'db>) -> Self { let kind = unsafe { std::mem::transmute::, ConstKind<'static>>(kind) }; let flags = FlagComputation::for_const_kind(&kind); let cached = WithCachedTypeInfo { @@ -59,6 +62,10 @@ impl<'db> Const<'db> { Self { interned: Interned::new_gc(ConstInterned(cached)) } } + pub fn new(_interner: DbInterner<'db>, kind: ConstKind<'db>) -> Self { + Self::new_without_interner(kind) + } + pub fn inner(&self) -> &WithCachedTypeInfo> { let inner = &self.interned.0; unsafe { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/infer/canonical/canonicalizer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/infer/canonical/canonicalizer.rs index 33e4c175d0635..e6416eadc05ec 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/infer/canonical/canonicalizer.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/infer/canonical/canonicalizer.rs @@ -498,7 +498,7 @@ impl<'cx, 'db> Canonicalizer<'cx, 'db> { { let base = Canonical { max_universe: UniverseIndex::ROOT, - var_kinds: CanonicalVarKinds::empty(tcx), + var_kinds: CanonicalVarKinds::empty(), value: (), }; Canonicalizer::canonicalize_with_base( diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs index 7b2a811a01afe..df7c9bfe1ec44 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs @@ -90,8 +90,8 @@ macro_rules! interned_slice { impl<'db> $name<'db> { #[inline] - pub fn empty(interner: DbInterner<'db>) -> Self { - interner.default_types().empty.$default_types_field + pub fn empty() -> Self { + $crate::next_solver::default_types().empty.$default_types_field } #[inline] @@ -168,7 +168,7 @@ macro_rules! interned_slice { impl<'db> Default for $name<'db> { #[inline] fn default() -> Self { - $name::empty(DbInterner::conjure()) + $name::empty() } } @@ -399,7 +399,7 @@ impl<'db> DbInterner<'db> { #[inline] pub fn default_types(&self) -> &'db crate::next_solver::DefaultAny<'db> { - crate::next_solver::default_types(self.db) + crate::next_solver::default_types() } #[inline] @@ -1092,7 +1092,7 @@ impl<'db> Interner for DbInterner<'db> { | SolverDefId::InternedCoroutineId(_) | SolverDefId::InternedCoroutineClosureId(_) | SolverDefId::AnonConstId(_) => { - return VariancesOf::empty(self); + return VariancesOf::empty(); } }; self.db.variances_of(generic_def) @@ -1345,7 +1345,7 @@ impl<'db> Interner for DbInterner<'db> { let own_bounds: FxHashSet<_> = self.item_self_bounds(def_id).skip_binder().into_iter().collect(); if all_bounds.len() == own_bounds.len() { - EarlyBinder::bind(Clauses::empty(self)) + EarlyBinder::bind(Clauses::empty()) } else { EarlyBinder::bind(Clauses::new_from_iter( self, @@ -2172,7 +2172,7 @@ impl<'db> Interner for DbInterner<'db> { }; EarlyBinder::bind(Const::new_unevaluated( self, - UnevaluatedConst { def: GeneralConstIdWrapper(id), args: GenericArgs::empty(self) }, + UnevaluatedConst { def: GeneralConstIdWrapper(id), args: GenericArgs::empty() }, )) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/predicate.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/predicate.rs index cf492e65c3ff3..a1e249eaf9517 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/predicate.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/predicate.rs @@ -16,8 +16,8 @@ use rustc_type_ir::{ }; use crate::next_solver::{ - GenericArg, TraitIdWrapper, impl_foldable_for_interned_slice, impl_stored_interned_slice, - interned_slice, + GenericArg, TraitIdWrapper, default_types, impl_foldable_for_interned_slice, + impl_stored_interned_slice, interned_slice, }; use super::{Binder, BoundVarKinds, DbInterner, Region, Ty}; @@ -274,8 +274,8 @@ impl<'db> std::fmt::Debug for Clauses<'db> { impl<'db> Clauses<'db> { #[inline] - pub fn empty(interner: DbInterner<'db>) -> Self { - interner.default_types().empty.clauses + pub fn empty() -> Self { + default_types().empty.clauses } #[inline] @@ -321,6 +321,13 @@ impl<'db> Clauses<'db> { } } +impl Default for Clauses<'_> { + #[inline] + fn default() -> Self { + Self::empty() + } +} + impl<'db> IntoIterator for Clauses<'db> { type IntoIter = ::std::iter::Copied<::std::slice::Iter<'db, Clause<'db>>>; type Item = Clause<'db>; @@ -437,8 +444,9 @@ pub struct ParamEnv<'db> { } impl<'db> ParamEnv<'db> { - pub fn empty(interner: DbInterner<'db>) -> Self { - ParamEnv { clauses: Clauses::empty(interner) } + #[inline] + pub fn empty() -> Self { + ParamEnv { clauses: Clauses::empty() } } pub fn clauses(self) -> Clauses<'db> { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/region.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/region.rs index a6facff7623d8..53099f67fcd5a 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/region.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/region.rs @@ -38,11 +38,17 @@ const _: () = { }; impl<'db> Region<'db> { - pub fn new(_interner: DbInterner<'db>, kind: RegionKind<'db>) -> Self { + /// You should avoid using this if you can, since we want `Region` to be defined in `rustc_type_ir` and then this method + /// will become more difficult to use. + pub fn new_without_interner(kind: RegionKind<'db>) -> Self { let kind = unsafe { std::mem::transmute::, RegionKind<'static>>(kind) }; Self { interned: Interned::new_gc(RegionInterned(kind)) } } + pub fn new(_interner: DbInterner<'db>, kind: RegionKind<'db>) -> Self { + Self::new_without_interner(kind) + } + pub fn inner(&self) -> &RegionKind<'db> { let inner = &self.interned.0; unsafe { std::mem::transmute::<&RegionKind<'static>, &RegionKind<'db>>(inner) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs index 6faf0357e3583..c1810bc659c01 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs @@ -70,8 +70,10 @@ const _: () = { }; impl<'db> Ty<'db> { + /// You should avoid using this if you can, since we want `Const` to be defined in `rustc_type_ir` and then this method + /// will become more difficult to use. #[inline] - pub fn new(_interner: DbInterner<'db>, kind: TyKind<'db>) -> Self { + pub fn new_without_interner(kind: TyKind<'db>) -> Self { let kind = unsafe { std::mem::transmute::, TyKind<'static>>(kind) }; let flags = FlagComputation::for_kind(&kind); let cached = WithCachedTypeInfo { @@ -82,6 +84,11 @@ impl<'db> Ty<'db> { Self { interned: Interned::new_gc(TyInterned(cached)) } } + #[inline] + pub fn new(_interner: DbInterner<'db>, kind: TyKind<'db>) -> Self { + Self::new_without_interner(kind) + } + #[inline] pub fn inner(&self) -> &WithCachedTypeInfo> { let inner = &self.interned.0; @@ -784,7 +791,7 @@ impl<'db> Ty<'db> { let impl_bound = TraitRef::new_from_args( interner, future_trait.into(), - GenericArgs::empty(interner), + GenericArgs::empty(), ) .upcast(interner); Some(vec![impl_bound]) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs index a6e864916f40f..b10f2df273b44 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs @@ -938,36 +938,6 @@ fn foo(tuple: Tuple) { ); } -#[test] -fn const_block_pattern() { - check_infer( - r#" -struct Foo(usize); -fn foo(foo: Foo) { - match foo { - const { Foo(15 + 32) } => {}, - _ => {} - } -}"#, - expect![[r#" - 26..29 'foo': Foo - 36..115 '{ ... } }': () - 42..113 'match ... }': () - 48..51 'foo': Foo - 62..84 'const ... 32) }': Foo - 68..84 '{ Foo(... 32) }': Foo - 70..73 'Foo': fn Foo(usize) -> Foo - 70..82 'Foo(15 + 32)': Foo - 74..76 '15': usize - 74..81 '15 + 32': usize - 79..81 '32': usize - 88..90 '{}': () - 100..101 '_': Foo - 105..107 '{}': () - "#]], - ); -} - #[test] fn macro_pat() { check_types( diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs index 7934ffec28745..a6c8b4ac6a271 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs @@ -3135,22 +3135,6 @@ fn f() -> impl Sized { ); } -#[test] -fn regression_22836() { - check( - r#" -fn main() { - match () { - const { - async | v | () - // ^^^^^^^^^^^^^^ expected (), got impl AsyncFn({unknown}) - } - } -} - "#, - ); -} - #[test] fn regression_22986() { check_no_mismatches( diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs index f3aa024399e06..61f0e17cc9984 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs @@ -391,6 +391,6 @@ pub fn check_orphan_rules<'db>(db: &'db dyn HirDatabase, impl_: ImplId) -> bool } _ => false, }); - #[allow(clippy::let_and_return)] + #[allow(clippy::let_and_return, reason = "the name clarifies the meaning of the boolean")] is_not_orphan } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs index 2690297283988..cce1b4caf44a7 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs @@ -46,7 +46,7 @@ fn variances_of_query(db: &dyn HirDatabase, def: GenericDefId) -> StoredVariance GenericDefId::AdtId(adt) => { if let AdtId::StructId(id) = adt { let flags = &StructSignature::of(db, id).flags; - let types = || crate::next_solver::default_types(db); + let types = || crate::next_solver::default_types(); if flags.contains(StructFlags::IS_UNSAFE_CELL) { return types().one_invariant.store(); } else if flags.intersects( @@ -56,13 +56,13 @@ fn variances_of_query(db: &dyn HirDatabase, def: GenericDefId) -> StoredVariance } } } - _ => return VariancesOf::empty(DbInterner::new_no_crate(db)).store(), + _ => return VariancesOf::empty().store(), } let generics = generics(db, def); let count = generics.len(true); if count == 0 { - return VariancesOf::empty(DbInterner::new_no_crate(db)).store(); + return VariancesOf::empty().store(); } let variances = Context { generics, variances: vec![Variance::Bivariant; count].into_boxed_slice(), db } diff --git a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs index 5c3b628f386d5..a1ff564edcf56 100644 --- a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs @@ -1175,7 +1175,11 @@ impl<'a, 'db> DiagnosticsCollector<'a, 'db> { } fn collect_anon_const(&mut self, source_map: &ExpressionStoreSourceMap, def: AnonConstId<'db>) { - self.emit_inference_errors(def.into(), source_map, def.into()); + self.emit_inference_errors( + def.into(), + source_map, + TypeOwnerId::from_anon_const(def, self.db), + ); } fn collect_enum(&mut self, def: EnumId) { @@ -1232,7 +1236,7 @@ impl<'a, 'db> DiagnosticsCollector<'a, 'db> { } } - fn collect_def_with_body(&mut self, def: DefWithBodyId, type_owner: TypeOwnerId<'db>) { + fn collect_def_with_body(&mut self, def: DefWithBodyId, type_owner: TypeOwnerId) { let (body, source_map) = Body::with_source_map(self.db, def); self.collect_expr_store(body, source_map); @@ -1284,7 +1288,7 @@ impl<'a, 'db> DiagnosticsCollector<'a, 'db> { &mut self, def: InferBodyId<'db>, source_map: &ExpressionStoreSourceMap, - type_owner: TypeOwnerId<'db>, + type_owner: TypeOwnerId, ) { let infer = InferenceResult::of(self.db, def); @@ -1548,7 +1552,7 @@ impl<'db> AnyDiagnostic<'db> { edition: Edition, d: &'db InferenceDiagnostic, source_map: &ExpressionStoreSourceMap, - type_owner: TypeOwnerId<'db>, + type_owner: TypeOwnerId, ) -> Option> { let expr_syntax = |expr| Self::expr_syntax(expr, source_map); let pat_syntax = |pat| Self::pat_syntax(pat, source_map); @@ -1918,7 +1922,7 @@ impl<'db> AnyDiagnostic<'db> { db: &'db dyn HirDatabase, d: &'db SolverDiagnosticKind, span: SpanSyntax, - type_owner: TypeOwnerId<'db>, + type_owner: TypeOwnerId, ) -> Option> { let interner = DbInterner::new_no_crate(db); Some(match d { diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 34b9ede4985a6..f9073138e32dd 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -1299,16 +1299,15 @@ impl<'db> AnonConst<'db> { pub fn ty(self, db: &'db dyn HirDatabase) -> Type<'db> { let loc = self.id.loc(db); - Type { owner: self.id.into(), ty: loc.ty.get() } + Type { owner: TypeOwnerId::from_anon_const(self.id, db), ty: loc.ty.get() } } pub fn eval( self, db: &'db dyn HirDatabase, ) -> Result, ConstEvalError<'db>> { - let interner = DbInterner::new_no_crate(db); let ty = self.id.loc(db).ty.get().instantiate_identity().skip_norm_wip(); - db.anon_const_eval(self.id, GenericArgs::empty(interner), None).map(|it| EvaluatedConst { + db.anon_const_eval(self.id, GenericArgs::empty(), None).map(|it| EvaluatedConst { allocation: it, def: self.id.into(), ty, @@ -1550,7 +1549,7 @@ impl Function { } } - fn fn_sig<'db>(self, db: &'db dyn HirDatabase) -> (TypeOwnerId<'db>, PolyFnSig<'db>) { + fn fn_sig<'db>(self, db: &'db dyn HirDatabase) -> (TypeOwnerId, PolyFnSig<'db>) { let fn_ptr = self.fn_ptr_type(db); let TyKind::FnPtr(sig_tys, hdr) = fn_ptr.ty.skip_binder().kind() else { unreachable!(); @@ -1558,7 +1557,7 @@ impl Function { (fn_ptr.owner, sig_tys.with(hdr)) } - fn erased_fn_sig<'db>(self, db: &'db dyn HirDatabase) -> (TypeOwnerId<'db>, FnSig<'db>) { + fn erased_fn_sig<'db>(self, db: &'db dyn HirDatabase) -> (TypeOwnerId, FnSig<'db>) { let (owner, sig) = self.fn_sig(db); let sig = DbInterner::new_no_crate(db).instantiate_bound_regions_with_erased(sig); (owner, sig) @@ -1827,10 +1826,9 @@ impl Function { "evaluation of builtin derive impl methods is not supported".to_owned(), ))); }; - let interner = DbInterner::new_no_crate(db); let body = db.monomorphized_mir_body( id.into(), - GenericArgs::empty(interner).store(), + GenericArgs::empty().store(), ParamEnvAndCrate { param_env: db.trait_environment(id.into()), krate: id.module(db).krate(db), @@ -2109,9 +2107,8 @@ impl Const { /// Evaluate the constant. pub fn eval(self, db: &dyn HirDatabase) -> Result, ConstEvalError<'_>> { - let interner = DbInterner::new_no_crate(db); let ty = db.value_ty(self.id.into()).unwrap().instantiate_identity().skip_norm_wip(); - db.const_eval(self.id, GenericArgs::empty(interner), None).map(|it| EvaluatedConst { + db.const_eval(self.id, GenericArgs::empty(), None).map(|it| EvaluatedConst { allocation: it, def: self.id.into(), ty, @@ -3124,21 +3121,17 @@ impl GenericDef { // We cannot call this `Substitution` unfortunately... #[derive(Debug)] pub struct GenericSubstitution<'db> { - owner: TypeOwnerId<'db>, + owner: TypeOwnerId, def: GenericDefId, subst: GenericArgs<'db>, } impl<'db> GenericSubstitution<'db> { - fn new(def: GenericDefId, subst: GenericArgs<'db>, owner: TypeOwnerId<'db>) -> Self { + fn new(def: GenericDefId, subst: GenericArgs<'db>, owner: TypeOwnerId) -> Self { Self { owner, def, subst } } - fn new_from_fn( - def: Function, - subst: GenericArgs<'db>, - owner: TypeOwnerId<'db>, - ) -> Option { + fn new_from_fn(def: Function, subst: GenericArgs<'db>, owner: TypeOwnerId) -> Option { match def.id { AnyFunctionId::FunctionId(def) => Some(Self::new(def.into(), subst, owner)), AnyFunctionId::BuiltinDeriveImplMethod { .. } => None, @@ -3965,7 +3958,7 @@ impl Impl { #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub struct TraitRef<'db> { - owner: TypeOwnerId<'db>, + owner: TypeOwnerId, trait_ref: hir_ty::next_solver::TraitRef<'db>, } @@ -4003,7 +3996,7 @@ enum AnyClosureId<'db> { #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct Closure<'db> { - owner: TypeOwnerId<'db>, + owner: TypeOwnerId, id: AnyClosureId<'db>, subst: GenericArgs<'db>, } @@ -4347,23 +4340,26 @@ impl CaptureUsageSource { } #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] -enum TypeOwnerId<'db> { +enum TypeOwnerId { GenericDefId(GenericDefId), BuiltinDeriveImplId(BuiltinDeriveImplId), - AnonConstId(AnonConstId<'db>), // FIXME: What do when we unify two different crates? Currently we just randomly keep one. NoParams(base_db::Crate), } impl_from!( - impl<'db> GenericDefId, - BuiltinDeriveImplId, - AnonConstId<'db> - for TypeOwnerId<'db> + BuiltinDeriveImplId + for TypeOwnerId ); -impl TypeOwnerId<'_> { +impl TypeOwnerId { + /// We associated anon consts with their parent, because they can never have generics of their own. + /// It can have *less* than the parent, but providing more generic args is not a problem. + fn from_anon_const<'db>(id: AnonConstId<'db>, db: &'db dyn HirDatabase) -> TypeOwnerId { + TypeOwnerId::GenericDefId(id.loc(db).owner.generic_def(db)) + } + fn unify(self, other: Self) -> Option { match (self, other) { (TypeOwnerId::NoParams(_), owner) => Some(owner), @@ -4394,7 +4390,7 @@ impl TypeOwnerId<'_> { } let self_def = match self { TypeOwnerId::GenericDefId(def) => def, - TypeOwnerId::BuiltinDeriveImplId(_) | TypeOwnerId::AnonConstId(_) => return false, + TypeOwnerId::BuiltinDeriveImplId(_) => return false, TypeOwnerId::NoParams(_) => return true, }; let self_def = match self_def { @@ -4408,9 +4404,7 @@ impl TypeOwnerId<'_> { }; let rebase_into_def = match rebase_into { TypeOwnerId::GenericDefId(def) => def, - TypeOwnerId::BuiltinDeriveImplId(_) - | TypeOwnerId::AnonConstId(_) - | TypeOwnerId::NoParams(_) => return false, + TypeOwnerId::BuiltinDeriveImplId(_) | TypeOwnerId::NoParams(_) => return false, }; let rebase_into_parent = match rebase_into_def { GenericDefId::ConstId(def) => def.loc(db).container, @@ -4429,7 +4423,7 @@ impl TypeOwnerId<'_> { /// with types of different origins will cause errors or panics. Instead, use the `instantiate` methods. #[derive(Clone, Debug)] pub struct Type<'db> { - owner: TypeOwnerId<'db>, + owner: TypeOwnerId, ty: EarlyBinder<'db, Ty<'db>>, } @@ -4513,8 +4507,7 @@ impl<'db> Type<'db> { TypeOwnerId::BuiltinDeriveImplId(def) => { GenericArgs::error_for_item(interner, def.into()) } - TypeOwnerId::AnonConstId(def) => GenericArgs::error_for_item(interner, def.into()), - TypeOwnerId::NoParams(_) => GenericArgs::empty(interner), + TypeOwnerId::NoParams(_) => GenericArgs::empty(), }; Type::no_params(krate, self.ty.instantiate(interner, args).skip_norm_wip()) } @@ -4527,10 +4520,7 @@ impl<'db> Type<'db> { TypeOwnerId::BuiltinDeriveImplId(def) => { generic_args_from_tys(interner, def.into(), args) } - TypeOwnerId::AnonConstId(def) => generic_args_from_tys(interner, def.into(), args), - TypeOwnerId::NoParams(krate) => { - (GenericArgs::empty(interner), TypeOwnerId::NoParams(krate)) - } + TypeOwnerId::NoParams(krate) => (GenericArgs::empty(), TypeOwnerId::NoParams(krate)), }; Type { owner, ty: EarlyBinder::bind(self.ty.instantiate(interner, args).skip_norm_wip()) } } @@ -4546,7 +4536,6 @@ impl<'db> Type<'db> { let owner = match ty.owner { TypeOwnerId::GenericDefId(def) => def.into(), TypeOwnerId::BuiltinDeriveImplId(def) => def.into(), - TypeOwnerId::AnonConstId(def) => def.into(), TypeOwnerId::NoParams(_) => return ty.ty.skip_binder(), }; let args = GenericArgs::for_item(infcx.interner, owner, |_, param, _, _| { @@ -4624,7 +4613,7 @@ impl<'db> Type<'db> { tys: impl IntoIterator>>, ) -> Self { let interner = DbInterner::new_no_crate(db); - let mut owner = None::>; + let mut owner = None::; let ty = EarlyBinder::bind(Ty::new_tup_from_iter( interner, tys.into_iter().map(|ty| { @@ -4840,29 +4829,21 @@ impl<'db> Type<'db> { TypeOwnerId::BuiltinDeriveImplId(def) => { hir_def::HasModule::krate(&def.loc(db).adt, db) } - TypeOwnerId::AnonConstId(def) => hir_def::HasModule::krate(&def, db), TypeOwnerId::NoParams(krate) => krate, } } fn param_env(&self, db: &'db dyn HirDatabase) -> ParamEnvAndCrate<'db> { - let interner = DbInterner::new_no_crate(db); let krate = self.krate(db); match self.owner { TypeOwnerId::GenericDefId(def) => { ParamEnvAndCrate { param_env: db.trait_environment(def), krate } } TypeOwnerId::BuiltinDeriveImplId(def) => ParamEnvAndCrate { - param_env: hir_ty::builtin_derive::param_env(interner, def), - krate, - }, - TypeOwnerId::AnonConstId(def) => ParamEnvAndCrate { - param_env: db.trait_environment(def.loc(db).owner.generic_def(db)), + param_env: hir_ty::builtin_derive::param_env(DbInterner::new_with(db, krate), def), krate, }, - TypeOwnerId::NoParams(_) => { - ParamEnvAndCrate { param_env: ParamEnv::empty(interner), krate } - } + TypeOwnerId::NoParams(_) => ParamEnvAndCrate { param_env: ParamEnv::empty(), krate }, } } @@ -4986,8 +4967,7 @@ impl<'db> Type<'db> { trait_: Trait, args: &[Type<'db>], ) -> bool { - let interner = DbInterner::new_no_crate(db); - let env = ParamEnvAndCrate { param_env: ParamEnv::empty(interner), krate: self.krate(db) }; + let env = ParamEnvAndCrate { param_env: ParamEnv::empty(), krate: self.krate(db) }; traits::implements_trait_unique_with_infcx(db, env, trait_.id, &mut |infcx| { let mut args = Self::instantiate_many_with_infer(iter::once(self).chain(args), infcx); GenericArgs::for_item(infcx.interner, trait_.id.into(), |_, param, _, _| { @@ -5681,7 +5661,7 @@ impl<'db> Type<'db> { pub fn walk(&self, db: &'db dyn HirDatabase, callback: impl FnMut(Type<'db>)) { struct Visitor<'db, F> { db: &'db dyn HirDatabase, - owner: TypeOwnerId<'db>, + owner: TypeOwnerId, callback: F, visited: FxHashSet>, } @@ -6144,7 +6124,7 @@ pub enum PredicatePolarity { #[derive(Debug, Clone, PartialEq, Eq)] pub struct TraitPredicate<'db> { inner: hir_ty::next_solver::TraitPredicate<'db>, - owner: TypeOwnerId<'db>, + owner: TypeOwnerId, } impl<'db> TraitPredicate<'db> { @@ -6549,8 +6529,8 @@ fn generic_args_from_tys<'db>( interner: DbInterner<'db>, def_id: SolverDefId<'db>, args: impl IntoIterator>>, -) -> (GenericArgs<'db>, TypeOwnerId<'db>) { - let mut owner = None::>; +) -> (GenericArgs<'db>, TypeOwnerId) { + let mut owner = None::; let mut args = args.into_iter(); let args = GenericArgs::for_item(interner, def_id, |_, id, _, _| { if matches!(id, GenericParamId::TypeParamId(_)) diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index 907193fe1d7ff..368e5e3c147fd 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -78,7 +78,7 @@ pub(crate) struct SourceAnalyzer<'db> { pub(crate) file_id: HirFileId, pub(crate) resolver: Resolver<'db>, pub(crate) body_or_sig: Option>, - pub(crate) type_owner: TypeOwnerId<'db>, + pub(crate) type_owner: TypeOwnerId, pub(crate) infer_body: Option>, } @@ -350,21 +350,18 @@ impl<'db> SourceAnalyzer<'db> { } fn trait_environment(&self, db: &'db dyn HirDatabase) -> ParamEnvAndCrate<'db> { - self.param_and(self.body_or_sig.as_ref().map_or_else( - || ParamEnv::empty(DbInterner::new_no_crate(db)), - |body_or_sig| { - let def = match *body_or_sig { - BodyOrSig::Body { def, .. } => def.generic_def(db), - BodyOrSig::VariantFields { def, .. } => match def { - VariantId::EnumVariantId(def) => def.loc(db).parent.into(), - VariantId::StructId(def) => def.into(), - VariantId::UnionId(def) => def.into(), - }, - BodyOrSig::Sig { def, .. } => def, - }; - db.trait_environment(def) - }, - )) + self.param_and(self.body_or_sig.as_ref().map_or_else(ParamEnv::empty, |body_or_sig| { + let def = match *body_or_sig { + BodyOrSig::Body { def, .. } => def.generic_def(db), + BodyOrSig::VariantFields { def, .. } => match def { + VariantId::EnumVariantId(def) => def.loc(db).parent.into(), + VariantId::StructId(def) => def.into(), + VariantId::UnionId(def) => def.into(), + }, + BodyOrSig::Sig { def, .. } => def, + }; + db.trait_environment(def) + })) } pub(crate) fn evaluate_where_clause( diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs index 9f9bb1d131548..67fa68df1e9df 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs @@ -140,6 +140,7 @@ fn add_missing_impl_members_inner( let missing_items = filter_assoc_items( &ctx.sema, + trait_, &ide_db::traits::get_missing_assoc_items(&ctx.sema, &impl_def), mode, ign_item, @@ -161,6 +162,7 @@ fn add_missing_impl_members_inner( trait_, &impl_def, &target_scope, + mode, ); let Some((first_new_item, other_items)) = new_item.split_first() else { @@ -2747,7 +2749,9 @@ pub trait Read { } impl Read for () { - $0fn read_buf() {} + fn read_buf() { + ${0:todo!()} + } } "#, ); @@ -2887,7 +2891,9 @@ pub trait Read { } impl Read for () { - $0fn read() {} + fn read() { + ${0:todo!()} + } } "#, ); @@ -2918,7 +2924,198 @@ pub trait Read { } impl Read for () { - $0fn read_buf() {} + fn read_buf() { + ${0:todo!()} + } +} + "#, + ); + } + + #[test] + fn required_method_with_body() { + check_assist( + add_missing_impl_members, + r#" +//- minicore: drop, pin +struct Foo; + +impl Drop for Foo { + $0 +} + "#, + r#" +struct Foo; + +impl Drop for Foo { + fn drop(&mut self) { + ${0:todo!()} + } +} + "#, + ); + + check_assist( + add_missing_impl_members, + r#" +#[rustc_must_implement_one_of(read_buf, read)] +pub trait Read { + fn read() { + Self::read_buf() + } + fn read_buf() { + Self::read(); + } +} + +impl Read for () { + $0 +} + "#, + r#" +#[rustc_must_implement_one_of(read_buf, read)] +pub trait Read { + fn read() { + Self::read_buf() + } + fn read_buf() { + Self::read(); + } +} + +impl Read for () { + fn read_buf() { + ${0:todo!()} + } +} + "#, + ); + check_assist( + add_missing_default_members, + r#" +#[rustc_must_implement_one_of(read_buf, read)] +pub trait Read { + fn read() { + Self::read_buf() + } + fn read_buf() { + Self::read(); + } +} + +impl Read for () { + $0 +} + "#, + r#" +#[rustc_must_implement_one_of(read_buf, read)] +pub trait Read { + fn read() { + Self::read_buf() + } + fn read_buf() { + Self::read(); + } +} + +impl Read for () { + $0fn read() { + Self::read_buf() + } +} + "#, + ); + } + + #[test] + fn unstable_item() { + check_assist( + add_missing_impl_members, + r#" +trait Foo { + #[unstable(feature = "foobar")] + fn foobar(); +} + +impl Foo for () { + $0 +} + "#, + r#" +trait Foo { + #[unstable(feature = "foobar")] + fn foobar(); +} + +impl Foo for () { + fn foobar() { + ${0:todo!()} + } +} + "#, + ); + check_assist_not_applicable( + add_missing_default_members, + r#" +trait Foo { + #[unstable(feature = "foobar")] + fn foobar() {} +} + +impl Foo for () { + $0 +} + "#, + ); + check_assist( + add_missing_default_members, + r#" +#![feature(foobar)] + +trait Foo { + #[unstable(feature = "foobar")] + fn foobar() {} +} + +impl Foo for () { + $0 +} + "#, + r#" +#![feature(foobar)] + +trait Foo { + #[unstable(feature = "foobar")] + fn foobar() {} +} + +impl Foo for () { + $0fn foobar() {} +} + "#, + ); + check_assist( + add_missing_default_members, + r#" +#[unstable(feature = "foobar")] +trait Foo { + #[unstable(feature = "foobar")] + fn foobar() {} +} + +impl Foo for () { + $0 +} + "#, + r#" +#[unstable(feature = "foobar")] +trait Foo { + #[unstable(feature = "foobar")] + fn foobar() {} +} + +impl Foo for () { + $0fn foobar() {} } "#, ); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_impl.rs index d88a94e2f7307..9fa9a0461eaa2 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_impl.rs @@ -167,6 +167,7 @@ pub(crate) fn generate_impl_trait(acc: &mut Assists, ctx: &AssistContext<'_, '_> let holder_arg = ast::GenericArg::TypeArg(make.type_arg(make.ty_placeholder())); let missing_items = utils::filter_assoc_items( &ctx.sema, + hir_trait, &ide_db::traits::trait_items_with_required(ctx.db(), hir_trait), DefaultMethods::No, IgnoreAssocItems::DocHiddenAttrPresent, @@ -205,6 +206,7 @@ pub(crate) fn generate_impl_trait(acc: &mut Assists, ctx: &AssistContext<'_, '_> hir_trait, &impl_, &target_scope, + DefaultMethods::No, ); let assoc_item_list = make.assoc_item_list(assoc_items); make_impl_(Some(assoc_item_list)) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs index 8648a013438e7..3e98aadb695c3 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs @@ -233,6 +233,7 @@ fn impl_def_from_trait( let trait_items = filter_assoc_items( sema, + trait_, &ide_db::traits::trait_items_with_required(sema.db, trait_), DefaultMethods::No, ignore_items, @@ -252,6 +253,7 @@ fn impl_def_from_trait( trait_, &impl_def, &target_scope, + DefaultMethods::No, ); let assoc_item_list = if let Some((first, other)) = assoc_items.split_first() { let first_item = if let ast::AssocItem::Fn(func) = first diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs index e5e735faf6f93..8acb887133e0f 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs @@ -4,7 +4,7 @@ use std::slice; pub(crate) use gen_trait_fn_body::gen_trait_fn_body; use hir::{ - HasAttrs as HirHasAttrs, HirDisplay, InFile, ModuleDef, PathResolution, Semantics, + HasAttrs as HirHasAttrs, HasCrate, HirDisplay, InFile, ModuleDef, PathResolution, Semantics, db::HirDatabase, }; use ide_db::{ @@ -158,11 +158,12 @@ pub enum DefaultMethods { pub fn filter_assoc_items( sema: &Semantics<'_, RootDatabase>, + trait_: hir::Trait, items: &[(hir::AssocItem, IsRequiredAssocItem)], default_methods: DefaultMethods, ignore_items: IgnoreAssocItems, ) -> Vec> { - items + let mut result = items .iter() .copied() .filter(|(assoc_item, is_required)| { @@ -179,16 +180,33 @@ pub fn filter_assoc_items( is_required.0 == (default_methods == DefaultMethods::No) }) + .map(|(item, _)| (item, item.attrs(sema.db).unstable_feature(sema.db))) // Note: This throws away items with no source. - .filter_map(|(assoc_item, _)| { + .filter_map(|(assoc_item, unstable_feature)| { let item = match assoc_item { hir::AssocItem::Function(it) => sema.source(it)?.map(ast::AssocItem::Fn), hir::AssocItem::TypeAlias(it) => sema.source(it)?.map(ast::AssocItem::TypeAlias), hir::AssocItem::Const(it) => sema.source(it)?.map(ast::AssocItem::Const), }; - Some(item) + Some((item, unstable_feature)) }) - .collect() + .collect::>(); + + // Now, we want to filter unstable assoc items whose feature is not enabled, unless: + // - it's required, or + // - the trait has the same feature, so the user probably intends to enable it. + if default_methods == DefaultMethods::Only { + let trait_unstable_feature = trait_.attrs(sema.db).unstable_feature(sema.db); + let krate = trait_.krate(sema.db); + result.retain(|(_, item_unstable_feature)| { + *item_unstable_feature == trait_unstable_feature + || item_unstable_feature + .as_ref() + .is_none_or(|feature| krate.is_unstable_feature_enabled(sema.db, feature)) + }); + } + + result.into_iter().map(|(item, _)| item).collect() } /// Given `original_items` retrieved from the trait definition (usually by @@ -204,6 +222,7 @@ pub fn add_trait_assoc_items_to_impl( trait_: hir::Trait, impl_: &ast::Impl, target_scope: &hir::SemanticsScope<'_>, + default_mode: DefaultMethods, ) -> Vec { let new_indent_level = IndentLevel::from_node(impl_.syntax()) + 1; original_items @@ -240,7 +259,10 @@ pub fn add_trait_assoc_items_to_impl( ast::AssocItem::cast(editor.finish().new_root().clone()).unwrap() }) .filter_map(|item| match item { - ast::AssocItem::Fn(fn_) if fn_.body().is_none() => { + // We can check `fn_.body().is_none()`, but this is actually not what we want to check: some functions (`Drop::drop()` + // or `#[rustc_must_implement_one_of]`) have a default body that should be ignored. So the criteria is whether + // we requested required or defaulted methods, and not whether the method actually has a body. + ast::AssocItem::Fn(fn_) if default_mode == DefaultMethods::No => { let (fn_editor, fn_) = SyntaxEditor::with_ast_node(&fn_); let fill_expr: ast::Expr = match config.expr_fill_default { ExprFillDefaultMode::Todo | ExprFillDefaultMode::Default => make.expr_todo(), diff --git a/src/tools/rust-analyzer/crates/ide-db/src/ra_fixture.rs b/src/tools/rust-analyzer/crates/ide-db/src/ra_fixture.rs index 09a270c143888..ee61cab4828c5 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/ra_fixture.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/ra_fixture.rs @@ -307,7 +307,7 @@ impl IsEmpty for SmallVec<[T; N]> { } } -#[allow(clippy::disallowed_types)] +#[expect(clippy::disallowed_types, reason = "generic allows for `FxHashMap`")] impl IsEmpty for std::collections::HashMap { fn is_empty(&self) -> bool { self.is_empty() @@ -376,7 +376,7 @@ impl UpmapFromRaFixture for SmallVec<[T; } } -#[allow(clippy::disallowed_types)] +#[expect(clippy::disallowed_types, reason = "generic allows for `FxHashMap`")] impl UpmapFromRaFixture for std::collections::HashMap { @@ -391,7 +391,7 @@ impl UpmapFromRaFixture for std::collections::HashMap { diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs index a72da8e7722a5..e13693df99560 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs @@ -247,6 +247,16 @@ struct SCREAMING_CASE {} ); } + #[test] + fn incorrect_raw_struct_name() { + check_diagnostics( + r#" +struct r#pub {} + // ^^^^^ 💡 warn: Structure `r#pub` should have UpperCamelCase name, e.g. `Pub` +"#, + ); + } + #[test] fn no_diagnostic_for_camel_cased_acronyms_in_struct_name() { check_diagnostics( @@ -340,6 +350,16 @@ enum SomeEnum { SOME_VARIANT(u8) } ); } + #[test] + fn incorrect_raw_enum_variant_name() { + check_diagnostics( + r#" +enum SomeEnum { r#pub } + // ^^^^^ 💡 warn: Variant `r#pub` should have UpperCamelCase name, e.g. `Pub` +"#, + ); + } + #[test] fn incorrect_const_name() { check_diagnostics( diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs index 24f1e3ad836a0..52532172ccda0 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs @@ -23,9 +23,21 @@ struct State { has_serialize: bool, has_deserialize: bool, names: FxHashMap, + edition: Option, } impl State { + fn make_name(&self, name: &str) -> ast::Name { + let edition = self.edition.unwrap(); + if syntax::utils::is_identifier(name, edition) + || syntax::utils::is_raw_identifier(name, edition) + { + make::name(name) + } else { + make::name("INVALID") + } + } + fn generate_new_name(&mut self, name: &str) -> ast::Name { let name = stdx::to_camel_case(name); let count = if let Some(count) = self.names.get_mut(&name) { @@ -35,7 +47,7 @@ impl State { self.names.insert(name.clone(), 1); 1 }; - make::name(&format!("{name}{count}")) + self.make_name(&format!("{name}{count}")) } fn serde_derive(&self) -> String { @@ -70,7 +82,7 @@ impl State { None, make::record_field_list(value.iter().sorted_unstable_by_key(|x| x.0).map( |(name, value)| { - make::record_field(None, make::name(name), self.type_of(name, value)) + make::record_field(None, self.make_name(name), self.type_of(name, value)) }, )) .into(), @@ -125,6 +137,7 @@ pub(crate) fn json_in_items( let serialize_resolved = scope_resolve("::serde::Serialize"); state.has_deserialize = deserialize_resolved.is_some(); state.has_serialize = serialize_resolved.is_some(); + state.edition = Some(edition); state.build_struct("Root", &it); edit.insert(range.start(), state.result); let vfs_file_id = file_id.file_id(sema.db); @@ -342,6 +355,36 @@ mod tests { ); } + #[test] + fn invalid_fields() { + check_fix( + r#" + //- /lib.rs crate:lib deps:serde + {$0 + "$": "", + "self": "", + "valided": "" + } + //- /serde.rs crate:serde + + pub trait Serialize { + fn serialize() -> u8; + } + pub trait Deserialize { + fn deserialize() -> u8; + } + "#, + r#" + use serde::Serialize; + use serde::Deserialize; + + #[derive(Serialize, Deserialize)] + struct Root1 { INVALID: String, INVALID: String, valided: String } + + "#, + ); + } + #[test] fn no_emit_outside_of_item_position() { check_no_fix( diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs index f70795ed29bde..1e92a795e47a9 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs @@ -2019,4 +2019,25 @@ fn test(_: Result) { "#, ); } + + #[test] + fn regression_23313() { + check_diagnostics( + r#" +fn hello_world() {} + +struct Wrapper ()>; + +impl ()> Wrapper<{ + Wrapper::<{hello_world}>::call(); + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: no such associated item + }> { +//^ 💡 error: expected fn(), found () + fn hello_world() { + F(); + } +} + "#, + ); + } } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs index e2d31503f1d08..e93e74177abe8 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs @@ -464,6 +464,20 @@ fn main() { m!(generic::); } } +"#, + ); + } + + #[test] + fn term_search_lookup_const() { + check_diagnostics( + r#" +struct S { f: i32 } +const C: i32 = 0; +fn main() { + let _: S = _; + //^ 💡 error: invalid `_` expression, expected type `S` +} "#, ); } diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs index ab5a0f70f5a69..c87a10d8e85b7 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs +++ b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs @@ -315,7 +315,6 @@ impl<'db, 'sema> Matcher<'db, 'sema> { Ok(()) } - #[allow(clippy::only_used_in_recursion)] fn check_constraint( &self, constraint: &Constraint, diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs index c152d7e9cc964..94e7db9390bc3 100644 --- a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs +++ b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs @@ -312,7 +312,10 @@ impl DocCommentToken { let DocCommentToken { prefix_len, doc_token } = self; // offset relative to the comments contents let original_start = doc_token.text_range().start(); - let relative_comment_offset = offset - original_start - prefix_len; + // If the cursor points inside the comment like `///` or to the first quote in `#[doc = "..."]` + // (i.e. relative_comment_offset is None) then we return w/o definition. + let relative_comment_offset = + offset.checked_sub(original_start)?.checked_sub(prefix_len)?; sema.descend_into_macros(doc_token).into_iter().find_map(|t| { let (node, descended_prefix_len, is_inner) = match_ast!{ diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs index 033de7dcc20b4..bb317525dd5d8 100644 --- a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs +++ b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs @@ -723,6 +723,13 @@ mod tests { assert!(navs.is_empty(), "didn't expect this to resolve anywhere: {navs:?}") } + #[track_caller] + fn check_no_definition(#[rust_analyzer::rust_fixture] ra_fixture: &str) { + let (analysis, position) = fixture::position(ra_fixture); + let navs = analysis.goto_definition(position, &TEST_CONFIG).unwrap(); + assert!(navs.is_none(), "didn't expect this to resolve anywhere: {navs:?}"); + } + fn check_name(expected_name: &str, #[rust_analyzer::rust_fixture] ra_fixture: &str) { let (analysis, position, _) = fixture::annotations(ra_fixture); let navs = analysis @@ -2132,6 +2139,30 @@ pub fn foo() { } ) } + #[test] + fn no_panic_on_offset_inside_doc_comment_prefix() { + // If the cursor (offset) points inside `///`/`//!`/the opening quote, i.e. before the docs' contents, + // this should not create navigation. + check_no_definition( + r#" +$0/// [`S`] +struct S; +"#, + ); + check_no_definition( + r#" +//$0! [`S`] +struct S; +"#, + ); + check_no_definition( + r#" +#[doc = $0"[`S`]"] +struct S; +"#, + ); + } + #[test] fn goto_def_for_intra_doc_link_outer_same_file() { check( diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs index 92473de4e634f..6f5878071aaa8 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs @@ -156,7 +156,6 @@ pub(crate) fn hover( Some(res) } -#[allow(clippy::field_reassign_with_default)] fn hover_offset( sema: &Semantics<'_, RootDatabase>, FilePosition { file_id, offset }: FilePosition, diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/bidirectional_protocol/msg.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/bidirectional_protocol/msg.rs index e516297f06196..22aac04c28e09 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/bidirectional_protocol/msg.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/bidirectional_protocol/msg.rs @@ -1,13 +1,11 @@ //! Bidirectional protocol messages -#![expect(clippy::disallowed_types)] - use std::{ - collections::{HashMap, HashSet}, io::{self, BufRead, Write}, ops::Range, }; use paths::Utf8PathBuf; +use rustc_hash::{FxHashMap, FxHashSet}; use serde::{Deserialize, Serialize}; use crate::{ @@ -122,7 +120,6 @@ pub struct SpanJoin { pub ctx: u32, } -#[expect(clippy::large_enum_variant)] #[derive(Debug, Serialize, Deserialize)] pub enum BidirectionalMessage { Request(Request), @@ -139,7 +136,6 @@ pub enum Request { SetConfig(ServerConfig), } -#[expect(clippy::large_enum_variant)] #[derive(Debug, Serialize, Deserialize)] pub enum Response { ListMacros(Result, String>), @@ -168,8 +164,8 @@ pub struct ExpandMacro { pub struct ExpandMacroResponse { pub tree: FlatTree, pub span_data_table: Vec, - pub tracked_env_vars: HashMap, Option>>, - pub tracked_paths: HashSet>, + pub tracked_env_vars: FxHashMap, Option>>, + pub tracked_paths: FxHashSet>, } #[derive(Debug, Serialize, Deserialize)] diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml index 05e0012586d5f..0427d0ee74a6e 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml @@ -14,6 +14,7 @@ doctest = false [dependencies] paths.workspace = true +rustc-hash.workspace = true # span = {workspace = true, default-features = false} does not work span = { path = "../span", version = "0.0.0", default-features = false} intern.workspace = true diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs index 7fc04a05155f8..e38d2ac11bce8 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs @@ -10,7 +10,7 @@ #![cfg(feature = "in-rust-tree")] #![feature(proc_macro_internals, proc_macro_diagnostic, proc_macro_span, rustc_private)] -#![expect(internal_features, clippy::disallowed_types, clippy::print_stderr)] +#![expect(internal_features)] #![allow(unused_features, unused_crate_dependencies)] #![deny(deprecated_safe, clippy::undocumented_unsafe_blocks)] #![cfg_attr(test, expect(unreachable_pub))] @@ -29,7 +29,7 @@ mod server_impl; mod token_stream; use std::{ - collections::{HashMap, HashSet, hash_map::Entry}, + collections::hash_map::Entry, env, ffi::OsString, fs, @@ -40,6 +40,7 @@ use std::{ }; use paths::{Utf8Path, Utf8PathBuf}; +use rustc_hash::{FxHashMap, FxHashSet}; use span::{FIXUP_ERASED_FILE_AST_ID_MARKER, Span}; pub use crate::server_impl::token_id::SpanId; @@ -61,7 +62,7 @@ pub enum ProcMacroKind { pub const RUSTC_VERSION_STRING: &str = env!("RUSTC_VERSION"); pub struct ProcMacroSrv<'env> { - expanders: Mutex>>, + expanders: Mutex>>, env: &'env EnvSnapshot, } @@ -226,8 +227,8 @@ impl ProcMacroSrv<'_> { #[derive(Default)] pub struct TrackedEnv { - pub env_vars: HashMap, Option>>, - pub paths: HashSet>, + pub env_vars: FxHashMap, Option>>, + pub paths: FxHashSet>, } pub trait ProcMacroSrvSpan: Copy + Send + Sync { @@ -289,7 +290,7 @@ impl PanicMessage { } pub struct EnvSnapshot { - vars: HashMap, + vars: FxHashMap, } impl Default for EnvSnapshot { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs index 6cbb0c718c3e6..8c8ad34f6c441 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -19,10 +19,7 @@ use hir_def::{ expr_store::{Body, BodySourceMap, ExpressionStore}, hir::{ExprId, PatId, generics::GenericParams}, }; -use hir_ty::{ - InferenceResult, - next_solver::{DbInterner, GenericArgs}, -}; +use hir_ty::{InferenceResult, next_solver::GenericArgs}; use ide::{ Analysis, AnalysisHost, AnnotationConfig, DiagnosticsConfig, Edition, InlayFieldsToResolve, InlayHintsConfig, LineCol, RaFixtureConfig, RootDatabase, @@ -411,7 +408,6 @@ impl flags::AnalysisStats { let mut all = 0; let mut fail = 0; for &a in adts { - let interner = DbInterner::new_no_crate(db); let generic_params = GenericParams::of(db, a.into()); if generic_params.iter_type_or_consts().next().is_some() || generic_params.iter_lt().next().is_some() @@ -422,7 +418,7 @@ impl flags::AnalysisStats { all += 1; let Err(e) = db.layout_of_adt( hir_def::AdtId::from(a), - GenericArgs::empty(interner).store(), + GenericArgs::empty().store(), hir_ty::ParamEnvAndCrate { param_env: db.trait_environment(a.into()), krate: a.krate(db).into(), diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/discover.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/discover.rs index 04d0cedb3eca2..f9491af71e7e1 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/discover.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/discover.rs @@ -68,7 +68,7 @@ impl DiscoverCommand { Ok(DiscoverHandle { handle: CommandHandle::spawn(cmd, DiscoverProjectParser, self.sender.clone(), None)?, - span: info_span!("discover_command").entered(), + _span: info_span!("discover_command").entered(), }) } } @@ -77,8 +77,8 @@ impl DiscoverCommand { #[derive(Debug)] pub(crate) struct DiscoverHandle { pub(crate) handle: CommandHandle, - #[allow(dead_code)] // not accessed, but used to log on drop. - span: EnteredSpan, + // not accessed, but used to log on drop. + _span: EnteredSpan, } /// An enum containing either progress messages, an error, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs index 85edb239e3f57..7f1f4ef137054 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs @@ -490,7 +490,7 @@ impl<'a> Substitutions<'a> { /// /// Same for {saved_file}. /// - #[allow(clippy::disallowed_types)] /* generic parameter allows for FxHashMap */ + #[expect(clippy::disallowed_types, reason = "generic parameter allows for `FxHashMap`")] fn substitute( self, template: &project_json::Runnable, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs index 8e0bb285c2318..19e067334e008 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs @@ -4,7 +4,12 @@ // might strip `false` values from the JSON payload due to their reserialization logic turning false // into null which will then cause them to be omitted in the resolve request. See https://github.com/rust-lang/rust-analyzer/issues/18767 -#![allow(clippy::disallowed_types)] +// FIXME: ideally we'd put this on `SnippetWorkspaceEdit.change_annotations`, but that doesn't work, +// most likely because the lint fires in the impls generated by the derives as well. +#![expect( + clippy::disallowed_types, + reason = "`SnippetWorkspaceEdit.change_annotations` needs to match `lsp_types::WorkspaceEdit.change_annotations` for the `From` impl" +)] use std::ops; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs index 56629f79ea216..4199cb29e66d2 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs @@ -8,7 +8,6 @@ //! specific JSON shapes here -- there's little value in such tests, as we can't //! be sure without a real client anyway. -#![allow(clippy::disallowed_types)] #![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] #[cfg(feature = "in-rust-tree")] diff --git a/src/tools/rust-analyzer/crates/stdx/src/rand.rs b/src/tools/rust-analyzer/crates/stdx/src/rand.rs index e028990900af6..07dfa6ef8877c 100644 --- a/src/tools/rust-analyzer/crates/stdx/src/rand.rs +++ b/src/tools/rust-analyzer/crates/stdx/src/rand.rs @@ -14,6 +14,6 @@ pub fn shuffle(slice: &mut [T], mut rand_index: impl FnMut(usize) -> usize) { pub fn seed() -> u64 { use std::hash::{BuildHasher, Hasher}; - #[allow(clippy::disallowed_types)] + #[expect(clippy::disallowed_types, reason = "we need a source of randomness for the seed")] std::collections::hash_map::RandomState::new().build_hasher().finish() } diff --git a/src/tools/rust-analyzer/crates/stdx/src/variance.rs b/src/tools/rust-analyzer/crates/stdx/src/variance.rs index 8465d72bf3719..0f87d1bd9bcc6 100644 --- a/src/tools/rust-analyzer/crates/stdx/src/variance.rs +++ b/src/tools/rust-analyzer/crates/stdx/src/variance.rs @@ -70,12 +70,11 @@ macro_rules! phantom_type { impl Eq for $name where T: ?Sized {} - #[allow(clippy::non_canonical_partial_ord_impl)] impl PartialOrd for $name where T: ?Sized { - fn partial_cmp(&self, _: &Self) -> Option { - Some(Ordering::Equal) + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) } } diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/expr_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/expr_ext.rs index ced9163f661af..2b1c91f20517d 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/expr_ext.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/expr_ext.rs @@ -335,7 +335,7 @@ impl ast::Literal { pub fn token(&self) -> SyntaxToken { self.syntax() .children_with_tokens() - .find(|e| e.kind() != ATTR && !e.kind().is_trivia()) + .find(|e| !ast::AnyAttr::can_cast(e.kind()) && !e.kind().is_trivia()) .and_then(|e| e.into_token()) .unwrap() } diff --git a/src/tools/rust-analyzer/crates/syntax/src/tests.rs b/src/tools/rust-analyzer/crates/syntax/src/tests.rs index e5beb44f42ec7..1002fdd902d29 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/tests.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/tests.rs @@ -126,6 +126,12 @@ fn self_hosting_parsing() { } } +#[test] +fn doc_comment_on_literal_expr() { + let parse = SourceFile::parse("fn f() { ///\n0..0; }", parser::Edition::CURRENT); + assert!(parse.errors().is_empty()); +} + fn test_data_dir() -> PathBuf { project_root().into_std_path_buf().join("crates/syntax/test_data") } diff --git a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs index 0d9bb4f92bdc0..129e63d3988b5 100644 --- a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs +++ b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs @@ -670,7 +670,11 @@ pub mod ops { // region:drop #[lang = "drop"] pub trait Drop { - fn drop(&mut self); + fn drop(&mut self) { + // region:pin + Drop::pin_drop(crate::pin::Pin::new(self)) + // endregion:pin + } // region:pin fn pin_drop(self: crate::pin::Pin<&mut Self>) {} diff --git a/src/tools/rust-analyzer/crates/toolchain/src/lib.rs b/src/tools/rust-analyzer/crates/toolchain/src/lib.rs index 6bed98f4cd2d7..26883add08699 100644 --- a/src/tools/rust-analyzer/crates/toolchain/src/lib.rs +++ b/src/tools/rust-analyzer/crates/toolchain/src/lib.rs @@ -74,7 +74,7 @@ impl Tool { // Prevent rustup from automatically installing toolchains, see https://github.com/rust-lang/rust-analyzer/issues/20719. pub const NO_RUSTUP_AUTO_INSTALL_ENV: (&str, &str) = ("RUSTUP_AUTO_INSTALL", "0"); -#[allow(clippy::disallowed_types)] /* generic parameter allows for FxHashMap */ +#[expect(clippy::disallowed_types, reason = "generic parameter allows for `FxHashMap`")] pub fn command( cmd: impl AsRef, working_directory: impl AsRef, diff --git a/src/tools/rust-analyzer/docs/book/src/contributing/lsp-extensions.md b/src/tools/rust-analyzer/docs/book/src/contributing/lsp-extensions.md index da4a5aaa686c5..42bdb5dc1055a 100644 --- a/src/tools/rust-analyzer/docs/book/src/contributing/lsp-extensions.md +++ b/src/tools/rust-analyzer/docs/book/src/contributing/lsp-extensions.md @@ -1,5 +1,5 @@ $DIR/unexpected-type-for-constructor.rs:7:35 + | +LL | const C_INNER: (*const u8, u8) = (None::, None::); + | ^^^^^^^^^^ expected `*const u8`, found `Option` + | + = note: expected raw pointer `*const u8` + found enum `Option` + +error[E0308]: mismatched types + --> $DIR/unexpected-type-for-constructor.rs:7:47 + | +LL | const C_INNER: (*const u8, u8) = (None::, None::); + | ^^^^^^^^^^ expected `u8`, found `Option` + | + = note: expected type `u8` + found enum `Option` + +error: could not evaluate constant pattern + --> $DIR/unexpected-type-for-constructor.rs:13:9 + | +LL | const C_INNER: (*const u8, u8) = (None::, None::); + | ------------------------------ constant defined here +... +LL | C_INNER => {} + | ^^^^^^^ could not evaluate constant + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/mgca/valtree-leaf-const.rs b/tests/ui/const-generics/mgca/valtree-leaf-const.rs new file mode 100644 index 0000000000000..e372e89fe5e50 --- /dev/null +++ b/tests/ui/const-generics/mgca/valtree-leaf-const.rs @@ -0,0 +1,12 @@ +//@ compile-flags: -Znext-solver + +#![feature(macroless_generic_const_args)] +#![feature(generic_const_args)] +#![feature(min_generic_const_args)] + +const TUPLE: (&'static str, &'static str) = ("a", true); +//~^ ERROR mismatched type + +fn main() { + TUPLE; +} diff --git a/tests/ui/const-generics/mgca/valtree-leaf-const.stderr b/tests/ui/const-generics/mgca/valtree-leaf-const.stderr new file mode 100644 index 0000000000000..db45a82198752 --- /dev/null +++ b/tests/ui/const-generics/mgca/valtree-leaf-const.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/valtree-leaf-const.rs:7:51 + | +LL | const TUPLE: (&'static str, &'static str) = ("a", true); + | ^^^^ expected `&str`, found `bool` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/generic-associated-types/trait-method-requires-gat-impl-trait.rs b/tests/ui/generic-associated-types/trait-method-requires-gat-impl-trait.rs new file mode 100644 index 0000000000000..3477f579cd0dd --- /dev/null +++ b/tests/ui/generic-associated-types/trait-method-requires-gat-impl-trait.rs @@ -0,0 +1,17 @@ +//! Regression test for . +//@compile-flags: -Znext-solver=globally +//@ check-pass + +trait Trait { + type Assoc; + fn foo() + where + Self::Assoc: Trait; +} + +impl Trait for T { + type Assoc = T; + fn foo() {} +} + +fn main() {}