[ERROR hir_ty::mir] Only tuple or closure has tuple or closure field
While working on r-a itself I tend to see this spammed, I haven't figured out which part of the codebase causes this though
I am currently working on a small demo project using Diesel and Axum. However, I am encountering some issues when trying to integrate Diesel. Specifically, rust-analyzer seems unable to resolve some Diesel names and lose track of the types.
In addition, I am also seeing the following error: "[ERROR hir_ty::mir] Only tuple has tuple field".
I have the same issue with quick_error
I see the same issue working with Diesel and Actix, maybe it has something to do with all of those macros from Diesel?
I can reproduce with the following
impl Bork {
fn f((x, y): T) {}
}
Note that Bork need not exist for the error to appear. It is specifically the pattern matching an unknown type within the signature that seems to cause the error.
Backtrace
Panic context:
> fetch_native_diagnostics
thread 'Worker' panicked at crates/hir-ty/src/mir.rs:185:21:
internal error: entered unreachable code: Only tuple has tuple field
stack backtrace:
0: rust_begin_unwind
at /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/std/src/panicking.rs:645:5
1: core::panicking::panic_fmt
at /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/core/src/panicking.rs:72:14
2: core::panicking::unreachable_display
3: hir_ty::mir::ProjectionElem<V,T>::projected_ty
4: hir_ty::mir::borrowck::moved_out_of_ref::{{closure}}
5: hir_ty::mir::borrowck::moved_out_of_ref
6: hir_ty::mir::borrowck::borrowck_query::{{closure}}
7: hir_ty::mir::borrowck::all_mir_bodies
8: hir_ty::mir::borrowck::borrowck_query
9: salsa::Cycle::catch
10: salsa::derived::slot::Slot<Q,MP>::execute
11: salsa::derived::slot::Slot<Q,MP>::read
12: <salsa::derived::DerivedStorage<Q,MP> as salsa::plumbing::QueryStorageOps<Q>>::fetch
13: <DB as hir_ty::db::HirDatabase>::borrowck::__shim
14: <DB as hir_ty::db::HirDatabase>::borrowck
15: hir::DefWithBody::diagnostics
16: hir::Module::diagnostics
17: ide_diagnostics::diagnostics
18: salsa::Cancelled::catch
19: ide::Analysis::with_db
20: ide::Analysis::diagnostics
21: core::ops::function::impls::<impl core::ops::function::FnMut<A> for &mut F>::call_mut
22: <alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter
23: rust_analyzer::diagnostics::fetch_native_diagnostics
24: core::ops::function::FnOnce::call_once{{vtable.shim}}
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Edit: In fact it can be reduced to just
fn f((x, y): T) {}
Investigated a little bit. Here is a way to make a similar error:
enum Foo {
Bar { x: i32 },
}
fn f(Foo::Bar { x }: T) {}
Error: internal error: entered unreachable code: Only adt has field, found {error}\n.
And this:
fn f(&x: T) {}
Error: internal error: entered unreachable code: Overloaded deref on type {unknown} is not a projection\n
In general, the error-handling in this block is off: https://github.com/rust-lang/rust-analyzer/blob/2b7b44bf27a7635eded9aa53678acb2c4e25063e/crates/hir-ty/src/mir.rs#L154-L227. It assumes type errors cannot happen, but evidently they can.
We might wanna set a flag for InferenceResult whether errors happened and then just error out in mir lowering if that is the case
Here is another test case that, unlike the others, is actually valid code:
struct Foo<T> {
l: T,
r: T,
}
trait Trait {
type State;
fn f(_: Self::State) -> Self;
}
impl<T> Trait for Foo<T> {
type State = (T, T);
fn f(state: Self::State) -> Self {
Self {
l: state.0,
r: state.1,
}
}
}
It has trouble detecting that Self::State is in fact a tuple.
It is specifically the pattern matching an unknown type within the signature that seems to cause the error.
Backtrace Edit: In fact it can be reduced to just
fn f((x, y): T) {}
Aww man, that's totally why this slams axum and diesel, lmao. Extractors and SQL rows. I have a lot of tuple destructuring in my data layer, so at least now I know why my inference has ground to a crawl.
I've been meaning to get up to speed on rust-analyzer internals and dip my toes into contributing. How crazy of a first issue would this be to jump into, do you think?
Hmm, fwiw this should only affect MIR building for the function so at worst you'll miss out on some diagnostics there.
The simple fix would be to skip mir building if we encounter any sort of type mismatches as said here https://github.com/rust-lang/rust-analyzer/issues/15090#issuecomment-1985638015 which shouldn't be too difficult. It's basically adding a bool field to InferenceResult, and check that in lower_to_mir and bail out if its set.
I have the same issue.
I edit
fn f(arg: (usize, bool)) {}
remove arg and add (index, fla
and rust-analyzer crash on
fn f((index,fla: (usize, bool)) {}
panic backtrace:
thread 'Worker' panicked at crates/hir-ty/src/mir.rs:185:21:
internal error: entered unreachable code: Only tuple has tuple field
stack backtrace:
0: _rust_begin_unwind
1: core::panicking::panic_fmt
2: core::panicking::unreachable_display
3: hir_ty::mir::ProjectionElem<V,T>::projected_ty
4: hir_ty::mir::borrowck::moved_out_of_ref::{{closure}}
5: hir_ty::mir::borrowck::moved_out_of_ref
6: hir_ty::mir::borrowck::borrowck_query::{{closure}}
7: hir_ty::mir::borrowck::all_mir_bodies
8: hir_ty::mir::borrowck::borrowck_query
9: salsa::Cycle::catch
10: salsa::derived::slot::Slot<Q,MP>::execute
11: salsa::derived::slot::Slot<Q,MP>::read
12: <salsa::derived::DerivedStorage<Q,MP> as salsa::plumbing::QueryStorageOps<Q>>::fetch
13: <DB as hir_ty::db::HirDatabase>::borrowck::__shim
14: <DB as hir_ty::db::HirDatabase>::borrowck
15: hir::DefWithBody::diagnostics
16: hir::ModuleDef::diagnostics
17: hir::Module::diagnostics
18: ide_diagnostics::diagnostics
19: salsa::Cancelled::catch
20: ide::Analysis::diagnostics
21: core::ops::function::impls::<impl core::ops::function::FnMut<A> for &mut F>::call_mut
22: <alloc::vec::Vec<T> as alloc::vec::spec_from_iter::SpecFromIter<T,I>>::from_iter
23: rust_analyzer::diagnostics::fetch_native_diagnostics
24: core::ops::function::FnOnce::call_once{{vtable.shim}}
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
rustc --version rustc 1.80.0-beta.4 (64a1fe671 2024-06-21)
rust-analyzer --version rust-analyzer 0.0.0 (cae997e338 2024-07-03)