diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index 3a62cd52a9d94..ee43eb736e651 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -133,7 +133,7 @@ pub(crate) fn codegen_const_value<'tcx>(
}
}
Scalar::Ptr(ptr, _size) => {
- let (prov, offset) = ptr.into_parts(); // we know the `offset` is relative
+ let (prov, offset) = ptr.prov_and_relative_offset();
let alloc_id = prov.alloc_id();
let base_addr = match fx.tcx.global_alloc(alloc_id) {
GlobalAlloc::Memory(alloc) => {
diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs
index fdd47821b515b..89f77f9169928 100644
--- a/compiler/rustc_codegen_gcc/src/common.rs
+++ b/compiler/rustc_codegen_gcc/src/common.rs
@@ -248,7 +248,7 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
}
}
Scalar::Ptr(ptr, _size) => {
- let (prov, offset) = ptr.into_parts(); // we know the `offset` is relative
+ let (prov, offset) = ptr.prov_and_relative_offset();
let alloc_id = prov.alloc_id();
let base_addr = match self.tcx.global_alloc(alloc_id) {
GlobalAlloc::Memory(alloc) => {
diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs
index ae5add59322fe..7cfab25bc50cf 100644
--- a/compiler/rustc_codegen_llvm/src/common.rs
+++ b/compiler/rustc_codegen_llvm/src/common.rs
@@ -268,7 +268,7 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> {
}
}
Scalar::Ptr(ptr, _size) => {
- let (prov, offset) = ptr.into_parts();
+ let (prov, offset) = ptr.prov_and_relative_offset();
let global_alloc = self.tcx.global_alloc(prov.alloc_id());
let base_addr = match global_alloc {
GlobalAlloc::Memory(alloc) => {
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
index 8fddc7e324973..08e1877f0eb2b 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -209,9 +209,9 @@ pub(super) fn op_to_const<'tcx>(
match immediate {
Left(ref mplace) => {
- // We know `offset` is relative to the allocation, so we can use `into_parts`.
- let (prov, offset) = mplace.ptr().into_parts();
- let alloc_id = prov.expect("cannot have `fake` place for non-ZST type").alloc_id();
+ let (prov, offset) =
+ mplace.ptr().into_pointer_or_addr().unwrap().prov_and_relative_offset();
+ let alloc_id = prov.alloc_id();
ConstValue::Indirect { alloc_id, offset }
}
// see comment on `let force_as_immediate` above
@@ -232,9 +232,10 @@ pub(super) fn op_to_const<'tcx>(
imm.layout.ty,
);
let msg = "`op_to_const` on an immediate scalar pair must only be used on slice references to the beginning of an actual allocation";
- // We know `offset` is relative to the allocation, so we can use `into_parts`.
- let (prov, offset) = a.to_pointer(ecx).expect(msg).into_parts();
- let alloc_id = prov.expect(msg).alloc_id();
+ let ptr = a.to_pointer(ecx).expect(msg);
+ let (prov, offset) =
+ ptr.into_pointer_or_addr().expect(msg).prov_and_relative_offset();
+ let alloc_id = prov.alloc_id();
let data = ecx.tcx.global_alloc(alloc_id).unwrap_memory();
assert!(offset == abi::Size::ZERO, "{}", msg);
let meta = b.to_target_usize(ecx).expect(msg);
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index 14abdd8c98c18..9133a5fc8ef2f 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -574,7 +574,7 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
if addr != 0 {
diag.arg(
"pointer",
- Pointer::>::from_addr_invalid(addr).to_string(),
+ Pointer:: >::without_provenance(addr).to_string(),
);
}
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index d6d230fbd1776..35ec303f96197 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -747,7 +747,7 @@ pub macro compile_time_machine(<$tcx: lifetime>) {
// Allow these casts, but make the pointer not dereferenceable.
// (I.e., they behave like transmutation.)
// This is correct because no pointers can ever be exposed in compile-time evaluation.
- interp_ok(Pointer::from_addr_invalid(addr))
+ interp_ok(Pointer::without_provenance(addr))
}
#[inline(always)]
@@ -756,8 +756,7 @@ pub macro compile_time_machine(<$tcx: lifetime>) {
ptr: Pointer,
_size: i64,
) -> Option<(AllocId, Size, Self::ProvenanceExtra)> {
- // We know `offset` is relative to the allocation, so we can use `into_parts`.
- let (prov, offset) = ptr.into_parts();
+ let (prov, offset) = ptr.prov_and_relative_offset();
Some((prov.alloc_id(), offset, prov.immutable()))
}
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 69fceb02ff931..3b36bb8598577 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -1596,7 +1596,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
Some((alloc_id, offset, extra)) => Ok((alloc_id, offset, extra)),
None => {
assert!(M::Provenance::OFFSET_IS_ADDR);
- let (_, addr) = ptr.into_parts();
+ // Offset is absolute, as we just asserted.
+ let (_, addr) = ptr.into_raw_parts();
Err(addr.bytes())
}
},
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index 3028568dd8f00..a3cd35ff0bbbf 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -118,7 +118,7 @@ impl<'tcx, Prov: Provenance> MPlaceTy<'tcx, Prov> {
pub fn fake_alloc_zst(layout: TyAndLayout<'tcx>) -> Self {
assert!(layout.is_zst());
let align = layout.align.abi;
- let ptr = Pointer::from_addr_invalid(align.bytes()); // no provenance, absolute address
+ let ptr = Pointer::without_provenance(align.bytes()); // no provenance, absolute address
MPlaceTy { mplace: MemPlace { ptr, meta: MemPlaceMeta::None, misaligned: None }, layout }
}
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 998ef3729eafe..7268001938021 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -518,7 +518,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
Ub(DanglingIntPointer { addr: i, .. }) => DanglingPtrNoProvenance {
ptr_kind,
// FIXME this says "null pointer" when null but we need translate
- pointer: format!("{}", Pointer::>::from_addr_invalid(i))
+ pointer: format!("{}", Pointer:: >::without_provenance(i))
},
Ub(PointerOutOfBounds { .. }) => DanglingPtrOutOfBounds {
ptr_kind
@@ -868,7 +868,9 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
fn add_data_range(&mut self, ptr: Pointer >, size: Size) {
if let Some(data_bytes) = self.data_bytes.as_mut() {
// We only have to store the offset, the rest is the same for all pointers here.
- let (_prov, offset) = ptr.into_parts();
+ // The logic is agnostic to wether the offset is relative or absolute as long as
+ // it is consistent.
+ let (_prov, offset) = ptr.into_raw_parts();
// Add this.
data_bytes.add_range(offset, size);
};
@@ -894,7 +896,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
.as_mplace_or_imm()
.expect_left("place must be in memory")
.ptr();
- let (_prov, offset) = ptr.into_parts();
+ let (_prov, offset) = ptr.into_raw_parts();
offset
}
@@ -903,7 +905,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
// Our value must be in memory, otherwise we would not have set up `data_bytes`.
let mplace = self.ecx.force_allocation(place)?;
// Determine starting offset and size.
- let (_prov, start_offset) = mplace.ptr().into_parts();
+ let (_prov, start_offset) = mplace.ptr().into_raw_parts();
let (size, _align) = self
.ecx
.size_and_align_of_val(&mplace)?
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 4855fc58d034a..1849038545556 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -1112,7 +1112,9 @@ fn get_backend_from_raw_matches(
matches: &Matches,
) -> Box {
let debug_flags = matches.opt_strs("Z");
- let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
+ let backend_name = debug_flags
+ .iter()
+ .find_map(|x| x.strip_prefix("codegen-backend=").or(x.strip_prefix("codegen_backend=")));
let target = parse_target_triple(early_dcx, matches);
let sysroot = Sysroot::new(matches.opt_str("sysroot").map(PathBuf::from));
let target = config::build_target_config(early_dcx, &target, sysroot.path());
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index edfb05e2ccd25..3fe7c5e42864d 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -298,6 +298,16 @@ fn configure_and_expand(
fn print_macro_stats(ecx: &ExtCtxt<'_>) {
use std::fmt::Write;
+ let crate_name = ecx.ecfg.crate_name.as_str();
+ let crate_name = if crate_name == "build_script_build" {
+ // This is a build script. Get the package name from the environment.
+ let pkg_name =
+ std::env::var("CARGO_PKG_NAME").unwrap_or_else(|_| "".to_string());
+ format!("{pkg_name} build script")
+ } else {
+ crate_name.to_string()
+ };
+
// No instability because we immediately sort the produced vector.
#[allow(rustc::potential_query_instability)]
let mut macro_stats: Vec<_> = ecx
@@ -327,7 +337,7 @@ fn print_macro_stats(ecx: &ExtCtxt<'_>) {
// non-interleaving, though.
let mut s = String::new();
_ = writeln!(s, "{prefix} {}", "=".repeat(banner_w));
- _ = writeln!(s, "{prefix} MACRO EXPANSION STATS: {}", ecx.ecfg.crate_name);
+ _ = writeln!(s, "{prefix} MACRO EXPANSION STATS: {}", crate_name);
_ = writeln!(
s,
"{prefix} {:uses_w$}{:>lines_w$}{:>avg_lines_w$}{:>bytes_w$}{:>avg_bytes_w$}",
@@ -341,20 +351,30 @@ fn print_macro_stats(ecx: &ExtCtxt<'_>) {
}
for (bytes, lines, uses, name, kind) in macro_stats {
let mut name = ExpnKind::Macro(kind, *name).descr();
+ let uses_with_underscores = thousands::usize_with_underscores(uses);
let avg_lines = lines as f64 / uses as f64;
let avg_bytes = bytes as f64 / uses as f64;
- if name.len() >= name_w {
- // If the name is long, print it on a line by itself, then
- // set the name to empty and print things normally, to show the
- // stats on the next line.
+
+ // Ensure the "Macro Name" and "Uses" columns are as compact as possible.
+ let mut uses_w = uses_w;
+ if name.len() + uses_with_underscores.len() >= name_w + uses_w {
+ // The name would abut or overlap the uses value. Print the name
+ // on a line by itself, then set the name to empty and print things
+ // normally, to show the stats on the next line.
_ = writeln!(s, "{prefix} {:= name_w {
+ // The name won't abut or overlap with the uses value, but it does
+ // overlap with the empty part of the uses column. Shrink the width
+ // of the uses column to account for the excess name length.
+ uses_w = uses_with_underscores.len() + 1
+ };
+
_ = writeln!(
s,
"{prefix} {:uses_w$}{:>lines_w$}{:>avg_lines_w$}{:>bytes_w$}{:>avg_bytes_w$}",
name,
- thousands::usize_with_underscores(uses),
+ uses_with_underscores,
thousands::usize_with_underscores(lines),
thousands::f64p1_with_underscores(avg_lines),
thousands::usize_with_underscores(bytes),
diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs
index 2b2ffa7162880..16edc24054480 100644
--- a/compiler/rustc_middle/src/mir/consts.rs
+++ b/compiler/rustc_middle/src/mir/consts.rs
@@ -168,8 +168,9 @@ impl<'tcx> ConstValue<'tcx> {
return Some(&[]);
}
// Non-empty slice, must have memory. We know this is a relative pointer.
- let (inner_prov, offset) = ptr.into_parts();
- let data = tcx.global_alloc(inner_prov?.alloc_id()).unwrap_memory();
+ let (inner_prov, offset) =
+ ptr.into_pointer_or_addr().ok()?.prov_and_relative_offset();
+ let data = tcx.global_alloc(inner_prov.alloc_id()).unwrap_memory();
(data, offset.bytes(), offset.bytes() + len)
}
};
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index dd55d039794f7..4198b198ab1ce 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -526,7 +526,7 @@ impl Allocation {
let ptr_bytes = &mut bytes[idx..idx + ptr_size];
let bits = read_target_uint(endian, ptr_bytes).unwrap();
let (ptr_prov, ptr_offset) =
- adjust_ptr(Pointer::new(alloc_id, Size::from_bytes(bits)))?.into_parts();
+ adjust_ptr(Pointer::new(alloc_id, Size::from_bytes(bits)))?.into_raw_parts();
write_target_uint(endian, ptr_bytes, ptr_offset.bytes().into()).unwrap();
new_provenance.push((offset, ptr_prov));
}
@@ -769,7 +769,7 @@ impl Allocation
// as-is into memory. This also double-checks that `val.size()` matches `range.size`.
let (bytes, provenance) = match val.to_bits_or_ptr_internal(range.size)? {
Right(ptr) => {
- let (provenance, offset) = ptr.into_parts();
+ let (provenance, offset) = ptr.into_raw_parts();
(u128::from(offset.bytes()), Some(provenance))
}
Left(data) => (data, None),
diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs
index 25c7c26ddd974..0ff14f15c13a4 100644
--- a/compiler/rustc_middle/src/mir/interpret/pointer.rs
+++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs
@@ -288,7 +288,7 @@ impl From for Pointer {
impl From> for Pointer> {
#[inline(always)]
fn from(ptr: Pointer) -> Self {
- let (prov, offset) = ptr.into_parts();
+ let (prov, offset) = ptr.into_raw_parts();
Pointer::new(Some(prov), offset)
}
}
@@ -314,19 +314,17 @@ impl Pointer> {
assert!(Prov::OFFSET_IS_ADDR);
self.offset
}
-}
-impl Pointer> {
/// Creates a pointer to the given address, with invalid provenance (i.e., cannot be used for
/// any memory access).
#[inline(always)]
- pub fn from_addr_invalid(addr: u64) -> Self {
+ pub fn without_provenance(addr: u64) -> Self {
Pointer { provenance: None, offset: Size::from_bytes(addr) }
}
#[inline(always)]
pub fn null() -> Self {
- Pointer::from_addr_invalid(0)
+ Pointer::without_provenance(0)
}
}
@@ -336,11 +334,11 @@ impl Pointer {
Pointer { provenance, offset }
}
- /// Obtain the constituents of this pointer. Not that the meaning of the offset depends on the type `Prov`!
- /// This function must only be used in the implementation of `Machine::ptr_get_alloc`,
- /// and when a `Pointer` is taken apart to be stored efficiently in an `Allocation`.
+ /// Obtain the constituents of this pointer. Note that the meaning of the offset depends on the
+ /// type `Prov`! This is a low-level function that should only be used when absolutely
+ /// necessary. Prefer `prov_and_relative_offset` if possible.
#[inline(always)]
- pub fn into_parts(self) -> (Prov, Size) {
+ pub fn into_raw_parts(self) -> (Prov, Size) {
(self.provenance, self.offset)
}
@@ -361,3 +359,12 @@ impl Pointer {
self.wrapping_offset(Size::from_bytes(i as u64), cx)
}
}
+
+impl Pointer {
+ /// Return the provenance and relative offset stored in this pointer. Safer alternative to
+ /// `into_raw_parts` since the type ensures that the offset is indeed relative.
+ #[inline(always)]
+ pub fn prov_and_relative_offset(self) -> (CtfeProvenance, Size) {
+ (self.provenance, self.offset)
+ }
+}
diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs
index 7ba0e5b5e07e5..8092f634dc854 100644
--- a/compiler/rustc_middle/src/mir/interpret/value.rs
+++ b/compiler/rustc_middle/src/mir/interpret/value.rs
@@ -109,7 +109,7 @@ impl Scalar {
/// Create a Scalar from a pointer with an `Option<_>` provenance (where `None` represents a
/// plain integer / "invalid" pointer).
pub fn from_maybe_pointer(ptr: Pointer>, cx: &impl HasDataLayout) -> Self {
- match ptr.into_parts() {
+ match ptr.into_raw_parts() {
(Some(prov), offset) => Scalar::from_pointer(Pointer::new(prov, offset), cx),
(None, offset) => {
Scalar::Int(ScalarInt::try_from_uint(offset.bytes(), cx.pointer_size()).unwrap())
@@ -276,7 +276,7 @@ impl<'tcx, Prov: Provenance> Scalar {
Right(ptr) => interp_ok(ptr.into()),
Left(bits) => {
let addr = u64::try_from(bits).unwrap();
- interp_ok(Pointer::from_addr_invalid(addr))
+ interp_ok(Pointer::without_provenance(addr))
}
}
}
@@ -299,7 +299,7 @@ impl<'tcx, Prov: Provenance> Scalar {
Ok(ScalarInt::try_from_uint(ptr.offset.bytes(), Size::from_bytes(sz)).unwrap())
} else {
// We know `offset` is relative, since `OFFSET_IS_ADDR == false`.
- let (prov, offset) = ptr.into_parts();
+ let (prov, offset) = ptr.into_raw_parts();
// Because `OFFSET_IS_ADDR == false`, this unwrap can never fail.
Err(Scalar::Ptr(Pointer::new(prov.get_alloc_id().unwrap(), offset), sz))
}
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 1392d1d08fcb5..bee490b3648b9 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1755,7 +1755,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
) -> Result<(), PrintError> {
define_scoped_cx!(self);
- let (prov, offset) = ptr.into_parts();
+ let (prov, offset) = ptr.prov_and_relative_offset();
match ty.kind() {
// Byte strings (&[u8; N])
ty::Ref(_, inner, _) => {
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index b17b7f450009c..335354c23b67a 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -1636,7 +1636,7 @@ fn op_to_prop_const<'tcx>(
}
let pointer = mplace.ptr().into_pointer_or_addr().ok()?;
- let (prov, offset) = pointer.into_parts();
+ let (prov, offset) = pointer.prov_and_relative_offset();
let alloc_id = prov.alloc_id();
intern_const_alloc_for_constprop(ecx, alloc_id).discard_err()?;
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index a6ca699e28241..2434a278d556b 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -11,6 +11,15 @@ dependencies = [
"memchr",
]
+[[package]]
+name = "ansi_term"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
+dependencies = [
+ "winapi",
+]
+
[[package]]
name = "anstyle"
version = "1.0.10"
@@ -62,8 +71,8 @@ dependencies = [
"toml",
"tracing",
"tracing-chrome",
+ "tracing-forest",
"tracing-subscriber",
- "tracing-tree",
"walkdir",
"windows",
"xz2",
@@ -449,15 +458,6 @@ dependencies = [
"winapi",
]
-[[package]]
-name = "nu-ansi-term"
-version = "0.50.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399"
-dependencies = [
- "windows-sys 0.52.0",
-]
-
[[package]]
name = "objc2-core-foundation"
version = "0.3.1"
@@ -775,6 +775,26 @@ dependencies = [
"winapi-util",
]
+[[package]]
+name = "thiserror"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
[[package]]
name = "thread_local"
version = "1.1.8"
@@ -837,6 +857,19 @@ dependencies = [
"valuable",
]
+[[package]]
+name = "tracing-forest"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee40835db14ddd1e3ba414292272eddde9dad04d3d4b65509656414d1c42592f"
+dependencies = [
+ "ansi_term",
+ "smallvec",
+ "thiserror",
+ "tracing",
+ "tracing-subscriber",
+]
+
[[package]]
name = "tracing-log"
version = "0.2.0"
@@ -855,7 +888,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
dependencies = [
"matchers",
- "nu-ansi-term 0.46.0",
+ "nu-ansi-term",
"once_cell",
"regex",
"sharded-slab",
@@ -866,18 +899,6 @@ dependencies = [
"tracing-log",
]
-[[package]]
-name = "tracing-tree"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f459ca79f1b0d5f71c54ddfde6debfc59c8b6eeb46808ae492077f739dc7b49c"
-dependencies = [
- "nu-ansi-term 0.50.1",
- "tracing-core",
- "tracing-log",
- "tracing-subscriber",
-]
-
[[package]]
name = "typenum"
version = "1.17.0"
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index 9785a306c9b1b..073cebdcae24f 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -7,7 +7,7 @@ default-run = "bootstrap"
[features]
build-metrics = ["sysinfo"]
-tracing = ["dep:tracing", "dep:tracing-chrome", "dep:tracing-subscriber", "dep:tracing-tree"]
+tracing = ["dep:tracing", "dep:tracing-chrome", "dep:tracing-subscriber", "dep:tracing-forest"]
[lib]
path = "src/lib.rs"
@@ -64,7 +64,7 @@ sysinfo = { version = "0.35.0", default-features = false, optional = true, featu
tracing = { version = "0.1", optional = true, features = ["attributes"] }
tracing-chrome = { version = "0.7", optional = true }
tracing-subscriber = { version = "0.3", optional = true, features = ["env-filter", "fmt", "registry", "std"] }
-tracing-tree = { version = "0.4.0", optional = true }
+tracing-forest = { version = "0.1.6", optional = true, default-features = false, features = ["smallvec", "ansi", "env-filter"] }
[target.'cfg(windows)'.dependencies.junction]
version = "1.0.0"
diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs
index 833f80279517a..e1862a451f2dc 100644
--- a/src/bootstrap/src/bin/main.rs
+++ b/src/bootstrap/src/bin/main.rs
@@ -217,12 +217,11 @@ fn check_version(config: &Config) -> Option {
// "tracing", instrument(..))]`.
#[cfg(feature = "tracing")]
fn setup_tracing() -> impl Drop {
+ use tracing_forest::ForestLayer;
use tracing_subscriber::EnvFilter;
use tracing_subscriber::layer::SubscriberExt;
let filter = EnvFilter::from_env("BOOTSTRAP_TRACING");
- // cf. .
- let layer = tracing_tree::HierarchicalLayer::default().with_targets(true).with_indent_amount(2);
let mut chrome_layer = tracing_chrome::ChromeLayerBuilder::new().include_args(true);
@@ -233,7 +232,8 @@ fn setup_tracing() -> impl Drop {
let (chrome_layer, _guard) = chrome_layer.build();
- let registry = tracing_subscriber::registry().with(filter).with(layer).with(chrome_layer);
+ let registry =
+ tracing_subscriber::registry().with(filter).with(ForestLayer::default()).with(chrome_layer);
tracing::subscriber::set_global_default(registry).unwrap();
_guard
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 8200e1541692a..84064150738f5 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -2241,7 +2241,7 @@ impl Step for Assemble {
debug!("copying codegen backends to sysroot");
copy_codegen_backends_to_sysroot(builder, build_compiler, target_compiler);
- if builder.config.lld_enabled && !builder.config.is_system_llvm(target_compiler.host) {
+ if builder.config.lld_enabled {
builder.ensure(crate::core::build_steps::tool::LldWrapper {
build_compiler,
target_compiler,
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index d1ffdf24acd0e..0cdfbbdaf75d7 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -1003,9 +1003,7 @@ impl Config {
}
if config.lld_enabled && config.is_system_llvm(config.host_target) {
- eprintln!(
- "Warning: LLD is enabled when using external llvm-config. LLD will not be built and copied to the sysroot."
- );
+ panic!("Cannot enable LLD with `rust.lld = true` when using external llvm-config.");
}
config.optimized_compiler_builtins =
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index 7c588cfea8c28..006c294d4458f 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -431,4 +431,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
severity: ChangeSeverity::Warning,
summary: "It is no longer possible to `x build` with stage 0. All build commands have to be on stage 1+.",
},
+ ChangeInfo {
+ change_id: 143175,
+ severity: ChangeSeverity::Info,
+ summary: "It is no longer possible to combine `rust.lld = true` with configuring external LLVM using `llvm.llvm-config`.",
+ },
];
diff --git a/src/doc/book b/src/doc/book
index 8a6d44e45b7b5..ef1ce8f87a8b1 160000
--- a/src/doc/book
+++ b/src/doc/book
@@ -1 +1 @@
-Subproject commit 8a6d44e45b7b564eeb6bae30507e1fbac439d72d
+Subproject commit ef1ce8f87a8b18feb1b6a9cf9a4939a79bde6795
diff --git a/src/doc/embedded-book b/src/doc/embedded-book
index 10fa1e084365f..41f688a598a50 160000
--- a/src/doc/embedded-book
+++ b/src/doc/embedded-book
@@ -1 +1 @@
-Subproject commit 10fa1e084365f23f24ad0000df541923385b73b6
+Subproject commit 41f688a598a5022b749e23d37f3c524f6a0b28e1
diff --git a/src/doc/reference b/src/doc/reference
index 50fc1628f3656..e9fc99f107840 160000
--- a/src/doc/reference
+++ b/src/doc/reference
@@ -1 +1 @@
-Subproject commit 50fc1628f36563958399123829c73755fa7a8421
+Subproject commit e9fc99f107840813916f62e16b3f6d9556e1f2d8
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
index 05c7d8bae65f2..288b4e4948add 160000
--- a/src/doc/rust-by-example
+++ b/src/doc/rust-by-example
@@ -1 +1 @@
-Subproject commit 05c7d8bae65f23a1837430c5a19be129d414f5ec
+Subproject commit 288b4e4948add43f387cad35adc7b1c54ca6fe12
diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml
index 3b544d8b82817..cdada5a223062 100644
--- a/src/tools/compiletest/Cargo.toml
+++ b/src/tools/compiletest/Cargo.toml
@@ -6,6 +6,10 @@ edition = "2024"
[lib]
doctest = false
+[[bin]]
+name = "compiletest"
+path = "src/bin/main.rs"
+
[dependencies]
# tidy-alphabetical-start
anstyle-svg = "0.1.3"
diff --git a/src/tools/compiletest/src/bin/main.rs b/src/tools/compiletest/src/bin/main.rs
new file mode 100644
index 0000000000000..1f777e71cf97f
--- /dev/null
+++ b/src/tools/compiletest/src/bin/main.rs
@@ -0,0 +1,24 @@
+use std::env;
+use std::io::IsTerminal;
+use std::sync::Arc;
+
+use compiletest::{early_config_check, log_config, parse_config, run_tests};
+
+fn main() {
+ tracing_subscriber::fmt::init();
+
+ // colored checks stdout by default, but for some reason only stderr is a terminal.
+ // compiletest *does* print many things to stdout, but it doesn't really matter.
+ if std::io::stderr().is_terminal()
+ && matches!(std::env::var("NO_COLOR").as_deref(), Err(_) | Ok("0"))
+ {
+ colored::control::set_override(true);
+ }
+
+ let config = Arc::new(parse_config(env::args().collect()));
+
+ early_config_check(&config);
+
+ log_config(&config);
+ run_tests(config);
+}
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index 0db4d3f6a4100..23a4dd73796e2 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -51,12 +51,6 @@ use crate::util::logv;
/// some code here that inspects environment variables or even runs executables
/// (e.g. when discovering debugger versions).
pub fn parse_config(args: Vec) -> Config {
- if env::var("RUST_TEST_NOCAPTURE").is_ok() {
- eprintln!(
- "WARNING: RUST_TEST_NOCAPTURE is not supported. Use the `--no-capture` flag instead."
- );
- }
-
let mut opts = Options::new();
opts.reqopt("", "compile-lib-path", "path to host shared libraries", "PATH")
.reqopt("", "run-lib-path", "path to target shared libraries", "PATH")
@@ -1111,3 +1105,25 @@ fn check_for_overlapping_test_paths(found_path_stems: &HashSet) {
);
}
}
+
+pub fn early_config_check(config: &Config) {
+ if !config.has_html_tidy && config.mode == Mode::Rustdoc {
+ eprintln!("warning: `tidy` (html-tidy.org) is not installed; diffs will not be generated");
+ }
+
+ if !config.profiler_runtime && config.mode == Mode::CoverageRun {
+ let actioned = if config.bless { "blessed" } else { "checked" };
+ eprintln!(
+ r#"
+WARNING: profiler runtime is not available, so `.coverage` files won't be {actioned}
+help: try setting `profiler = true` in the `[build]` section of `bootstrap.toml`"#
+ );
+ }
+
+ // `RUST_TEST_NOCAPTURE` is a libtest env var, but we don't callout to libtest.
+ if env::var("RUST_TEST_NOCAPTURE").is_ok() {
+ eprintln!(
+ "WARNING: RUST_TEST_NOCAPTURE is not supported. Use the `--no-capture` flag instead."
+ );
+ }
+}
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
deleted file mode 100644
index b9ae583581ef2..0000000000000
--- a/src/tools/compiletest/src/main.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-use std::env;
-use std::io::IsTerminal;
-use std::sync::Arc;
-
-use compiletest::common::Mode;
-use compiletest::{log_config, parse_config, run_tests};
-
-fn main() {
- tracing_subscriber::fmt::init();
-
- // colored checks stdout by default, but for some reason only stderr is a terminal.
- // compiletest *does* print many things to stdout, but it doesn't really matter.
- if std::io::stderr().is_terminal()
- && matches!(std::env::var("NO_COLOR").as_deref(), Err(_) | Ok("0"))
- {
- colored::control::set_override(true);
- }
-
- let config = Arc::new(parse_config(env::args().collect()));
-
- if !config.has_html_tidy && config.mode == Mode::Rustdoc {
- eprintln!("warning: `tidy` (html-tidy.org) is not installed; diffs will not be generated");
- }
-
- if !config.profiler_runtime && config.mode == Mode::CoverageRun {
- let actioned = if config.bless { "blessed" } else { "checked" };
- eprintln!(
- r#"
-WARNING: profiler runtime is not available, so `.coverage` files won't be {actioned}
-help: try setting `profiler = true` in the `[build]` section of `bootstrap.toml`"#
- );
- }
-
- log_config(&config);
- run_tests(config);
-}
diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs
index 4a038fe648735..1796120cf8ab9 100644
--- a/src/tools/miri/src/alloc_addresses/mod.rs
+++ b/src/tools/miri/src/alloc_addresses/mod.rs
@@ -390,7 +390,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
) -> InterpResult<'tcx, interpret::Pointer> {
let this = self.eval_context_ref();
- let (prov, offset) = ptr.into_parts(); // offset is relative (AllocId provenance)
+ let (prov, offset) = ptr.prov_and_relative_offset();
let alloc_id = prov.alloc_id();
// Get a pointer to the beginning of this allocation.
@@ -447,7 +447,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
) -> Option<(AllocId, Size)> {
let this = self.eval_context_ref();
- let (tag, addr) = ptr.into_parts(); // addr is absolute (Tag provenance)
+ let (tag, addr) = ptr.into_raw_parts(); // addr is absolute (Miri provenance)
let alloc_id = if let Provenance::Concrete { alloc_id, .. } = tag {
alloc_id
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index 3a748c4c68726..17c13a9e33c54 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -285,7 +285,7 @@ impl interpret::Provenance for Provenance {
}
fn fmt(ptr: &interpret::Pointer, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let (prov, addr) = ptr.into_parts(); // address is absolute
+ let (prov, addr) = ptr.into_raw_parts(); // offset is absolute address
write!(f, "{:#x}", addr.bytes())?;
if f.alternate() {
write!(f, "{prov:#?}")?;
diff --git a/src/tools/miri/src/provenance_gc.rs b/src/tools/miri/src/provenance_gc.rs
index b3d715db9cd63..6adf14486480d 100644
--- a/src/tools/miri/src/provenance_gc.rs
+++ b/src/tools/miri/src/provenance_gc.rs
@@ -68,15 +68,13 @@ impl VisitProvenance for Provenance {
impl VisitProvenance for StrictPointer {
fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
- let (prov, _offset) = self.into_parts();
- prov.visit_provenance(visit);
+ self.provenance.visit_provenance(visit);
}
}
impl VisitProvenance for Pointer {
fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
- let (prov, _offset) = self.into_parts();
- prov.visit_provenance(visit);
+ self.provenance.visit_provenance(visit);
}
}
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index 416cb1ab55e6a..97070eb742f3e 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -411,7 +411,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
AlignFromBytesError::TooLarge(_) => Align::MAX,
}
});
- let (_, addr) = ptr.into_parts(); // we know the offset is absolute
+ let addr = ptr.addr();
// Cannot panic since `align` is a power of 2 and hence non-zero.
if addr.bytes().strict_rem(align.bytes()) != 0 {
throw_unsup_format!(
diff --git a/src/tools/miri/src/shims/unix/mem.rs b/src/tools/miri/src/shims/unix/mem.rs
index 4bbbbc69c08a3..1738de4dd4fe7 100644
--- a/src/tools/miri/src/shims/unix/mem.rs
+++ b/src/tools/miri/src/shims/unix/mem.rs
@@ -49,7 +49,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
&& matches!(&*this.tcx.sess.target.os, "macos" | "solaris" | "illumos")
&& (flags & map_fixed) != 0
{
- return interp_ok(Scalar::from_maybe_pointer(Pointer::from_addr_invalid(addr), this));
+ return interp_ok(Scalar::from_maybe_pointer(Pointer::without_provenance(addr), this));
}
let prot_read = this.eval_libc_i32("PROT_READ");
diff --git a/src/tools/opt-dist/src/tests.rs b/src/tools/opt-dist/src/tests.rs
index 53ce772fa7792..705a1750ae874 100644
--- a/src/tools/opt-dist/src/tests.rs
+++ b/src/tools/opt-dist/src/tests.rs
@@ -72,6 +72,8 @@ change-id = 115898
[rust]
channel = "{channel}"
verbose-tests = true
+# rust-lld cannot be combined with an external LLVM
+lld = false
[build]
rustc = "{rustc}"
diff --git a/src/tools/rust-analyzer/.github/workflows/ci.yaml b/src/tools/rust-analyzer/.github/workflows/ci.yaml
index 79fb7a2d2ea96..770652494f4a8 100644
--- a/src/tools/rust-analyzer/.github/workflows/ci.yaml
+++ b/src/tools/rust-analyzer/.github/workflows/ci.yaml
@@ -17,6 +17,10 @@ env:
RUST_BACKTRACE: short
RUSTUP_MAX_RETRIES: 10
+defaults:
+ run:
+ shell: bash
+
jobs:
changes:
runs-on: ubuntu-latest
@@ -80,6 +84,7 @@ jobs:
CC: deny_c
strategy:
+ fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
@@ -99,7 +104,7 @@ jobs:
rustup toolchain install nightly --profile minimal --component rustfmt
# https://github.com/actions-rust-lang/setup-rust-toolchain/blob/main/rust.json
- name: Install Rust Problem Matcher
- if: matrix.os == 'ubuntu-latest'
+ if: matrix.os == 'macos-latest'
run: echo "::add-matcher::.github/rust.json"
# - name: Cache Dependencies
@@ -116,23 +121,9 @@ jobs:
if: matrix.os == 'ubuntu-latest'
run: cargo codegen --check
- - name: Compile tests
- run: cargo test --no-run
-
- name: Run tests
run: cargo nextest run --no-fail-fast --hide-progress-bar --status-level fail
- - name: Cancel parallel jobs
- if: failure()
- run: |
- # https://docs.github.com/en/rest/actions/workflow-runs?apiVersion=2022-11-28#cancel-a-workflow-run
- curl -L \
- -X POST \
- -H "Accept: application/vnd.github.v3+json" \
- -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
- -H "X-GitHub-Api-Version: 2022-11-28" \
- https://api.github.com/repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/cancel
-
- name: Run Clippy
if: matrix.os == 'macos-latest'
run: cargo clippy --all-targets -- -D clippy::disallowed_macros -D clippy::dbg_macro -D clippy::todo -D clippy::print_stdout -D clippy::print_stderr
@@ -333,3 +324,21 @@ jobs:
jq -C <<< '${{ toJson(needs) }}'
# Check if all jobs that we depend on (in the needs array) were successful (or have been skipped).
jq --exit-status 'all(.result == "success" or .result == "skipped")' <<< '${{ toJson(needs) }}'
+
+ cancel-if-matrix-failed:
+ needs: rust
+ if: ${{ always() }}
+ runs-on: ubuntu-latest
+ steps:
+ - name: Cancel parallel jobs
+ run: |
+ if jq --exit-status 'all(.result == "success" or .result == "skipped")' <<< '${{ toJson(needs) }}'; then
+ exit 0
+ fi
+ # https://docs.github.com/en/rest/actions/workflow-runs?apiVersion=2022-11-28#cancel-a-workflow-run
+ curl -L \
+ -X POST \
+ -H "Accept: application/vnd.github.v3+json" \
+ -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
+ -H "X-GitHub-Api-Version: 2022-11-28" \
+ https://api.github.com/repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/cancel
diff --git a/src/tools/rust-analyzer/.github/workflows/release.yaml b/src/tools/rust-analyzer/.github/workflows/release.yaml
index a758ecfd46796..5bd90130f4c21 100644
--- a/src/tools/rust-analyzer/.github/workflows/release.yaml
+++ b/src/tools/rust-analyzer/.github/workflows/release.yaml
@@ -134,13 +134,13 @@ jobs:
- name: Run analysis-stats on rust-analyzer
if: matrix.target == 'x86_64-unknown-linux-gnu'
- run: target/${{ matrix.target }}/release/rust-analyzer analysis-stats .
+ run: target/${{ matrix.target }}/release/rust-analyzer analysis-stats . -q
- name: Run analysis-stats on rust std library
if: matrix.target == 'x86_64-unknown-linux-gnu'
env:
RUSTC_BOOTSTRAP: 1
- run: target/${{ matrix.target }}/release/rust-analyzer analysis-stats --with-deps $(rustc --print sysroot)/lib/rustlib/src/rust/library/std
+ run: target/${{ matrix.target }}/release/rust-analyzer analysis-stats --with-deps $(rustc --print sysroot)/lib/rustlib/src/rust/library/std -q
- name: Upload artifacts
uses: actions/upload-artifact@v4
diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock
index 2c7b46416412d..caa8f28d8e2f6 100644
--- a/src/tools/rust-analyzer/Cargo.lock
+++ b/src/tools/rust-analyzer/Cargo.lock
@@ -1458,7 +1458,7 @@ dependencies = [
"edition",
"expect-test",
"ra-ap-rustc_lexer",
- "rustc-literal-escaper 0.0.3",
+ "rustc-literal-escaper 0.0.4",
"stdx",
"tracing",
]
@@ -1927,9 +1927,9 @@ checksum = "0041b6238913c41fe704213a4a9329e2f685a156d1781998128b4149c230ad04"
[[package]]
name = "rustc-literal-escaper"
-version = "0.0.3"
+version = "0.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78744cd17f5d01c75b709e49807d1363e02a940ccee2e9e72435843fdb0d076e"
+checksum = "ab03008eb631b703dd16978282ae36c73282e7922fe101a4bd072a40ecea7b8b"
[[package]]
name = "rustc-stable-hash"
@@ -2207,7 +2207,7 @@ dependencies = [
"rayon",
"rowan",
"rustc-hash 2.1.1",
- "rustc-literal-escaper 0.0.3",
+ "rustc-literal-escaper 0.0.4",
"rustc_apfloat",
"smol_str",
"stdx",
diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml
index 449c75859cf9c..0a8e6feb46edd 100644
--- a/src/tools/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/Cargo.toml
@@ -143,7 +143,7 @@ serde = { version = "1.0.219" }
serde_derive = { version = "1.0.219" }
serde_json = "1.0.140"
rustc-hash = "2.1.1"
-rustc-literal-escaper = "0.0.3"
+rustc-literal-escaper = "0.0.4"
smallvec = { version = "1.15.1", features = [
"const_new",
"union",
diff --git a/src/tools/rust-analyzer/crates/base-db/Cargo.toml b/src/tools/rust-analyzer/crates/base-db/Cargo.toml
index 3b423a86f97af..ea06fd9c48fc1 100644
--- a/src/tools/rust-analyzer/crates/base-db/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/base-db/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
rust-version.workspace = true
[lib]
+doctest = false
[dependencies]
la-arena.workspace = true
diff --git a/src/tools/rust-analyzer/crates/cfg/Cargo.toml b/src/tools/rust-analyzer/crates/cfg/Cargo.toml
index d7764a16c044c..ba34966614536 100644
--- a/src/tools/rust-analyzer/crates/cfg/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/cfg/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
rust-version.workspace = true
[lib]
+doctest = false
[dependencies]
rustc-hash.workspace = true
diff --git a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml
index c6922eca49f27..abb4819a7672a 100644
--- a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
rust-version.workspace = true
[lib]
+doctest = false
[dependencies]
arrayvec.workspace = true
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs
index 00408e95ae6f5..c67bb2422ac65 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs
@@ -25,11 +25,10 @@ use crate::{
import_map::ImportMap,
item_tree::{ItemTree, file_item_tree_query},
lang_item::{self, LangItem},
- nameres::{assoc::TraitItems, crate_def_map, diagnostics::DefDiagnostics},
+ nameres::crate_def_map,
signatures::{
ConstSignature, EnumSignature, FunctionSignature, ImplSignature, StaticSignature,
StructSignature, TraitAliasSignature, TraitSignature, TypeAliasSignature, UnionSignature,
- VariantFields,
},
tt,
visibility::{self, Visibility},
@@ -113,24 +112,6 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase {
// region:data
- #[salsa::invoke(VariantFields::query)]
- fn variant_fields_with_source_map(
- &self,
- id: VariantId,
- ) -> (Arc, Arc);
-
- #[salsa::transparent]
- #[salsa::invoke(TraitItems::trait_items_query)]
- fn trait_items(&self, e: TraitId) -> Arc;
-
- #[salsa::invoke(TraitItems::trait_items_with_diagnostics_query)]
- fn trait_items_with_diagnostics(&self, tr: TraitId) -> (Arc, DefDiagnostics);
-
- #[salsa::tracked]
- fn variant_fields(&self, id: VariantId) -> Arc {
- self.variant_fields_with_source_map(id).0
- }
-
#[salsa::tracked]
fn trait_signature(&self, trait_: TraitId) -> Arc {
self.trait_signature_with_source_map(trait_).0
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 f617c3225ae13..85bd193223fef 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
@@ -9,7 +9,10 @@ pub mod scope;
#[cfg(test)]
mod tests;
-use std::ops::{Deref, Index};
+use std::{
+ ops::{Deref, Index},
+ sync::LazyLock,
+};
use cfg::{CfgExpr, CfgOptions};
use either::Either;
@@ -19,6 +22,7 @@ use rustc_hash::FxHashMap;
use smallvec::SmallVec;
use span::{Edition, SyntaxContext};
use syntax::{AstPtr, SyntaxNodePtr, ast};
+use triomphe::Arc;
use tt::TextRange;
use crate::{
@@ -220,6 +224,12 @@ impl ExpressionStoreBuilder {
}
impl ExpressionStore {
+ pub fn empty_singleton() -> Arc {
+ static EMPTY: LazyLock> =
+ LazyLock::new(|| Arc::new(ExpressionStoreBuilder::default().finish()));
+ EMPTY.clone()
+ }
+
/// Returns an iterator over all block expressions in this store that define inner items.
pub fn blocks<'a>(
&'a self,
@@ -636,6 +646,12 @@ impl Index for ExpressionStore {
// FIXME: Change `node_` prefix to something more reasonable.
// Perhaps `expr_syntax` and `expr_id`?
impl ExpressionStoreSourceMap {
+ pub fn empty_singleton() -> Arc {
+ static EMPTY: LazyLock> =
+ LazyLock::new(|| Arc::new(ExpressionStoreSourceMap::default()));
+ EMPTY.clone()
+ }
+
pub fn expr_or_pat_syntax(&self, id: ExprOrPatId) -> Result {
match id {
ExprOrPatId::ExprId(id) => self.expr_syntax(id),
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 efa1374a44650..c0e51b338b4ff 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
@@ -2250,7 +2250,7 @@ impl ExprCollector<'_> {
Some(ModuleDefId::ConstId(_)) => (None, Pat::Path(name.into())),
Some(ModuleDefId::EnumVariantId(variant))
// FIXME: This can cause a cycle if the user is writing invalid code
- if self.db.variant_fields(variant.into()).shape != FieldsShape::Record =>
+ if variant.fields(self.db).shape != FieldsShape::Record =>
{
(None, Pat::Path(name.into()))
}
@@ -2825,14 +2825,7 @@ impl ExprCollector<'_> {
let use_format_args_since_1_89_0 = fmt_args().is_some() && fmt_unsafe_arg().is_none();
let idx = if use_format_args_since_1_89_0 {
- self.collect_format_args_impl(
- syntax_ptr,
- fmt,
- hygiene,
- argmap,
- lit_pieces,
- format_options,
- )
+ self.collect_format_args_impl(syntax_ptr, fmt, argmap, lit_pieces, format_options)
} else {
self.collect_format_args_before_1_89_0_impl(
syntax_ptr,
@@ -2962,7 +2955,6 @@ impl ExprCollector<'_> {
&mut self,
syntax_ptr: AstPtr,
fmt: FormatArgs,
- hygiene: HygieneId,
argmap: FxIndexSet<(usize, ArgumentType)>,
lit_pieces: ExprId,
format_options: ExprId,
@@ -2997,8 +2989,11 @@ impl ExprCollector<'_> {
let args =
self.alloc_expr_desugared(Expr::Array(Array::ElementList { elements: args }));
let args_name = Name::new_symbol_root(sym::args);
- let args_binding =
- self.alloc_binding(args_name.clone(), BindingAnnotation::Unannotated, hygiene);
+ let args_binding = self.alloc_binding(
+ args_name.clone(),
+ BindingAnnotation::Unannotated,
+ HygieneId::ROOT,
+ );
let args_pat = self.alloc_pat_desugared(Pat::Bind { id: args_binding, subpat: None });
self.add_definition_to_binding(args_binding, args_pat);
// TODO: We don't have `super let` yet.
@@ -3008,13 +3003,16 @@ impl ExprCollector<'_> {
initializer: Some(args),
else_branch: None,
};
- (vec![let_stmt], self.alloc_expr_desugared(Expr::Path(Path::from(args_name))))
+ (vec![let_stmt], self.alloc_expr_desugared(Expr::Path(args_name.into())))
} else {
// Generate:
// super let args = (&arg0, &arg1, &...);
let args_name = Name::new_symbol_root(sym::args);
- let args_binding =
- self.alloc_binding(args_name.clone(), BindingAnnotation::Unannotated, hygiene);
+ let args_binding = self.alloc_binding(
+ args_name.clone(),
+ BindingAnnotation::Unannotated,
+ HygieneId::ROOT,
+ );
let args_pat = self.alloc_pat_desugared(Pat::Bind { id: args_binding, subpat: None });
self.add_definition_to_binding(args_binding, args_pat);
let elements = arguments
@@ -3057,8 +3055,11 @@ impl ExprCollector<'_> {
.collect();
let array =
self.alloc_expr_desugared(Expr::Array(Array::ElementList { elements: args }));
- let args_binding =
- self.alloc_binding(args_name.clone(), BindingAnnotation::Unannotated, hygiene);
+ let args_binding = self.alloc_binding(
+ args_name.clone(),
+ BindingAnnotation::Unannotated,
+ HygieneId::ROOT,
+ );
let args_pat = self.alloc_pat_desugared(Pat::Bind { id: args_binding, subpat: None });
self.add_definition_to_binding(args_binding, args_pat);
let let_stmt2 = Statement::Let {
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 56c7655f9ea6a..87bcd33ed7b61 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
@@ -121,7 +121,7 @@ pub fn print_variant_body_hir(db: &dyn DefDatabase, owner: VariantId, edition: E
VariantId::UnionId(it) => format!("union {}", item_name(db, it, "")),
};
- let fields = db.variant_fields(owner);
+ let fields = owner.fields(db);
let mut p = Printer {
db,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/generics.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/generics.rs
index a9a0e36312c1a..94e683cb0f8fa 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/hir/generics.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/hir/generics.rs
@@ -331,13 +331,13 @@ impl GenericParams {
}
#[inline]
- pub fn no_predicates(&self) -> bool {
+ pub fn has_no_predicates(&self) -> bool {
self.where_predicates.is_empty()
}
#[inline]
- pub fn where_predicates(&self) -> std::slice::Iter<'_, WherePredicate> {
- self.where_predicates.iter()
+ pub fn where_predicates(&self) -> &[WherePredicate] {
+ &self.where_predicates
}
/// Iterator of type_or_consts field
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs
index a6138fb6821d9..f31f355cfa5d7 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs
@@ -16,7 +16,7 @@ use crate::{
AssocItemId, AttrDefId, Complete, FxIndexMap, ModuleDefId, ModuleId, TraitId,
db::DefDatabase,
item_scope::{ImportOrExternCrate, ItemInNs},
- nameres::{DefMap, crate_def_map},
+ nameres::{DefMap, assoc::TraitItems, crate_def_map},
visibility::Visibility,
};
@@ -221,7 +221,7 @@ impl ImportMap {
trait_import_info: &ImportInfo,
) {
let _p = tracing::info_span!("collect_trait_assoc_items").entered();
- for &(ref assoc_item_name, item) in &db.trait_items(tr).items {
+ for &(ref assoc_item_name, item) in &TraitItems::query(db, tr).items {
let module_def_id = match item {
AssocItemId::FunctionId(f) => ModuleDefId::from(f),
AssocItemId::ConstId(c) => ModuleDefId::from(c),
@@ -482,7 +482,7 @@ mod tests {
use expect_test::{Expect, expect};
use test_fixture::WithFixture;
- use crate::{ItemContainerId, Lookup, test_db::TestDB};
+ use crate::{ItemContainerId, Lookup, nameres::assoc::TraitItems, test_db::TestDB};
use super::*;
@@ -580,7 +580,7 @@ mod tests {
let trait_info = dependency_imports.import_info_for(ItemInNs::Types(trait_id.into()))?;
- let trait_items = db.trait_items(trait_id);
+ let trait_items = TraitItems::query(db, trait_id);
let (assoc_item_name, _) = trait_items
.items
.iter()
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
index faff7d036a289..750308026eec6 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
@@ -9,8 +9,10 @@ use triomphe::Arc;
use crate::{
AdtId, AssocItemId, AttrDefId, Crate, EnumId, EnumVariantId, FunctionId, ImplId, ModuleDefId,
- StaticId, StructId, TraitId, TypeAliasId, UnionId, db::DefDatabase, expr_store::path::Path,
- nameres::crate_def_map,
+ StaticId, StructId, TraitId, TypeAliasId, UnionId,
+ db::DefDatabase,
+ expr_store::path::Path,
+ nameres::{assoc::TraitItems, crate_def_map},
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -113,14 +115,16 @@ pub fn crate_lang_items(db: &dyn DefDatabase, krate: Crate) -> Option {
lang_items.collect_lang_item(db, trait_, LangItemTarget::Trait);
- db.trait_items(trait_).items.iter().for_each(|&(_, assoc_id)| match assoc_id {
- AssocItemId::FunctionId(f) => {
- lang_items.collect_lang_item(db, f, LangItemTarget::Function);
+ TraitItems::query(db, trait_).items.iter().for_each(|&(_, assoc_id)| {
+ match assoc_id {
+ AssocItemId::FunctionId(f) => {
+ lang_items.collect_lang_item(db, f, LangItemTarget::Function);
+ }
+ AssocItemId::TypeAliasId(alias) => {
+ lang_items.collect_lang_item(db, alias, LangItemTarget::TypeAlias)
+ }
+ AssocItemId::ConstId(_) => {}
}
- AssocItemId::TypeAliasId(alias) => {
- lang_items.collect_lang_item(db, alias, LangItemTarget::TypeAlias)
- }
- AssocItemId::ConstId(_) => {}
});
}
ModuleDefId::AdtId(AdtId::EnumId(e)) => {
@@ -304,6 +308,8 @@ impl LangItem {
language_item_table! {
// Variant name, Name, Getter method name, Target Generic requirements;
Sized, sym::sized, sized_trait, Target::Trait, GenericRequirement::Exact(0);
+ MetaSized, sym::meta_sized, sized_trait, Target::Trait, GenericRequirement::Exact(0);
+ PointeeSized, sym::pointee_sized, sized_trait, Target::Trait, GenericRequirement::Exact(0);
Unsize, sym::unsize, unsize_trait, Target::Trait, GenericRequirement::Minimum(1);
/// Trait injected by `#[derive(PartialEq)]`, (i.e. "Partial EQ").
StructuralPeq, sym::structural_peq, structural_peq_trait, Target::Trait, GenericRequirement::None;
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 a562f2d0af2f9..bdf8b453e2d65 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
@@ -87,9 +87,12 @@ use crate::{
attr::Attrs,
builtin_type::BuiltinType,
db::DefDatabase,
+ expr_store::ExpressionStoreSourceMap,
hir::generics::{LocalLifetimeParamId, LocalTypeOrConstParamId},
nameres::{
- LocalDefMap, assoc::ImplItems, block_def_map, crate_def_map, crate_local_def_map,
+ LocalDefMap,
+ assoc::{ImplItems, TraitItems},
+ block_def_map, crate_def_map, crate_local_def_map,
diagnostics::DefDiagnostics,
},
signatures::{EnumVariants, InactiveEnumVariantCode, VariantFields},
@@ -252,9 +255,35 @@ impl_intern!(FunctionId, FunctionLoc, intern_function, lookup_intern_function);
type StructLoc = ItemLoc;
impl_intern!(StructId, StructLoc, intern_struct, lookup_intern_struct);
+impl StructId {
+ pub fn fields(self, db: &dyn DefDatabase) -> &VariantFields {
+ VariantFields::firewall(db, self.into())
+ }
+
+ pub fn fields_with_source_map(
+ self,
+ db: &dyn DefDatabase,
+ ) -> (Arc, Arc) {
+ VariantFields::query(db, self.into())
+ }
+}
+
pub type UnionLoc = ItemLoc;
impl_intern!(UnionId, UnionLoc, intern_union, lookup_intern_union);
+impl UnionId {
+ pub fn fields(self, db: &dyn DefDatabase) -> &VariantFields {
+ VariantFields::firewall(db, self.into())
+ }
+
+ pub fn fields_with_source_map(
+ self,
+ db: &dyn DefDatabase,
+ ) -> (Arc, Arc) {
+ VariantFields::query(db, self.into())
+ }
+}
+
pub type EnumLoc = ItemLoc;
impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum);
@@ -282,6 +311,13 @@ impl_intern!(StaticId, StaticLoc, intern_static, lookup_intern_static);
pub type TraitLoc = ItemLoc;
impl_intern!(TraitId, TraitLoc, intern_trait, lookup_intern_trait);
+impl TraitId {
+ #[inline]
+ pub fn trait_items(self, db: &dyn DefDatabase) -> &TraitItems {
+ TraitItems::query(db, self)
+ }
+}
+
pub type TraitAliasLoc = ItemLoc;
impl_intern!(TraitAliasId, TraitAliasLoc, intern_trait_alias, lookup_intern_trait_alias);
@@ -328,6 +364,20 @@ pub struct EnumVariantLoc {
}
impl_intern!(EnumVariantId, EnumVariantLoc, intern_enum_variant, lookup_intern_enum_variant);
impl_loc!(EnumVariantLoc, id: Variant, parent: EnumId);
+
+impl EnumVariantId {
+ pub fn fields(self, db: &dyn DefDatabase) -> &VariantFields {
+ VariantFields::firewall(db, self.into())
+ }
+
+ pub fn fields_with_source_map(
+ self,
+ db: &dyn DefDatabase,
+ ) -> (Arc, Arc) {
+ VariantFields::query(db, self.into())
+ }
+}
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Macro2Loc {
pub container: ModuleId,
@@ -1015,8 +1065,15 @@ pub enum VariantId {
impl_from!(EnumVariantId, StructId, UnionId for VariantId);
impl VariantId {
- pub fn variant_data(self, db: &dyn DefDatabase) -> Arc {
- db.variant_fields(self)
+ pub fn fields(self, db: &dyn DefDatabase) -> &VariantFields {
+ VariantFields::firewall(db, self)
+ }
+
+ pub fn fields_with_source_map(
+ self,
+ db: &dyn DefDatabase,
+ ) -> (Arc, Arc) {
+ VariantFields::query(db, self)
}
pub fn file_id(self, db: &dyn DefDatabase) -> HirFileId {
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 7aaa918d1c92a..07210df887369 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
@@ -38,16 +38,18 @@ pub struct TraitItems {
pub macro_calls: ThinVec<(AstId, MacroCallId)>,
}
+#[salsa::tracked]
impl TraitItems {
#[inline]
- pub(crate) fn trait_items_query(db: &dyn DefDatabase, tr: TraitId) -> Arc {
- db.trait_items_with_diagnostics(tr).0
+ pub(crate) fn query(db: &dyn DefDatabase, tr: TraitId) -> &TraitItems {
+ &Self::query_with_diagnostics(db, tr).0
}
- pub(crate) fn trait_items_with_diagnostics_query(
+ #[salsa::tracked(returns(ref))]
+ pub fn query_with_diagnostics(
db: &dyn DefDatabase,
tr: TraitId,
- ) -> (Arc, DefDiagnostics) {
+ ) -> (TraitItems, DefDiagnostics) {
let ItemLoc { container: module_id, id: ast_id } = tr.lookup(db);
let collector =
@@ -55,7 +57,7 @@ impl TraitItems {
let source = ast_id.with_value(collector.ast_id_map.get(ast_id.value)).to_node(db);
let (items, macro_calls, diagnostics) = collector.collect(source.assoc_item_list());
- (Arc::new(TraitItems { macro_calls, items }), DefDiagnostics::new(diagnostics))
+ (TraitItems { macro_calls, items }, DefDiagnostics::new(diagnostics))
}
pub fn associated_types(&self) -> impl Iterator- + '_ {
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 78fdc275606eb..0c3274d849ad8 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
@@ -41,6 +41,7 @@ use crate::{
macro_call_as_call_id,
nameres::{
BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs, ModuleData, ModuleOrigin, ResolveMode,
+ assoc::TraitItems,
attr_resolution::{attr_macro_as_call_id, derive_macro_as_call_id},
crate_def_map,
diagnostics::DefDiagnostic,
@@ -1020,8 +1021,7 @@ impl<'db> DefCollector<'db> {
let resolutions = if true {
vec![]
} else {
- self.db
- .trait_items(it)
+ TraitItems::query(self.db, it)
.items
.iter()
.map(|&(ref name, variant)| {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs
index e8235b1c96fe0..4641b220daadc 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs
@@ -24,8 +24,8 @@ use crate::{
item_scope::{BUILTIN_SCOPE, ImportOrExternCrate},
item_tree::FieldsShape,
nameres::{
- BlockInfo, BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs, crate_def_map,
- sub_namespace_match,
+ BlockInfo, BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs, assoc::TraitItems,
+ crate_def_map, sub_namespace_match,
},
per_ns::PerNs,
visibility::{RawVisibility, Visibility},
@@ -584,8 +584,11 @@ impl DefMap {
// now resulting in a cycle.
// To properly implement this, trait item collection needs to be done in def map
// collection...
- let item =
- if true { None } else { db.trait_items(t).assoc_item_by_name(segment) };
+ let item = if true {
+ None
+ } else {
+ TraitItems::query(db, t).assoc_item_by_name(segment)
+ };
return match item {
Some(item) => ResolvePathResult::new(
match item {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/signatures.rs b/src/tools/rust-analyzer/crates/hir-def/src/signatures.rs
index 377a545ebf4b5..1958eb6c6a18a 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/signatures.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/signatures.rs
@@ -1,6 +1,6 @@
//! Item signature IR definitions
-use std::ops::Not as _;
+use std::{cell::LazyCell, ops::Not as _};
use bitflags::bitflags;
use cfg::{CfgExpr, CfgOptions};
@@ -731,29 +731,26 @@ pub struct VariantFields {
pub store: Arc
,
pub shape: FieldsShape,
}
+
+#[salsa::tracked]
impl VariantFields {
- #[inline]
+ #[salsa::tracked(returns(clone))]
pub(crate) fn query(
db: &dyn DefDatabase,
id: VariantId,
) -> (Arc, Arc) {
- let (shape, (fields, store, source_map)) = match id {
+ let (shape, result) = match id {
VariantId::EnumVariantId(id) => {
let loc = id.lookup(db);
let parent = loc.parent.lookup(db);
let source = loc.source(db);
let shape = adt_shape(source.value.kind());
- let span_map = db.span_map(source.file_id);
- let override_visibility = visibility_from_ast(
- db,
- source.value.parent_enum().visibility(),
- &mut |range| span_map.span_for_range(range).ctx,
- );
+ let enum_vis = Some(source.value.parent_enum().visibility());
let fields = lower_field_list(
db,
parent.container,
source.map(|src| src.field_list()),
- Some(override_visibility),
+ enum_vis,
);
(shape, fields)
}
@@ -777,10 +774,29 @@ impl VariantFields {
(FieldsShape::Record, fields)
}
};
+ match result {
+ Some((fields, store, source_map)) => (
+ Arc::new(VariantFields { fields, store: Arc::new(store), shape }),
+ Arc::new(source_map),
+ ),
+ None => (
+ Arc::new(VariantFields {
+ fields: Arena::default(),
+ store: ExpressionStore::empty_singleton(),
+ shape,
+ }),
+ ExpressionStoreSourceMap::empty_singleton(),
+ ),
+ }
+ }
- (Arc::new(VariantFields { fields, store: Arc::new(store), shape }), Arc::new(source_map))
+ #[salsa::tracked(returns(deref))]
+ pub(crate) fn firewall(db: &dyn DefDatabase, id: VariantId) -> Arc {
+ Self::query(db, id).0
}
+}
+impl VariantFields {
pub fn len(&self) -> usize {
self.fields.len()
}
@@ -798,31 +814,24 @@ fn lower_field_list(
db: &dyn DefDatabase,
module: ModuleId,
fields: InFile>,
- override_visibility: Option,
-) -> (Arena, ExpressionStore, ExpressionStoreSourceMap) {
+ override_visibility: Option>,
+) -> Option<(Arena, ExpressionStore, ExpressionStoreSourceMap)> {
let file_id = fields.file_id;
- match fields.value {
- Some(ast::FieldList::RecordFieldList(fields)) => lower_fields(
+ match fields.value? {
+ ast::FieldList::RecordFieldList(fields) => lower_fields(
db,
module,
InFile::new(file_id, fields.fields().map(|field| (field.ty(), field))),
|_, field| as_name_opt(field.name()),
override_visibility,
),
- Some(ast::FieldList::TupleFieldList(fields)) => lower_fields(
+ ast::FieldList::TupleFieldList(fields) => lower_fields(
db,
module,
InFile::new(file_id, fields.fields().map(|field| (field.ty(), field))),
|idx, _| Name::new_tuple_field(idx),
override_visibility,
),
- None => lower_fields(
- db,
- module,
- InFile::new(file_id, std::iter::empty::<(Option, ast::RecordField)>()),
- |_, _| Name::missing(),
- None,
- ),
}
}
@@ -831,22 +840,34 @@ fn lower_fields(
module: ModuleId,
fields: InFile, Field)>>,
mut field_name: impl FnMut(usize, &Field) -> Name,
- override_visibility: Option,
-) -> (Arena, ExpressionStore, ExpressionStoreSourceMap) {
- let mut arena = Arena::new();
+ override_visibility: Option>,
+) -> Option<(Arena, ExpressionStore, ExpressionStoreSourceMap)> {
let cfg_options = module.krate.cfg_options(db);
let mut col = ExprCollector::new(db, module, fields.file_id);
+ let override_visibility = override_visibility.map(|vis| {
+ LazyCell::new(|| {
+ let span_map = db.span_map(fields.file_id);
+ visibility_from_ast(db, vis, &mut |range| span_map.span_for_range(range).ctx)
+ })
+ });
+
+ let mut arena = Arena::new();
let mut idx = 0;
+ let mut has_fields = false;
for (ty, field) in fields.value {
+ has_fields = true;
match Attrs::is_cfg_enabled_for(db, &field, col.span_map(), cfg_options) {
Ok(()) => {
let type_ref =
col.lower_type_ref_opt(ty, &mut ExprCollector::impl_trait_error_allocator);
- let visibility = override_visibility.clone().unwrap_or_else(|| {
- visibility_from_ast(db, field.visibility(), &mut |range| {
- col.span_map().span_for_range(range).ctx
- })
- });
+ let visibility = override_visibility.as_ref().map_or_else(
+ || {
+ visibility_from_ast(db, field.visibility(), &mut |range| {
+ col.span_map().span_for_range(range).ctx
+ })
+ },
+ |it| RawVisibility::clone(it),
+ );
let is_unsafe = field
.syntax()
.children_with_tokens()
@@ -867,9 +888,12 @@ fn lower_fields(
}
}
}
+ if !has_fields {
+ return None;
+ }
let store = col.store.finish();
arena.shrink_to_fit();
- (arena, store, col.source_map)
+ Some((arena, store, col.source_map))
}
#[derive(Debug, PartialEq, Eq)]
@@ -948,7 +972,7 @@ impl EnumVariants {
self.variants.iter().all(|&(v, _, _)| {
// The condition check order is slightly modified from rustc
// to improve performance by early returning with relatively fast checks
- let variant = &db.variant_fields(v.into());
+ let variant = v.fields(db);
if !variant.fields().is_empty() {
return false;
}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs b/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs
index 2514e88864f3f..b5eb84c25f2b6 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs
@@ -273,7 +273,7 @@ pub(crate) fn field_visibilities_query(
db: &dyn DefDatabase,
variant_id: VariantId,
) -> Arc> {
- let variant_fields = db.variant_fields(variant_id);
+ let variant_fields = variant_id.fields(db);
let fields = variant_fields.fields();
if fields.is_empty() {
return Arc::default();
diff --git a/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml b/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml
index ed818c5be3f71..80a3c08486531 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
rust-version.workspace = true
[lib]
+doctest = false
[dependencies]
cov-mark = "2.0.0"
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs
index 94c97713f0650..986f8764f5c9e 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs
@@ -433,20 +433,19 @@ fn unescape(s: &str) -> Option> {
let mut buf = String::new();
let mut prev_end = 0;
let mut has_error = false;
- unescape::unescape_unicode(s, unescape::Mode::Str, &mut |char_range, unescaped_char| match (
- unescaped_char,
- buf.capacity() == 0,
- ) {
- (Ok(c), false) => buf.push(c),
- (Ok(_), true) if char_range.len() == 1 && char_range.start == prev_end => {
- prev_end = char_range.end
- }
- (Ok(c), true) => {
- buf.reserve_exact(s.len());
- buf.push_str(&s[..prev_end]);
- buf.push(c);
+ unescape::unescape_str(s, |char_range, unescaped_char| {
+ match (unescaped_char, buf.capacity() == 0) {
+ (Ok(c), false) => buf.push(c),
+ (Ok(_), true) if char_range.len() == 1 && char_range.start == prev_end => {
+ prev_end = char_range.end
+ }
+ (Ok(c), true) => {
+ buf.reserve_exact(s.len());
+ buf.push_str(&s[..prev_end]);
+ buf.push(c);
+ }
+ (Err(_), _) => has_error = true,
}
- (Err(_), _) => has_error = true,
});
match (has_error, buf.capacity() == 0) {
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs
index 3180b8dae10e1..f9abe4f5566e7 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs
@@ -12,7 +12,7 @@ use span::{Edition, FileId, Span};
use stdx::format_to;
use syntax::{
format_smolstr,
- unescape::{Mode, unescape_byte, unescape_char, unescape_unicode},
+ unescape::{unescape_byte, unescape_char, unescape_str},
};
use syntax_bridge::syntax_node_to_token_tree;
@@ -430,7 +430,7 @@ fn compile_error_expand(
kind: tt::LitKind::Str | tt::LitKind::StrRaw(_),
suffix: _,
})),
- ] => ExpandError::other(span, Box::from(unescape_str(text).as_str())),
+ ] => ExpandError::other(span, Box::from(unescape_symbol(text).as_str())),
_ => ExpandError::other(span, "`compile_error!` argument must be a string"),
};
@@ -481,7 +481,7 @@ fn concat_expand(
format_to!(text, "{}", it.symbol.as_str())
}
tt::LitKind::Str => {
- text.push_str(unescape_str(&it.symbol).as_str());
+ text.push_str(unescape_symbol(&it.symbol).as_str());
record_span(it.span);
}
tt::LitKind::StrRaw(_) => {
@@ -691,7 +691,7 @@ fn parse_string(tt: &tt::TopSubtree) -> Result<(Symbol, Span), ExpandError> {
span,
kind: tt::LitKind::Str,
suffix: _,
- })) => Ok((unescape_str(text), *span)),
+ })) => Ok((unescape_symbol(text), *span)),
TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
symbol: text,
span,
@@ -712,7 +712,7 @@ fn parse_string(tt: &tt::TopSubtree) -> Result<(Symbol, Span), ExpandError> {
span,
kind: tt::LitKind::Str,
suffix: _,
- })) => Some((unescape_str(text), *span)),
+ })) => Some((unescape_symbol(text), *span)),
TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
symbol: text,
span,
@@ -897,11 +897,11 @@ fn quote_expand(
)
}
-fn unescape_str(s: &Symbol) -> Symbol {
+fn unescape_symbol(s: &Symbol) -> Symbol {
if s.as_str().contains('\\') {
let s = s.as_str();
let mut buf = String::with_capacity(s.len());
- unescape_unicode(s, Mode::Str, &mut |_, c| {
+ unescape_str(s, |_, c| {
if let Ok(c) = c {
buf.push(c)
}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
index 8b65126e7b749..7cc0a26d37c80 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
rust-version.workspace = true
[lib]
+doctest = false
[dependencies]
cov-mark = "2.0.0"
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs b/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs
index 7acc9456ec9cb..cc8f7bf04a5cb 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs
@@ -208,7 +208,7 @@ pub(crate) fn deref_by_trait(
};
let trait_id = trait_id()?;
let target =
- db.trait_items(trait_id).associated_type_by_name(&Name::new_symbol_root(sym::Target))?;
+ trait_id.trait_items(db).associated_type_by_name(&Name::new_symbol_root(sym::Target))?;
let projection = {
let b = TyBuilder::subst_for_def(db, trait_id, None);
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
index 79454428112ff..26b635298a651 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
@@ -315,9 +315,8 @@ impl chalk_solve::RustIrDatabase for ChalkContext<'_> {
crate::ImplTraitId::AsyncBlockTypeImplTrait(..) => {
if let Some((future_trait, future_output)) =
LangItem::Future.resolve_trait(self.db, self.krate).and_then(|trait_| {
- let alias = self
- .db
- .trait_items(trait_)
+ let alias = trait_
+ .trait_items(self.db)
.associated_type_by_name(&Name::new_symbol_root(sym::Output))?;
Some((trait_, alias))
})
@@ -711,7 +710,7 @@ pub(crate) fn trait_datum_query(
};
let where_clauses = convert_where_clauses(db, trait_.into(), &bound_vars);
let associated_ty_ids =
- db.trait_items(trait_).associated_types().map(to_assoc_type_id).collect();
+ trait_.trait_items(db).associated_types().map(to_assoc_type_id).collect();
let trait_datum_bound = rust_ir::TraitDatumBound { where_clauses };
let well_known = db.lang_attr(trait_.into()).and_then(well_known_trait_from_lang_item);
let trait_datum = TraitDatum {
@@ -802,7 +801,7 @@ pub(crate) fn adt_datum_query(
// this slows down rust-analyzer by quite a bit unfortunately, so enabling this is currently not worth it
let _variant_id_to_fields = |id: VariantId| {
- let variant_data = &id.variant_data(db);
+ let variant_data = &id.fields(db);
let fields = if variant_data.fields().is_empty() {
vec![]
} else {
@@ -879,7 +878,7 @@ fn impl_def_datum(db: &dyn HirDatabase, krate: Crate, impl_id: hir_def::ImplId)
let polarity = if negative { rust_ir::Polarity::Negative } else { rust_ir::Polarity::Positive };
let impl_datum_bound = rust_ir::ImplDatumBound { trait_ref, where_clauses };
- let trait_data = db.trait_items(trait_);
+ let trait_data = trait_.trait_items(db);
let associated_ty_value_ids = impl_id
.impl_items(db)
.items
@@ -931,8 +930,9 @@ fn type_alias_associated_ty_value(
.into_value_and_skipped_binders()
.0; // we don't return any assoc ty values if the impl'd trait can't be resolved
- let assoc_ty = db
- .trait_items(trait_ref.hir_trait_id())
+ let assoc_ty = trait_ref
+ .hir_trait_id()
+ .trait_items(db)
.associated_type_by_name(&type_alias_data.name)
.expect("assoc ty value should not exist"); // validated when building the impl data as well
let (ty, binders) = db.ty(type_alias.into()).into_value_and_skipped_binders();
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 1873f12fb7cb4..9c0f8f4008024 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
@@ -307,7 +307,7 @@ impl<'a> DeclValidator<'a> {
/// Check incorrect names for struct fields.
fn validate_struct_fields(&mut self, struct_id: StructId) {
- let data = self.db.variant_fields(struct_id.into());
+ let data = struct_id.fields(self.db);
if data.shape != FieldsShape::Record {
return;
};
@@ -468,7 +468,7 @@ impl<'a> DeclValidator<'a> {
/// Check incorrect names for fields of enum variant.
fn validate_enum_variant_fields(&mut self, variant_id: EnumVariantId) {
- let variant_data = self.db.variant_fields(variant_id.into());
+ let variant_data = variant_id.fields(self.db);
if variant_data.shape != FieldsShape::Record {
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 df2eb410b996e..5d56957be6dfb 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
@@ -494,7 +494,7 @@ impl FilterMapNextChecker {
Some(next_function_id),
match next_function_id.lookup(db).container {
ItemContainerId::TraitId(iterator_trait_id) => {
- let iterator_trait_items = &db.trait_items(iterator_trait_id).items;
+ let iterator_trait_items = &iterator_trait_id.trait_items(db).items;
iterator_trait_items.iter().find_map(|(name, it)| match it {
&AssocItemId::FunctionId(id) if *name == sym::filter_map => Some(id),
_ => None,
@@ -558,7 +558,7 @@ pub fn record_literal_missing_fields(
return None;
}
- let variant_data = variant_def.variant_data(db);
+ let variant_data = variant_def.fields(db);
let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect();
let missed_fields: Vec = variant_data
@@ -588,7 +588,7 @@ pub fn record_pattern_missing_fields(
return None;
}
- let variant_data = variant_def.variant_data(db);
+ let variant_data = variant_def.fields(db);
let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect();
let missed_fields: Vec = variant_data
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs
index 916876d4ac956..0bce32a67782f 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check.rs
@@ -169,13 +169,13 @@ impl<'a> PatCtxt<'a> {
}
hir_def::hir::Pat::TupleStruct { ref args, ellipsis, .. } if variant.is_some() => {
- let expected_len = variant.unwrap().variant_data(self.db).fields().len();
+ let expected_len = variant.unwrap().fields(self.db).fields().len();
let subpatterns = self.lower_tuple_subpats(args, expected_len, ellipsis);
self.lower_variant_or_leaf(pat, ty, subpatterns)
}
hir_def::hir::Pat::Record { ref args, .. } if variant.is_some() => {
- let variant_data = variant.unwrap().variant_data(self.db);
+ let variant_data = variant.unwrap().fields(self.db);
let subpatterns = args
.iter()
.map(|field| {
@@ -345,7 +345,7 @@ impl HirDisplay for Pat {
)?,
};
- let variant_data = variant.variant_data(f.db);
+ let variant_data = variant.fields(f.db);
if variant_data.shape == FieldsShape::Record {
write!(f, " {{ ")?;
@@ -377,7 +377,7 @@ impl HirDisplay for Pat {
}
let num_fields =
- variant.map_or(subpatterns.len(), |v| v.variant_data(f.db).fields().len());
+ variant.map_or(subpatterns.len(), |v| v.fields(f.db).fields().len());
if num_fields != 0 || variant.is_none() {
write!(f, "(")?;
let subpats = (0..num_fields).map(|i| {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
index 2873a3e09e7dc..7cf22c64d0f8e 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
@@ -6,7 +6,7 @@ use std::fmt;
use hir_def::{DefWithBodyId, EnumId, EnumVariantId, HasModule, LocalFieldId, ModuleId, VariantId};
use intern::sym;
use rustc_pattern_analysis::{
- Captures, IndexVec, PatCx, PrivateUninhabitedField,
+ IndexVec, PatCx, PrivateUninhabitedField,
constructor::{Constructor, ConstructorSet, VariantVisibility},
usefulness::{PlaceValidity, UsefulnessReport, compute_match_usefulness},
};
@@ -138,15 +138,15 @@ impl<'db> MatchCheckCtx<'db> {
}
// This lists the fields of a variant along with their types.
- fn list_variant_fields<'a>(
- &'a self,
- ty: &'a Ty,
+ fn list_variant_fields(
+ &self,
+ ty: &Ty,
variant: VariantId,
- ) -> impl Iterator- + Captures<'a> + Captures<'db> {
+ ) -> impl Iterator
- {
let (_, substs) = ty.as_adt().unwrap();
let field_tys = self.db.field_types(variant);
- let fields_len = variant.variant_data(self.db).fields().len() as u32;
+ let fields_len = variant.fields(self.db).fields().len() as u32;
(0..fields_len).map(|idx| LocalFieldId::from_raw(idx.into())).map(move |fid| {
let ty = field_tys[fid].clone().substitute(Interner, substs);
@@ -229,7 +229,7 @@ impl<'db> MatchCheckCtx<'db> {
}
};
let variant = Self::variant_id_for_adt(self.db, &ctor, adt).unwrap();
- arity = variant.variant_data(self.db).fields().len();
+ arity = variant.fields(self.db).fields().len();
}
_ => {
never!("pattern has unexpected type: pat: {:?}, ty: {:?}", pat, &pat.ty);
@@ -349,7 +349,7 @@ impl PatCx for MatchCheckCtx<'_> {
1
} else {
let variant = Self::variant_id_for_adt(self.db, ctor, adt).unwrap();
- variant.variant_data(self.db).fields().len()
+ variant.fields(self.db).fields().len()
}
}
_ => {
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 1aa7e0fcf88bf..507bab292083c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
@@ -888,7 +888,7 @@ fn render_const_scalar(
write!(f, "{}", data.name.display(f.db, f.edition()))?;
let field_types = f.db.field_types(s.into());
render_variant_after_name(
- &f.db.variant_fields(s.into()),
+ s.fields(f.db),
f,
&field_types,
f.db.trait_environment(adt.0.into()),
@@ -920,7 +920,7 @@ fn render_const_scalar(
)?;
let field_types = f.db.field_types(var_id.into());
render_variant_after_name(
- &f.db.variant_fields(var_id.into()),
+ var_id.fields(f.db),
f,
&field_types,
f.db.trait_environment(adt.0.into()),
@@ -1394,7 +1394,7 @@ impl HirDisplay for Ty {
let future_trait =
LangItem::Future.resolve_trait(db, body.module(db).krate());
let output = future_trait.and_then(|t| {
- db.trait_items(t)
+ t.trait_items(db)
.associated_type_by_name(&Name::new_symbol_root(sym::Output))
});
write!(f, "impl ")?;
@@ -2178,6 +2178,7 @@ impl HirDisplayWithExpressionStore for TypeRefId {
f.write_joined(
generic_params
.where_predicates()
+ .iter()
.filter_map(|it| match it {
WherePredicate::TypeBound { target, bound }
| WherePredicate::ForLifetime { lifetimes: _, target, bound }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
index 48094945c1144..30949c83bfae1 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
@@ -101,7 +101,7 @@ where
// rustc checks for non-lifetime binders here, but we don't support HRTB yet
- let trait_data = db.trait_items(trait_);
+ let trait_data = trait_.trait_items(db);
for (_, assoc_item) in &trait_data.items {
dyn_compatibility_violation_for_assoc_item(db, trait_, *assoc_item, cb)?;
}
@@ -164,7 +164,7 @@ fn predicates_reference_self(db: &dyn HirDatabase, trait_: TraitId) -> bool {
// Same as the above, `predicates_reference_self`
fn bounds_reference_self(db: &dyn HirDatabase, trait_: TraitId) -> bool {
- let trait_data = db.trait_items(trait_);
+ let trait_data = trait_.trait_items(db);
trait_data
.items
.iter()
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs
index a3ed39934cd8b..f14872e68c3f5 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs
@@ -60,7 +60,16 @@ impl Generics {
}
pub(crate) fn where_predicates(&self) -> impl Iterator
- {
- self.params.where_predicates()
+ self.params.where_predicates().iter()
+ }
+
+ pub(crate) fn has_no_predicates(&self) -> bool {
+ self.params.has_no_predicates()
+ && self.parent_generics.as_ref().is_none_or(|g| g.params.has_no_predicates())
+ }
+
+ pub(crate) fn is_empty(&self) -> bool {
+ self.params.is_empty() && self.parent_generics.as_ref().is_none_or(|g| g.params.is_empty())
}
pub(crate) fn iter_id(&self) -> impl Iterator
- + '_ {
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 80478f19371bb..ce53198e966f3 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
@@ -1813,7 +1813,7 @@ impl<'db> InferenceContext<'db> {
}
fn resolve_output_on(&self, trait_: TraitId) -> Option
{
- self.db.trait_items(trait_).associated_type_by_name(&Name::new_symbol_root(sym::Output))
+ trait_.trait_items(self.db).associated_type_by_name(&Name::new_symbol_root(sym::Output))
}
fn resolve_lang_trait(&self, lang: LangItem) -> Option {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs
index 8d345defdc105..4e95eca3f9402 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/cast.rs
@@ -382,7 +382,7 @@ fn pointer_kind(ty: &Ty, table: &mut InferenceTable<'_>) -> Result {}
ProjectionElem::Field(Either::Left(f)) => {
- let variant_data = f.parent.variant_data(db);
+ let variant_data = f.parent.fields(db);
match variant_data.shape {
FieldsShape::Record => {
result.push('_');
@@ -720,7 +720,7 @@ impl CapturedItem {
// In source code autoderef kicks in.
ProjectionElem::Deref => {}
ProjectionElem::Field(Either::Left(f)) => {
- let variant_data = f.parent.variant_data(db);
+ let variant_data = f.parent.fields(db);
match variant_data.shape {
FieldsShape::Record => format_to!(
result,
@@ -782,7 +782,7 @@ impl CapturedItem {
if field_need_paren {
result = format!("({result})");
}
- let variant_data = f.parent.variant_data(db);
+ let variant_data = f.parent.fields(db);
let field = match variant_data.shape {
FieldsShape::Record => {
variant_data.fields()[f.local_id].name.as_str().to_owned()
@@ -1210,9 +1210,8 @@ impl InferenceContext<'_> {
if let Some(deref_trait) =
self.resolve_lang_item(LangItem::DerefMut).and_then(|it| it.as_trait())
{
- if let Some(deref_fn) = self
- .db
- .trait_items(deref_trait)
+ if let Some(deref_fn) = deref_trait
+ .trait_items(self.db)
.method_by_name(&Name::new_symbol_root(sym::deref_mut))
{
break 'b deref_fn == f;
@@ -1560,7 +1559,7 @@ impl InferenceContext<'_> {
self.consume_place(place)
}
VariantId::StructId(s) => {
- let vd = &*self.db.variant_fields(s.into());
+ let vd = s.fields(self.db);
for field_pat in args.iter() {
let arg = field_pat.pat;
let Some(local_id) = vd.field(&field_pat.name) else {
@@ -1612,7 +1611,7 @@ impl InferenceContext<'_> {
self.consume_place(place)
}
VariantId::StructId(s) => {
- let vd = &*self.db.variant_fields(s.into());
+ let vd = s.fields(self.db);
let (al, ar) =
args.split_at(ellipsis.map_or(args.len(), |it| it as usize));
let fields = vd.fields().iter();
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 640312792963a..d40d52c134d4b 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
@@ -542,7 +542,7 @@ impl InferenceContext<'_> {
_ if fields.is_empty() => {}
Some(def) => {
let field_types = self.db.field_types(def);
- let variant_data = def.variant_data(self.db);
+ let variant_data = def.fields(self.db);
let visibilities = self.db.field_visibilities(def);
for field in fields.iter() {
let field_def = {
@@ -654,9 +654,8 @@ impl InferenceContext<'_> {
match op {
UnaryOp::Deref => {
if let Some(deref_trait) = self.resolve_lang_trait(LangItem::Deref) {
- if let Some(deref_fn) = self
- .db
- .trait_items(deref_trait)
+ if let Some(deref_fn) = deref_trait
+ .trait_items(self.db)
.method_by_name(&Name::new_symbol_root(sym::deref))
{
// FIXME: this is wrong in multiple ways, subst is empty, and we emit it even for builtin deref (note that
@@ -813,9 +812,8 @@ impl InferenceContext<'_> {
self.table.new_lifetime_var(),
));
self.write_expr_adj(*base, adj.into_boxed_slice());
- if let Some(func) = self
- .db
- .trait_items(index_trait)
+ if let Some(func) = index_trait
+ .trait_items(self.db)
.method_by_name(&Name::new_symbol_root(sym::index))
{
let subst = TyBuilder::subst_for_def(self.db, index_trait, None);
@@ -1148,7 +1146,7 @@ impl InferenceContext<'_> {
let Some(trait_) = fn_x.get_id(self.db, self.table.trait_env.krate) else {
return;
};
- let trait_data = self.db.trait_items(trait_);
+ let trait_data = trait_.trait_items(self.db);
if let Some(func) = trait_data.method_by_name(&fn_x.method_name()) {
let subst = TyBuilder::subst_for_def(self.db, trait_, None)
.push(callee_ty.clone())
@@ -1316,7 +1314,7 @@ impl InferenceContext<'_> {
let trait_func = lang_items_for_bin_op(op).and_then(|(name, lang_item)| {
let trait_id = self.resolve_lang_item(lang_item)?.as_trait()?;
- let func = self.db.trait_items(trait_id).method_by_name(&name)?;
+ let func = trait_id.trait_items(self.db).method_by_name(&name)?;
Some((trait_id, func))
});
let (trait_, func) = match trait_func {
@@ -1568,12 +1566,12 @@ impl InferenceContext<'_> {
});
}
&TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), ref parameters) => {
- let local_id = self.db.variant_fields(s.into()).field(name)?;
+ let local_id = s.fields(self.db).field(name)?;
let field = FieldId { parent: s.into(), local_id };
(field, parameters.clone())
}
&TyKind::Adt(AdtId(hir_def::AdtId::UnionId(u)), ref parameters) => {
- let local_id = self.db.variant_fields(u.into()).field(name)?;
+ let local_id = u.fields(self.db).field(name)?;
let field = FieldId { parent: u.into(), local_id };
(field, parameters.clone())
}
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 ac450c0b5591a..d2eaf2123656e 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
@@ -129,9 +129,8 @@ impl InferenceContext<'_> {
if let Some(index_trait) =
LangItem::IndexMut.resolve_trait(self.db, self.table.trait_env.krate)
{
- if let Some(index_fn) = self
- .db
- .trait_items(index_trait)
+ if let Some(index_fn) = index_trait
+ .trait_items(self.db)
.method_by_name(&Name::new_symbol_root(sym::index_mut))
{
*f = index_fn;
@@ -194,9 +193,8 @@ impl InferenceContext<'_> {
});
if is_mut_ptr {
mutability = Mutability::Not;
- } else if let Some(deref_fn) = self
- .db
- .trait_items(deref_trait)
+ } else if let Some(deref_fn) = deref_trait
+ .trait_items(self.db)
.method_by_name(&Name::new_symbol_root(sym::deref_mut))
{
*f = deref_fn;
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 4bc3e167ebf77..99d3b5c7a8414 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
@@ -38,7 +38,7 @@ impl InferenceContext<'_> {
decl: Option,
) -> Ty {
let (ty, def) = self.resolve_variant(id.into(), path, true);
- let var_data = def.map(|it| it.variant_data(self.db));
+ let var_data = def.map(|it| it.fields(self.db));
if let Some(variant) = def {
self.write_variant_resolution(id.into(), variant);
}
@@ -60,7 +60,7 @@ impl InferenceContext<'_> {
_ if subs.is_empty() => {}
Some(def) => {
let field_types = self.db.field_types(def);
- let variant_data = def.variant_data(self.db);
+ let variant_data = def.fields(self.db);
let visibilities = self.db.field_visibilities(def);
let (pre, post) = match ellipsis {
@@ -129,7 +129,7 @@ impl InferenceContext<'_> {
_ if subs.len() == 0 => {}
Some(def) => {
let field_types = self.db.field_types(def);
- let variant_data = def.variant_data(self.db);
+ let variant_data = def.fields(self.db);
let visibilities = self.db.field_visibilities(def);
let substs = ty.as_adt().map(TupleExt::tail);
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs
index c327c13b66419..bc8648ecdd943 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs
@@ -278,7 +278,7 @@ impl InferenceContext<'_> {
) -> Option<(ValueNs, Substitution)> {
let trait_ = trait_ref.hir_trait_id();
let item =
- self.db.trait_items(trait_).items.iter().map(|(_name, id)| *id).find_map(|item| {
+ trait_.trait_items(self.db).items.iter().map(|(_name, id)| *id).find_map(|item| {
match item {
AssocItemId::FunctionId(func) => {
if segment.name == &self.db.function_signature(func).name {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs
index 631b571465fe1..c07755535f2a6 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs
@@ -859,7 +859,7 @@ impl<'a> InferenceTable<'a> {
] {
let krate = self.trait_env.krate;
let fn_trait = fn_trait_name.get_id(self.db, krate)?;
- let trait_data = self.db.trait_items(fn_trait);
+ let trait_data = fn_trait.trait_items(self.db);
let output_assoc_type =
trait_data.associated_type_by_name(&Name::new_symbol_root(output_assoc_name))?;
@@ -1001,7 +1001,7 @@ impl<'a> InferenceTable<'a> {
// Must use a loop here and not recursion because otherwise users will conduct completely
// artificial examples of structs that have themselves as the tail field and complain r-a crashes.
while let Some((AdtId::StructId(id), subst)) = ty.as_adt() {
- let struct_data = self.db.variant_fields(id.into());
+ let struct_data = id.fields(self.db);
if let Some((last_field, _)) = struct_data.fields().iter().next_back() {
let last_field_ty = self.db.field_types(id.into())[last_field]
.clone()
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs b/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs
index 79a99321f1010..b16b6a1178460 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs
@@ -132,7 +132,7 @@ impl UninhabitedFrom<'_> {
variant: VariantId,
subst: &Substitution,
) -> ControlFlow {
- let variant_data = self.db.variant_fields(variant);
+ let variant_data = variant.fields(self.db);
let fields = variant_data.fields();
if fields.is_empty() {
return CONTINUE_OPAQUELY_INHABITED;
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
index c58bd1b773e23..3fa2bfbd1b761 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
@@ -375,7 +375,7 @@ pub(crate) fn layout_of_ty_cycle_result(
fn struct_tail_erasing_lifetimes(db: &dyn HirDatabase, pointee: Ty) -> Ty {
match pointee.kind(Interner) {
&TyKind::Adt(AdtId(hir_def::AdtId::StructId(i)), ref subst) => {
- let data = db.variant_fields(i.into());
+ let data = i.fields(db);
let mut it = data.fields().iter().rev();
match it.next() {
Some((f, _)) => {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs
index dff986fec3c3c..236f316366dc9 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs
@@ -42,7 +42,7 @@ pub fn layout_of_adt_query(
AdtId::StructId(s) => {
let sig = db.struct_signature(s);
let mut r = SmallVec::<[_; 1]>::new();
- r.push(handle_variant(s.into(), &db.variant_fields(s.into()))?);
+ r.push(handle_variant(s.into(), s.fields(db))?);
(
r,
sig.repr.unwrap_or_default(),
@@ -52,7 +52,7 @@ pub fn layout_of_adt_query(
AdtId::UnionId(id) => {
let data = db.union_signature(id);
let mut r = SmallVec::new();
- r.push(handle_variant(id.into(), &db.variant_fields(id.into()))?);
+ r.push(handle_variant(id.into(), id.fields(db))?);
(r, data.repr.unwrap_or_default(), false)
}
AdtId::EnumId(e) => {
@@ -60,7 +60,7 @@ pub fn layout_of_adt_query(
let r = variants
.variants
.iter()
- .map(|&(v, _, _)| handle_variant(v.into(), &db.variant_fields(v.into())))
+ .map(|&(v, _, _)| handle_variant(v.into(), v.fields(db)))
.collect::, _>>()?;
(r, db.enum_signature(e).repr.unwrap_or_default(), false)
}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
index 148f2a41e7db5..e787fd9b1e584 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
@@ -891,8 +891,8 @@ pub fn callable_sig_from_fn_trait(
) -> Option<(FnTrait, CallableSig)> {
let krate = trait_env.krate;
let fn_once_trait = FnTrait::FnOnce.get_id(db, krate)?;
- let output_assoc_type = db
- .trait_items(fn_once_trait)
+ let output_assoc_type = fn_once_trait
+ .trait_items(db)
.associated_type_by_name(&Name::new_symbol_root(sym::Output))?;
let mut table = InferenceTable::new(db, trait_env.clone());
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 0a546768dab4d..f32b6af4d8544 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
@@ -581,11 +581,28 @@ impl<'a> TyLoweringContext<'a> {
match bound {
&TypeBound::Path(path, TraitBoundModifier::None) | &TypeBound::ForLifetime(_, path) => {
// FIXME Don't silently drop the hrtb lifetimes here
- if let Some((trait_ref, ctx)) = self.lower_trait_ref_from_path(path, self_ty) {
- if !ignore_bindings {
- assoc_bounds = ctx.assoc_type_bindings_from_type_bound(trait_ref.clone());
+ if let Some((trait_ref, mut ctx)) =
+ self.lower_trait_ref_from_path(path, self_ty.clone())
+ {
+ // FIXME(sized-hierarchy): Remove this bound modifications once we have implemented
+ // sized-hierarchy correctly.
+ let meta_sized = LangItem::MetaSized
+ .resolve_trait(ctx.ty_ctx().db, ctx.ty_ctx().resolver.krate());
+ let pointee_sized = LangItem::PointeeSized
+ .resolve_trait(ctx.ty_ctx().db, ctx.ty_ctx().resolver.krate());
+ if meta_sized.is_some_and(|it| it == trait_ref.hir_trait_id()) {
+ // Ignore this bound
+ } else if pointee_sized.is_some_and(|it| it == trait_ref.hir_trait_id()) {
+ // Regard this as `?Sized` bound
+ ctx.ty_ctx().unsized_types.insert(self_ty);
+ } else {
+ if !ignore_bindings {
+ assoc_bounds =
+ ctx.assoc_type_bindings_from_type_bound(trait_ref.clone());
+ }
+ clause =
+ Some(crate::wrap_empty_binders(WhereClause::Implemented(trait_ref)));
}
- clause = Some(crate::wrap_empty_binders(WhereClause::Implemented(trait_ref)));
}
}
&TypeBound::Path(path, TraitBoundModifier::Maybe) => {
@@ -711,7 +728,7 @@ impl<'a> TyLoweringContext<'a> {
.unwrap_or(it),
None => it,
},
- None => static_lifetime(),
+ None => error_lifetime(),
},
})
.intern(Interner)
@@ -805,7 +822,7 @@ fn named_associated_type_shorthand_candidates(
) -> Option {
let mut search = |t| {
all_super_trait_refs(db, t, |t| {
- let data = db.trait_items(t.hir_trait_id());
+ let data = t.hir_trait_id().trait_items(db);
for (name, assoc_id) in &data.items {
if let AssocItemId::TypeAliasId(alias) = assoc_id {
@@ -883,7 +900,12 @@ pub(crate) fn field_types_with_diagnostics_query(
db: &dyn HirDatabase,
variant_id: VariantId,
) -> (Arc>>, Diagnostics) {
- let var_data = db.variant_fields(variant_id);
+ let var_data = variant_id.fields(db);
+ let fields = var_data.fields();
+ if fields.is_empty() {
+ return (Arc::new(ArenaMap::default()), None);
+ }
+
let (resolver, def): (_, GenericDefId) = match variant_id {
VariantId::StructId(it) => (it.resolver(db), it.into()),
VariantId::UnionId(it) => (it.resolver(db), it.into()),
@@ -899,7 +921,7 @@ pub(crate) fn field_types_with_diagnostics_query(
LifetimeElisionKind::AnonymousReportError,
)
.with_type_param_mode(ParamLoweringMode::Variable);
- for (field_id, field_data) in var_data.fields().iter() {
+ for (field_id, field_data) in fields.iter() {
res.insert(field_id, make_binders(db, &generics, ctx.lower_ty(field_data.type_ref)));
}
(Arc::new(res), create_diagnostics(ctx.diagnostics))
@@ -920,6 +942,10 @@ pub(crate) fn generic_predicates_for_param_query(
assoc_name: Option,
) -> GenericPredicates {
let generics = generics(db, def);
+ if generics.has_no_predicates() && generics.is_empty() {
+ return GenericPredicates(None);
+ }
+
let resolver = def.resolver(db);
let mut ctx = TyLoweringContext::new(
db,
@@ -936,8 +962,32 @@ pub(crate) fn generic_predicates_for_param_query(
| WherePredicate::TypeBound { target, bound, .. } => {
let invalid_target = { ctx.lower_ty_only_param(*target) != Some(param_id) };
if invalid_target {
- // If this is filtered out without lowering, `?Sized` is not gathered into `ctx.unsized_types`
- if let TypeBound::Path(_, TraitBoundModifier::Maybe) = bound {
+ // FIXME(sized-hierarchy): Revisit and adjust this properly once we have implemented
+ // sized-hierarchy correctly.
+ // If this is filtered out without lowering, `?Sized` or `PointeeSized` is not gathered into
+ // `ctx.unsized_types`
+ let lower = || -> bool {
+ match bound {
+ TypeBound::Path(_, TraitBoundModifier::Maybe) => true,
+ TypeBound::Path(path, _) | TypeBound::ForLifetime(_, path) => {
+ let TypeRef::Path(path) = &ctx.store[path.type_ref()] else {
+ return false;
+ };
+ let Some(pointee_sized) =
+ LangItem::PointeeSized.resolve_trait(ctx.db, ctx.resolver.krate())
+ else {
+ return false;
+ };
+ // Lower the path directly with `Resolver` instead of PathLoweringContext`
+ // to prevent diagnostics duplications.
+ ctx.resolver.resolve_path_in_type_ns_fully(ctx.db, path).is_some_and(
+ |it| matches!(it, TypeNs::TraitId(tr) if tr == pointee_sized),
+ )
+ }
+ _ => false,
+ }
+ }();
+ if lower {
ctx.lower_where_predicate(pred, true).for_each(drop);
}
return false;
@@ -957,7 +1007,7 @@ pub(crate) fn generic_predicates_for_param_query(
};
all_super_traits(db, tr).iter().any(|tr| {
- db.trait_items(*tr).items.iter().any(|(name, item)| {
+ tr.trait_items(db).items.iter().any(|(name, item)| {
matches!(item, AssocItemId::TypeAliasId(_)) && name == assoc_name
})
})
@@ -1025,6 +1075,10 @@ pub(crate) fn trait_environment_query(
def: GenericDefId,
) -> Arc {
let generics = generics(db, def);
+ if generics.has_no_predicates() && generics.is_empty() {
+ return TraitEnvironment::empty(def.krate(db));
+ }
+
let resolver = def.resolver(db);
let mut ctx = TyLoweringContext::new(
db,
@@ -1128,6 +1182,10 @@ where
F: Fn(&WherePredicate, GenericDefId) -> bool,
{
let generics = generics(db, def);
+ if generics.has_no_predicates() && generics.is_empty() {
+ return (GenericPredicates(None), None);
+ }
+
let resolver = def.resolver(db);
let mut ctx = TyLoweringContext::new(
db,
@@ -1154,7 +1212,7 @@ where
}
}
- if generics.len() > 0 {
+ if !generics.is_empty() {
let subst = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
let explicitly_unsized_tys = ctx.unsized_types;
if let Some(implicitly_sized_predicates) =
@@ -1229,7 +1287,7 @@ pub(crate) fn generic_defaults_with_diagnostics_query(
def: GenericDefId,
) -> (GenericDefaults, Diagnostics) {
let generic_params = generics(db, def);
- if generic_params.len() == 0 {
+ if generic_params.is_empty() {
return (GenericDefaults(None), None);
}
let resolver = def.resolver(db);
@@ -1418,7 +1476,7 @@ fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnS
/// Build the type of a tuple struct constructor.
fn type_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> Option> {
- let struct_data = db.variant_fields(def.into());
+ let struct_data = def.fields(db);
match struct_data.shape {
FieldsShape::Record => None,
FieldsShape::Unit => Some(type_for_adt(db, def.into())),
@@ -1451,7 +1509,7 @@ fn type_for_enum_variant_constructor(
def: EnumVariantId,
) -> Option> {
let e = def.lookup(db).parent;
- match db.variant_fields(def.into()).shape {
+ match def.fields(db).shape {
FieldsShape::Record => None,
FieldsShape::Unit => Some(type_for_adt(db, e.into())),
FieldsShape::Tuple => {
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 726eaf8b0a1dc..06686b6a164cd 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
@@ -173,7 +173,7 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
self.skip_resolved_segment();
let segment = self.current_or_prev_segment;
let found =
- self.ctx.db.trait_items(trait_).associated_type_by_name(segment.name);
+ trait_.trait_items(self.ctx.db).associated_type_by_name(segment.name);
match found {
Some(associated_ty) => {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
index 25f1782bdd870..a6150a9bc1728 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
@@ -1302,7 +1302,7 @@ fn iterate_trait_method_candidates(
// trait, but if we find out it doesn't, we'll skip the rest of the
// iteration
let mut known_implemented = false;
- for &(_, item) in db.trait_items(t).items.iter() {
+ for &(_, item) in t.trait_items(db).items.iter() {
// Don't pass a `visible_from_module` down to `is_valid_candidate`,
// since only inherent methods should be included into visibility checking.
let visible =
@@ -1429,7 +1429,7 @@ fn iterate_inherent_methods(
) -> ControlFlow<()> {
let db = table.db;
for t in traits {
- let data = db.trait_items(t);
+ let data = t.trait_items(db);
for &(_, item) in data.items.iter() {
// We don't pass `visible_from_module` as all trait items should be visible.
let visible = match is_valid_trait_method_candidate(
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 a8156ec375bcf..1ec55a8209280 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
@@ -657,12 +657,12 @@ impl Evaluator<'_> {
cached_ptr_size,
cached_fn_trait_func: LangItem::Fn
.resolve_trait(db, crate_id)
- .and_then(|x| db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call))),
+ .and_then(|x| x.trait_items(db).method_by_name(&Name::new_symbol_root(sym::call))),
cached_fn_mut_trait_func: LangItem::FnMut.resolve_trait(db, crate_id).and_then(|x| {
- db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call_mut))
+ x.trait_items(db).method_by_name(&Name::new_symbol_root(sym::call_mut))
}),
cached_fn_once_trait_func: LangItem::FnOnce.resolve_trait(db, crate_id).and_then(|x| {
- db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call_once))
+ x.trait_items(db).method_by_name(&Name::new_symbol_root(sym::call_once))
}),
})
}
@@ -1749,8 +1749,7 @@ impl Evaluator<'_> {
AdtId::UnionId(_) => not_supported!("unsizing unions"),
AdtId::EnumId(_) => not_supported!("unsizing enums"),
};
- let Some((last_field, _)) =
- self.db.variant_fields(id.into()).fields().iter().next_back()
+ let Some((last_field, _)) = id.fields(self.db).fields().iter().next_back()
else {
not_supported!("unsizing struct without field");
};
@@ -2232,7 +2231,7 @@ impl Evaluator<'_> {
}
chalk_ir::TyKind::Adt(adt, subst) => match adt.0 {
AdtId::StructId(s) => {
- let data = this.db.variant_fields(s.into());
+ let data = s.fields(this.db);
let layout = this.layout(ty)?;
let field_types = this.db.field_types(s.into());
for (f, _) in data.fields().iter() {
@@ -2261,7 +2260,7 @@ impl Evaluator<'_> {
bytes,
e,
) {
- let data = &this.db.variant_fields(v.into());
+ let data = v.fields(this.db);
let field_types = this.db.field_types(v.into());
for (f, _) in data.fields().iter() {
let offset =
@@ -2808,7 +2807,7 @@ impl Evaluator<'_> {
) -> Result<()> {
let Some(drop_fn) = (|| {
let drop_trait = LangItem::Drop.resolve_trait(self.db, self.crate_id)?;
- self.db.trait_items(drop_trait).method_by_name(&Name::new_symbol_root(sym::drop))
+ drop_trait.trait_items(self.db).method_by_name(&Name::new_symbol_root(sym::drop))
})() else {
// in some tests we don't have drop trait in minicore, and
// we can ignore drop in them.
@@ -2838,7 +2837,7 @@ impl Evaluator<'_> {
return Ok(());
}
let layout = self.layout_adt(id.0, subst.clone())?;
- let variant_fields = self.db.variant_fields(s.into());
+ let variant_fields = s.fields(self.db);
match variant_fields.shape {
FieldsShape::Record | FieldsShape::Tuple => {
let field_types = self.db.field_types(s.into());
@@ -2918,7 +2917,7 @@ pub fn render_const_using_debug_impl(
not_supported!("core::fmt::Debug not found");
};
let Some(debug_fmt_fn) =
- db.trait_items(debug_trait).method_by_name(&Name::new_symbol_root(sym::fmt))
+ debug_trait.trait_items(db).method_by_name(&Name::new_symbol_root(sym::fmt))
else {
not_supported!("core::fmt::Debug::fmt not found");
};
@@ -3045,7 +3044,10 @@ impl IntValue {
(8, true) => Self::I64(i64::from_le_bytes(bytes.try_into().unwrap())),
(16, false) => Self::U128(u128::from_le_bytes(bytes.try_into().unwrap())),
(16, true) => Self::I128(i128::from_le_bytes(bytes.try_into().unwrap())),
- _ => panic!("invalid integer size"),
+ (len, is_signed) => {
+ never!("invalid integer size: {len}, signed: {is_signed}");
+ Self::I32(0)
+ }
}
}
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 6ebde0133444e..e9665d5ae9cf1 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
@@ -1257,9 +1257,8 @@ impl Evaluator<'_> {
args.push(IntervalAndTy::new(addr, field, self, locals)?);
}
if let Some(target) = LangItem::FnOnce.resolve_trait(self.db, self.crate_id) {
- if let Some(def) = self
- .db
- .trait_items(target)
+ if let Some(def) = target
+ .trait_items(self.db)
.method_by_name(&Name::new_symbol_root(sym::call_once))
{
self.exec_fn_trait(
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs
index 984648cfec328..bc331a23d98e3 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim/simd.rs
@@ -31,7 +31,7 @@ impl Evaluator<'_> {
Some(len) => len,
_ => {
if let AdtId::StructId(id) = id.0 {
- let struct_data = self.db.variant_fields(id.into());
+ let struct_data = id.fields(self.db);
let fields = struct_data.fields();
let Some((first_field, _)) = fields.iter().next() else {
not_supported!("simd type with no field");
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 3abbbe45e6f87..c1f86960e154c 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
@@ -984,3 +984,17 @@ fn main<'a, T: Foo + Bar + Baz>(
|e| matches!(e, MirEvalError::MirLowerError(_, MirLowerError::GenericArgNotProvided(..))),
);
}
+
+#[test]
+fn format_args_pass() {
+ check_pass(
+ r#"
+//- minicore: fmt
+fn main() {
+ let x1 = format_args!("");
+ let x2 = format_args!("{}", x1);
+ let x3 = format_args!("{} {}", x1, x2);
+}
+"#,
+ );
+}
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 71e038b92f085..845d6b8eae1e4 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
@@ -503,7 +503,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
Ok(Some(current))
}
ValueNs::EnumVariantId(variant_id) => {
- let variant_fields = &self.db.variant_fields(variant_id.into());
+ let variant_fields = variant_id.fields(self.db);
if variant_fields.shape == FieldsShape::Unit {
let ty = self.infer.type_of_expr[expr_id].clone();
current = self.lower_enum_variant(
@@ -856,7 +856,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
TyKind::Adt(_, s) => s.clone(),
_ => not_supported!("Non ADT record literal"),
};
- let variant_fields = self.db.variant_fields(variant_id);
+ let variant_fields = variant_id.fields(self.db);
match variant_id {
VariantId::EnumVariantId(_) | VariantId::StructId(_) => {
let mut operands = vec![None; variant_fields.fields().len()];
@@ -1176,8 +1176,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
place,
Rvalue::Aggregate(
AggregateKind::Adt(st.into(), subst.clone()),
- self.db
- .variant_fields(st.into())
+ st.fields(self.db)
.fields()
.iter()
.map(|it| {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs
index ad664693e29f7..e7bffead93122 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs
@@ -193,9 +193,8 @@ impl MirLowerCtx<'_> {
if let Some(deref_trait) =
self.resolve_lang_item(LangItem::DerefMut)?.as_trait()
{
- if let Some(deref_fn) = self
- .db
- .trait_items(deref_trait)
+ if let Some(deref_fn) = deref_trait
+ .trait_items(self.db)
.method_by_name(&Name::new_symbol_root(sym::deref_mut))
{
break 'b deref_fn == f;
@@ -347,9 +346,8 @@ impl MirLowerCtx<'_> {
.resolve_lang_item(trait_lang_item)?
.as_trait()
.ok_or(MirLowerError::LangItemNotFound(trait_lang_item))?;
- let deref_fn = self
- .db
- .trait_items(deref_trait)
+ let deref_fn = deref_trait
+ .trait_items(self.db)
.method_by_name(&trait_method_name)
.ok_or(MirLowerError::LangItemNotFound(trait_lang_item))?;
let deref_fn_op = Operand::const_zst(
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 b3c1f6f387f22..61c0685c48a2e 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
@@ -609,7 +609,7 @@ impl MirLowerCtx<'_> {
}
self.pattern_matching_variant_fields(
shape,
- &self.db.variant_fields(v.into()),
+ v.fields(self.db),
variant,
current,
current_else,
@@ -619,7 +619,7 @@ impl MirLowerCtx<'_> {
}
VariantId::StructId(s) => self.pattern_matching_variant_fields(
shape,
- &self.db.variant_fields(s.into()),
+ s.fields(self.db),
variant,
current,
current_else,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs
index 8764e48b53840..78a69cf450916 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/pretty.rs
@@ -326,7 +326,7 @@ impl<'a> MirPrettyCtx<'a> {
w!(this, ")");
}
ProjectionElem::Field(Either::Left(field)) => {
- let variant_fields = this.db.variant_fields(field.parent);
+ let variant_fields = field.parent.fields(this.db);
let name = &variant_fields.fields()[field.local_id].name;
match field.parent {
hir_def::VariantId::EnumVariantId(e) => {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs
index 9ca6ee476c653..79754bc8a09b7 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs
@@ -486,7 +486,7 @@ pub(crate) fn visit_module(
});
}
ModuleDefId::TraitId(it) => {
- let trait_data = db.trait_items(it);
+ let trait_data = it.trait_items(db);
for &(_, item) in trait_data.items.iter() {
match item {
AssocItemId::FunctionId(it) => cb(it.into()),
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs
index ddc5b715194df..3894b4b6f7bad 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs
@@ -561,7 +561,7 @@ trait Foo {}
fn test(f: impl Foo, g: &(impl Foo + ?Sized)) {
let _: &dyn Foo = &f;
let _: &dyn Foo = g;
- //^ expected &'? (dyn Foo + 'static), got &'? impl Foo + ?Sized
+ //^ expected &'? (dyn Foo + '?), got &'? impl Foo + ?Sized
}
"#,
);
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/display_source_code.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/display_source_code.rs
index a986b54a7b064..6e3faa05a629b 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/display_source_code.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/display_source_code.rs
@@ -67,11 +67,11 @@ trait B: A {}
fn test<'a>(
_: &(dyn A + Send),
- //^ &(dyn A + Send + 'static)
+ //^ &(dyn A + Send)
_: &'a (dyn Send + A),
- //^ &'a (dyn A + Send + 'static)
+ //^ &'a (dyn A + Send)
_: &dyn B,
- //^ &(dyn B + 'static)
+ //^ &(dyn B)
) {}
"#,
);
@@ -85,7 +85,7 @@ fn render_dyn_for_ty() {
trait Foo<'a> {}
fn foo(foo: &dyn for<'a> Foo<'a>) {}
- // ^^^ &(dyn Foo<'?> + 'static)
+ // ^^^ &dyn Foo<'?>
"#,
);
}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs
index 905fd8a3bca09..0377ce95f190c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs
@@ -567,7 +567,7 @@ fn main() {
"ast_id_map_shim",
"parse_shim",
"real_span_map_shim",
- "trait_items_with_diagnostics_shim",
+ "query_with_diagnostics_",
"body_shim",
"body_with_source_map_shim",
"attrs_shim",
@@ -596,8 +596,8 @@ fn main() {
"struct_signature_with_source_map_shim",
"generic_predicates_shim",
"value_ty_shim",
- "variant_fields_shim",
- "variant_fields_with_source_map_shim",
+ "firewall_",
+ "query_",
"lang_item",
"inherent_impls_in_crate_shim",
"impl_signature_shim",
@@ -674,7 +674,7 @@ fn main() {
"file_item_tree_query",
"real_span_map_shim",
"crate_local_def_map",
- "trait_items_with_diagnostics_shim",
+ "query_with_diagnostics_",
"body_with_source_map_shim",
"attrs_shim",
"body_shim",
@@ -695,11 +695,9 @@ fn main() {
"return_type_impl_traits_shim",
"infer_shim",
"function_signature_with_source_map_shim",
- "trait_environment_shim",
"expr_scopes_shim",
"struct_signature_with_source_map_shim",
- "generic_predicates_shim",
- "variant_fields_with_source_map_shim",
+ "query_",
"inherent_impls_in_crate_shim",
"impl_signature_with_source_map_shim",
"impl_signature_shim",
@@ -709,7 +707,6 @@ fn main() {
"impl_trait_with_diagnostics_shim",
"impl_self_ty_with_diagnostics_shim",
"generic_predicates_shim",
- "generic_predicates_shim",
]
"#]],
);
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs
index 94826acca305f..c58ca6c67a8de 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs
@@ -1153,9 +1153,9 @@ fn dyn_trait_super_trait_not_in_scope() {
51..55 'self': &'? Self
64..69 '{ 0 }': u32
66..67 '0': u32
- 176..177 'd': &'? (dyn Trait + 'static)
+ 176..177 'd': &'? (dyn Trait + '?)
191..207 '{ ...o(); }': ()
- 197..198 'd': &'? (dyn Trait + 'static)
+ 197..198 'd': &'? (dyn Trait + '?)
197..204 'd.foo()': u32
"#]],
);
@@ -2019,10 +2019,10 @@ impl dyn Error + Send {
/// Attempts to downcast the box to a concrete type.
pub fn downcast(self: Box) -> Result, Box> {
let err: Box = self;
- // ^^^^ expected Box, got Box
+ // ^^^^ expected Box, got Box
// FIXME, type mismatch should not occur
::downcast(err).map_err(|_| loop {})
- //^^^^^^^^^^^^^^^^^^^^^ type: fn downcast<{unknown}>(Box) -> Result, Box>
+ //^^^^^^^^^^^^^^^^^^^^^ type: fn downcast<{unknown}>(Box) -> Result, Box>
}
}
"#,
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 ff8adeef1dbee..238753e12e4f2 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
@@ -629,7 +629,7 @@ fn issue_4053_diesel_where_clauses() {
488..522 '{ ... }': ()
498..502 'self': SelectStatement
498..508 'self.order': O
- 498..515 'self.o...into()': dyn QueryFragment + 'static
+ 498..515 'self.o...into()': dyn QueryFragment + '?
"#]],
);
}
@@ -773,7 +773,7 @@ fn issue_4800() {
"#,
expect![[r#"
379..383 'self': &'? mut PeerSet
- 401..424 '{ ... }': dyn Future + 'static
+ 401..424 '{ ... }': dyn Future + '?
411..418 'loop {}': !
416..418 '{}': ()
575..579 'self': &'? mut Self
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs
index cf51671afb2be..43e8f3747ab8c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs
@@ -2741,11 +2741,11 @@ impl B for Astruct {}
715..744 '#[rust...1i32])': Box<[i32; 1], Global>
737..743 '[1i32]': [i32; 1]
738..742 '1i32': i32
- 755..756 'v': Vec, Global>
- 776..793 '<[_]> ...to_vec': fn into_vec, Global>(Box<[Box], Global>) -> Vec, Global>
- 776..850 '<[_]> ...ct)]))': Vec, Global>
- 794..849 '#[rust...uct)])': Box<[Box; 1], Global>
- 816..848 '[#[rus...ruct)]': [Box; 1]
+ 755..756 'v': Vec, Global>
+ 776..793 '<[_]> ...to_vec': fn into_vec, Global>(Box<[Box], Global>) -> Vec, Global>
+ 776..850 '<[_]> ...ct)]))': Vec, Global>
+ 794..849 '#[rust...uct)])': Box<[Box; 1], Global>
+ 816..848 '[#[rus...ruct)]': [Box; 1]
817..847 '#[rust...truct)': Box
839..846 'Astruct': Astruct
"#]],
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
index e5d1fbe9defee..56e31a1af1b9c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
@@ -1475,26 +1475,26 @@ fn test(x: Box>, y: &dyn Trait) {
expect![[r#"
29..33 'self': &'? Self
54..58 'self': &'? Self
- 198..200 '{}': Box + 'static>
- 210..211 'x': Box + 'static>
- 234..235 'y': &'? (dyn Trait + 'static)
+ 198..200 '{}': Box + '?>
+ 210..211 'x': Box + '?>
+ 234..235 'y': &'? (dyn Trait + '?)
254..371 '{ ...2(); }': ()
- 260..261 'x': Box + 'static>
- 267..268 'y': &'? (dyn Trait + 'static)
- 278..279 'z': Box + 'static>
- 282..285 'bar': fn bar() -> Box + 'static>
- 282..287 'bar()': Box + 'static>
- 293..294 'x': Box + 'static>
+ 260..261 'x': Box + '?>
+ 267..268 'y': &'? (dyn Trait + '?)
+ 278..279 'z': Box + '?>
+ 282..285 'bar': fn bar() -> Box + '?>
+ 282..287 'bar()': Box + '?>
+ 293..294 'x': Box + '?>
293..300 'x.foo()': u64
- 306..307 'y': &'? (dyn Trait + 'static)
+ 306..307 'y': &'? (dyn Trait + '?)
306..313 'y.foo()': u64
- 319..320 'z': Box + 'static>
+ 319..320 'z': Box + '?>
319..326 'z.foo()': u64
- 332..333 'x': Box + 'static>
+ 332..333 'x': Box + '?>
332..340 'x.foo2()': i64
- 346..347 'y': &'? (dyn Trait + 'static)
+ 346..347 'y': &'? (dyn Trait + '?)
346..354 'y.foo2()': i64
- 360..361 'z': Box + 'static>
+ 360..361 'z': Box + '?>
360..368 'z.foo2()': i64
"#]],
);
@@ -1523,14 +1523,14 @@ fn test(s: S) {
expect![[r#"
32..36 'self': &'? Self
102..106 'self': &'? S
- 128..139 '{ loop {} }': &'? (dyn Trait + 'static)
+ 128..139 '{ loop {} }': &'? (dyn Trait + '?)
130..137 'loop {}': !
135..137 '{}': ()
175..179 'self': &'? Self
251..252 's': S
267..289 '{ ...z(); }': ()
273..274 's': S
- 273..280 's.bar()': &'? (dyn Trait + 'static)
+ 273..280 's.bar()': &'? (dyn Trait + '?)
273..286 's.bar().baz()': (u32, i32)
"#]],
);
@@ -1556,20 +1556,20 @@ fn test(x: Trait, y: &Trait) -> u64 {
}"#,
expect![[r#"
26..30 'self': &'? Self
- 60..62 '{}': dyn Trait + 'static
- 72..73 'x': dyn Trait + 'static
- 82..83 'y': &'? (dyn Trait + 'static)
+ 60..62 '{}': dyn Trait + '?
+ 72..73 'x': dyn Trait + '?
+ 82..83 'y': &'? (dyn Trait + '?)
100..175 '{ ...o(); }': u64
- 106..107 'x': dyn Trait + 'static
- 113..114 'y': &'? (dyn Trait + 'static)
- 124..125 'z': dyn Trait + 'static
- 128..131 'bar': fn bar() -> dyn Trait + 'static
- 128..133 'bar()': dyn Trait + 'static
- 139..140 'x': dyn Trait + 'static
+ 106..107 'x': dyn Trait + '?
+ 113..114 'y': &'? (dyn Trait + '?)
+ 124..125 'z': dyn Trait + '?
+ 128..131 'bar': fn bar() -> dyn Trait + '?
+ 128..133 'bar()': dyn Trait + '?
+ 139..140 'x': dyn Trait + '?
139..146 'x.foo()': u64
- 152..153 'y': &'? (dyn Trait + 'static)
+ 152..153 'y': &'? (dyn Trait + '?)
152..159 'y.foo()': u64
- 165..166 'z': dyn Trait + 'static
+ 165..166 'z': dyn Trait + '?
165..172 'z.foo()': u64
"#]],
);
@@ -1589,10 +1589,10 @@ fn main() {
expect![[r#"
31..35 'self': &'? S
37..39 '{}': ()
- 47..48 '_': &'? (dyn Fn(S) + 'static)
+ 47..48 '_': &'? (dyn Fn(S) + '?)
58..60 '{}': ()
71..105 '{ ...()); }': ()
- 77..78 'f': fn f(&'? (dyn Fn(S) + 'static))
+ 77..78 'f': fn f(&'? (dyn Fn(S) + '?))
77..102 'f(&|nu...foo())': ()
79..101 '&|numb....foo()': &'? impl Fn(S)
80..101 '|numbe....foo()': impl Fn(S)
@@ -2927,13 +2927,13 @@ fn test(x: &dyn Foo) {
foo(x);
}"#,
expect![[r#"
- 21..22 'x': &'? (dyn Foo + 'static)
+ 21..22 'x': &'? (dyn Foo + '?)
34..36 '{}': ()
- 46..47 'x': &'? (dyn Foo + 'static)
+ 46..47 'x': &'? (dyn Foo + '?)
59..74 '{ foo(x); }': ()
- 65..68 'foo': fn foo(&'? (dyn Foo + 'static))
+ 65..68 'foo': fn foo(&'? (dyn Foo + '?))
65..71 'foo(x)': ()
- 69..70 'x': &'? (dyn Foo + 'static)
+ 69..70 'x': &'? (dyn Foo + '?)
"#]],
);
}
@@ -3210,13 +3210,13 @@ fn foo() {
218..324 '{ ...&s); }': ()
228..229 's': Option
232..236 'None': Option
- 246..247 'f': Box) + 'static>
- 281..310 'Box { ... {}) }': Box) + 'static>
+ 246..247 'f': Box) + '?>
+ 281..310 'Box { ... {}) }': Box) + '?>
294..308 '&mut (|ps| {})': &'? mut impl FnOnce(&'? Option)
300..307 '|ps| {}': impl FnOnce(&'? Option)
301..303 'ps': &'? Option
305..307 '{}': ()
- 316..317 'f': Box) + 'static>
+ 316..317 'f': Box) + '?>
316..321 'f(&s)': ()
318..320 '&s': &'? Option
319..320 's': Option
@@ -4252,9 +4252,9 @@ fn f<'a>(v: &dyn Trait = &'a i32>) {
"#,
expect![[r#"
90..94 'self': &'? Self
- 127..128 'v': &'? (dyn Trait = &'a i32> + 'static)
+ 127..128 'v': &'? (dyn Trait = &'a i32> + '?)
164..195 '{ ...f(); }': ()
- 170..171 'v': &'? (dyn Trait = &'a i32> + 'static)
+ 170..171 'v': &'? (dyn Trait = &'a i32> + '?)
170..184 'v.get::()': &'? i32
170..192 'v.get:...eref()': &'? i32
"#]],
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
index 4c8e635eff986..d07c1aa33b407 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
@@ -1,7 +1,7 @@
//! Helper functions for working with def, which don't need to be a separate
//! query, but can't be computed directly from `*Data` (ie, which need a `db`).
-use std::iter;
+use std::{cell::LazyCell, iter};
use base_db::Crate;
use chalk_ir::{
@@ -161,11 +161,12 @@ impl Iterator for ClauseElaborator<'_> {
}
fn direct_super_traits_cb(db: &dyn DefDatabase, trait_: TraitId, cb: impl FnMut(TraitId)) {
- let resolver = trait_.resolver(db);
+ let resolver = LazyCell::new(|| trait_.resolver(db));
let (generic_params, store) = db.generic_params_and_store(trait_.into());
let trait_self = generic_params.trait_self_param();
generic_params
.where_predicates()
+ .iter()
.filter_map(|pred| match pred {
WherePredicate::ForLifetime { target, bound, .. }
| WherePredicate::TypeBound { target, bound } => {
@@ -218,7 +219,7 @@ pub(super) fn associated_type_by_name_including_super_traits(
name: &Name,
) -> Option<(TraitRef, TypeAliasId)> {
all_super_trait_refs(db, trait_ref, |t| {
- let assoc_type = db.trait_items(t.hir_trait_id()).associated_type_by_name(name)?;
+ let assoc_type = t.hir_trait_id().trait_items(db).associated_type_by_name(name)?;
Some((t, assoc_type))
})
}
diff --git a/src/tools/rust-analyzer/crates/hir/Cargo.toml b/src/tools/rust-analyzer/crates/hir/Cargo.toml
index 2af3c2e4c3515..c68ff706e4814 100644
--- a/src/tools/rust-analyzer/crates/hir/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
rust-version.workspace = true
[lib]
+doctest = false
[dependencies]
rustc-hash.workspace = true
diff --git a/src/tools/rust-analyzer/crates/hir/src/attrs.rs b/src/tools/rust-analyzer/crates/hir/src/attrs.rs
index 0bce69a179b8c..c8645b6282392 100644
--- a/src/tools/rust-analyzer/crates/hir/src/attrs.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/attrs.rs
@@ -207,7 +207,7 @@ fn resolve_assoc_or_field(
// Doc paths in this context may only resolve to an item of this trait
// (i.e. no items of its supertraits), so we need to handle them here
// independently of others.
- return db.trait_items(id).items.iter().find(|it| it.0 == name).map(|(_, assoc_id)| {
+ return id.trait_items(db).items.iter().find(|it| it.0 == name).map(|(_, assoc_id)| {
let def = match *assoc_id {
AssocItemId::FunctionId(it) => ModuleDef::Function(it.into()),
AssocItemId::ConstId(it) => ModuleDef::Const(it.into()),
diff --git a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs
index 074bde91fb690..aba2e032b320e 100644
--- a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs
@@ -490,7 +490,7 @@ impl<'db> AnyDiagnostic<'db> {
) -> Option> {
match diagnostic {
BodyValidationDiagnostic::RecordMissingFields { record, variant, missed_fields } => {
- let variant_data = variant.variant_data(db);
+ let variant_data = variant.fields(db);
let missed_fields = missed_fields
.into_iter()
.map(|idx| variant_data.fields()[idx].name.clone())
diff --git a/src/tools/rust-analyzer/crates/hir/src/display.rs b/src/tools/rust-analyzer/crates/hir/src/display.rs
index 112558bdd04a8..2960ebedf3806 100644
--- a/src/tools/rust-analyzer/crates/hir/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/display.rs
@@ -404,7 +404,7 @@ impl HirDisplay for TupleField {
impl HirDisplay for Variant {
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
write!(f, "{}", self.name(f.db).display(f.db, f.edition()))?;
- let data = f.db.variant_fields(self.id.into());
+ let data = self.id.fields(f.db);
match data.shape {
FieldsShape::Unit => {}
FieldsShape::Tuple => {
@@ -633,7 +633,7 @@ fn has_disaplayable_predicates(
params: &GenericParams,
store: &ExpressionStore,
) -> bool {
- params.where_predicates().any(|pred| {
+ params.where_predicates().iter().any(|pred| {
!matches!(
pred,
WherePredicate::TypeBound { target, .. }
@@ -668,7 +668,7 @@ fn write_where_predicates(
_ => false,
};
- let mut iter = params.where_predicates().peekable();
+ let mut iter = params.where_predicates().iter().peekable();
while let Some(pred) = iter.next() {
if matches!(pred, TypeBound { target, .. } if is_unnamed_type_target(*target)) {
continue;
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index 3b39707cf6094..e8a18169712cb 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -54,7 +54,7 @@ use hir_def::{
},
item_tree::ImportAlias,
layout::{self, ReprOptions, TargetDataLayout},
- nameres::{self, diagnostics::DefDiagnostic},
+ nameres::{self, assoc::TraitItems, diagnostics::DefDiagnostic},
per_ns::PerNs,
resolver::{HasResolver, Resolver},
signatures::{ImplFlags, StaticFlags, TraitFlags, VariantFields},
@@ -649,7 +649,7 @@ impl Module {
acc.extend(def.diagnostics(db, style_lints))
}
ModuleDef::Trait(t) => {
- for diag in db.trait_items_with_diagnostics(t.id).1.iter() {
+ for diag in TraitItems::query_with_diagnostics(db, t.id).1.iter() {
emit_def_diagnostic(db, acc, diag, edition);
}
@@ -668,25 +668,25 @@ impl Module {
Adt::Struct(s) => {
let source_map = db.struct_signature_with_source_map(s.id).1;
expr_store_diagnostics(db, acc, &source_map);
- let source_map = db.variant_fields_with_source_map(s.id.into()).1;
- expr_store_diagnostics(db, acc, &source_map);
+ let source_map = &s.id.fields_with_source_map(db).1;
+ expr_store_diagnostics(db, acc, source_map);
push_ty_diagnostics(
db,
acc,
db.field_types_with_diagnostics(s.id.into()).1,
- &source_map,
+ source_map,
);
}
Adt::Union(u) => {
let source_map = db.union_signature_with_source_map(u.id).1;
expr_store_diagnostics(db, acc, &source_map);
- let source_map = db.variant_fields_with_source_map(u.id.into()).1;
- expr_store_diagnostics(db, acc, &source_map);
+ let source_map = &u.id.fields_with_source_map(db).1;
+ expr_store_diagnostics(db, acc, source_map);
push_ty_diagnostics(
db,
acc,
db.field_types_with_diagnostics(u.id.into()).1,
- &source_map,
+ source_map,
);
}
Adt::Enum(e) => {
@@ -711,14 +711,14 @@ impl Module {
}
}
for &(v, _, _) in &variants.variants {
- let source_map = db.variant_fields_with_source_map(v.into()).1;
+ let source_map = &v.fields_with_source_map(db).1;
push_ty_diagnostics(
db,
acc,
db.field_types_with_diagnostics(v.into()).1,
- &source_map,
+ source_map,
);
- expr_store_diagnostics(db, acc, &source_map);
+ expr_store_diagnostics(db, acc, source_map);
}
}
}
@@ -822,7 +822,7 @@ impl Module {
// Negative impls can't have items, don't emit missing items diagnostic for them
if let (false, Some(trait_)) = (impl_is_negative, trait_) {
- let items = &db.trait_items(trait_.into()).items;
+ let items = &trait_.id.trait_items(db).items;
let required_items = items.iter().filter(|&(_, assoc)| match *assoc {
AssocItemId::FunctionId(it) => !db.function_signature(it).has_body(),
AssocItemId::ConstId(id) => !db.const_signature(id).has_body(),
@@ -1311,7 +1311,7 @@ impl AstNode for FieldSource {
impl Field {
pub fn name(&self, db: &dyn HirDatabase) -> Name {
- db.variant_fields(self.parent.into()).fields()[self.id].name.clone()
+ VariantId::from(self.parent).fields(db).fields()[self.id].name.clone()
}
pub fn index(&self) -> usize {
@@ -1380,7 +1380,7 @@ impl Field {
impl HasVisibility for Field {
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
- let variant_data = db.variant_fields(self.parent.into());
+ let variant_data = VariantId::from(self.parent).fields(db);
let visibility = &variant_data.fields()[self.id].visibility;
let parent_id: hir_def::VariantId = self.parent.into();
// FIXME: RawVisibility::Public doesn't need to construct a resolver
@@ -1403,7 +1403,8 @@ impl Struct {
}
pub fn fields(self, db: &dyn HirDatabase) -> Vec {
- db.variant_fields(self.id.into())
+ self.id
+ .fields(db)
.fields()
.iter()
.map(|(id, _)| Field { parent: self.into(), id })
@@ -1434,8 +1435,8 @@ impl Struct {
}
}
- fn variant_fields(self, db: &dyn HirDatabase) -> Arc {
- db.variant_fields(self.id.into())
+ fn variant_fields(self, db: &dyn HirDatabase) -> &VariantFields {
+ self.id.fields(db)
}
pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
@@ -1478,7 +1479,7 @@ impl Union {
}
pub fn kind(self, db: &dyn HirDatabase) -> StructKind {
- match db.variant_fields(self.id.into()).shape {
+ match self.id.fields(db).shape {
hir_def::item_tree::FieldsShape::Record => StructKind::Record,
hir_def::item_tree::FieldsShape::Tuple => StructKind::Tuple,
hir_def::item_tree::FieldsShape::Unit => StructKind::Unit,
@@ -1486,7 +1487,8 @@ impl Union {
}
pub fn fields(self, db: &dyn HirDatabase) -> Vec {
- db.variant_fields(self.id.into())
+ self.id
+ .fields(db)
.fields()
.iter()
.map(|(id, _)| Field { parent: self.into(), id })
@@ -1626,7 +1628,8 @@ impl Variant {
}
pub fn fields(self, db: &dyn HirDatabase) -> Vec {
- db.variant_fields(self.id.into())
+ self.id
+ .fields(db)
.fields()
.iter()
.map(|(id, _)| Field { parent: self.into(), id })
@@ -1634,7 +1637,7 @@ impl Variant {
}
pub fn kind(self, db: &dyn HirDatabase) -> StructKind {
- match db.variant_fields(self.id.into()).shape {
+ match self.id.fields(db).shape {
hir_def::item_tree::FieldsShape::Record => StructKind::Record,
hir_def::item_tree::FieldsShape::Tuple => StructKind::Tuple,
hir_def::item_tree::FieldsShape::Unit => StructKind::Unit,
@@ -1727,10 +1730,10 @@ impl Adt {
pub fn ty_with_args<'db>(
self,
db: &'db dyn HirDatabase,
- args: impl Iterator- >,
+ args: impl IntoIterator
- >,
) -> Type<'db> {
let id = AdtId::from(self);
- let mut it = args.map(|t| t.ty);
+ let mut it = args.into_iter().map(|t| t.ty);
let ty = TyBuilder::def_ty(db, id.into(), None)
.fill(|x| {
let r = it.next().unwrap_or_else(|| TyKind::Error.intern(Interner));
@@ -2883,7 +2886,7 @@ impl Trait {
}
pub fn function(self, db: &dyn HirDatabase, name: impl PartialEq
) -> Option {
- db.trait_items(self.id).items.iter().find(|(n, _)| name == *n).and_then(|&(_, it)| match it
+ self.id.trait_items(db).items.iter().find(|(n, _)| name == *n).and_then(|&(_, it)| match it
{
AssocItemId::FunctionId(id) => Some(Function { id }),
_ => None,
@@ -2891,7 +2894,7 @@ impl Trait {
}
pub fn items(self, db: &dyn HirDatabase) -> Vec {
- db.trait_items(self.id).items.iter().map(|(_name, it)| (*it).into()).collect()
+ self.id.trait_items(db).items.iter().map(|(_name, it)| (*it).into()).collect()
}
pub fn items_with_supertraits(self, db: &dyn HirDatabase) -> Vec {
@@ -2939,7 +2942,7 @@ impl Trait {
}
fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId, MacroCallId)]> {
- db.trait_items(self.id).macro_calls.to_vec().into_boxed_slice()
+ self.id.trait_items(db).macro_calls.to_vec().into_boxed_slice()
}
/// `#[rust_analyzer::completions(...)]` mode.
@@ -3043,10 +3046,17 @@ pub struct BuiltinType {
}
impl BuiltinType {
+ // Constructors are added on demand, feel free to add more.
pub fn str() -> BuiltinType {
BuiltinType { inner: hir_def::builtin_type::BuiltinType::Str }
}
+ pub fn i32() -> BuiltinType {
+ BuiltinType {
+ inner: hir_def::builtin_type::BuiltinType::Int(hir_ty::primitive::BuiltinInt::I32),
+ }
+ }
+
pub fn ty<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> {
let core = Crate::core(db).map(|core| core.id).unwrap_or_else(|| db.all_crates()[0]);
Type::new_for_crate(core, TyBuilder::builtin(self.inner))
@@ -3667,7 +3677,7 @@ impl GenericDef {
let generics = db.generic_params(def);
- if generics.is_empty() && generics.no_predicates() {
+ if generics.is_empty() && generics.has_no_predicates() {
return;
}
@@ -5000,7 +5010,7 @@ impl<'db> Type<'db> {
}
let output_assoc_type =
- db.trait_items(trait_).associated_type_by_name(&Name::new_symbol_root(sym::Output))?;
+ trait_.trait_items(db).associated_type_by_name(&Name::new_symbol_root(sym::Output))?;
self.normalize_trait_assoc_type(db, &[], output_assoc_type.into())
}
@@ -5013,8 +5023,8 @@ impl<'db> Type<'db> {
/// This does **not** resolve `IntoIterator`, only `Iterator`.
pub fn iterator_item(self, db: &'db dyn HirDatabase) -> Option> {
let iterator_trait = LangItem::Iterator.resolve_trait(db, self.env.krate)?;
- let iterator_item = db
- .trait_items(iterator_trait)
+ let iterator_item = iterator_trait
+ .trait_items(db)
.associated_type_by_name(&Name::new_symbol_root(sym::Item))?;
self.normalize_trait_assoc_type(db, &[], iterator_item.into())
}
@@ -5044,8 +5054,8 @@ impl<'db> Type<'db> {
return None;
}
- let into_iter_assoc_type = db
- .trait_items(trait_)
+ let into_iter_assoc_type = trait_
+ .trait_items(db)
.associated_type_by_name(&Name::new_symbol_root(sym::IntoIter))?;
self.normalize_trait_assoc_type(db, &[], into_iter_assoc_type.into())
}
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
index d96975831e062..247bb69398311 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
@@ -2199,6 +2199,10 @@ pub struct SemanticsScope<'db> {
}
impl<'db> SemanticsScope<'db> {
+ pub fn file_id(&self) -> HirFileId {
+ self.file_id
+ }
+
pub fn module(&self) -> Module {
Module { id: self.resolver.module() }
}
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs
index fedd8239d031e..e7db93d375d33 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs
@@ -35,7 +35,7 @@ pub(crate) trait ChildBySource {
impl ChildBySource for TraitId {
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
- let data = db.trait_items(*self);
+ let data = self.trait_items(db);
data.macro_calls().filter(|(ast_id, _)| ast_id.file_id == file_id).for_each(
|(ast_id, call_id)| {
@@ -191,7 +191,7 @@ impl ChildBySource for VariantId {
Either::Right(source) => res[keys::RECORD_FIELD].insert(AstPtr::new(&source), id),
}
}
- let (_, sm) = db.variant_fields_with_source_map(*self);
+ let (_, sm) = self.fields_with_source_map(db);
sm.expansions().for_each(|(ast, &exp_id)| res[keys::MACRO_CALL].insert(ast.value, exp_id));
}
}
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 48543ca581fff..f18ca7cb2017e 100644
--- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
@@ -156,14 +156,14 @@ impl<'db> SourceAnalyzer<'db> {
InFile { file_id, .. }: InFile<&SyntaxNode>,
_offset: Option,
) -> SourceAnalyzer<'db> {
- let (fields, source_map) = db.variant_fields_with_source_map(def);
+ let (fields, source_map) = def.fields_with_source_map(db);
let resolver = def.resolver(db);
SourceAnalyzer {
resolver,
body_or_sig: Some(BodyOrSig::VariantFields {
def,
store: fields.store.clone(),
- source_map,
+ source_map: source_map.clone(),
}),
file_id,
}
@@ -713,7 +713,7 @@ impl<'db> SourceAnalyzer<'db> {
};
let (adt, subst) = self.infer()?.type_of_expr_or_pat(expr_id)?.as_adt()?;
let variant = self.infer()?.variant_resolution_for_expr_or_pat(expr_id)?;
- let variant_data = variant.variant_data(db);
+ let variant_data = variant.fields(db);
let field = FieldId { parent: variant, local_id: variant_data.field(&local_name)? };
let field_ty =
db.field_types(variant).get(field.local_id)?.clone().substitute(Interner, subst);
@@ -734,7 +734,7 @@ impl<'db> SourceAnalyzer<'db> {
let record_pat = ast::RecordPat::cast(field.syntax().parent().and_then(|p| p.parent())?)?;
let pat_id = self.pat_id(&record_pat.into())?;
let variant = self.infer()?.variant_resolution_for_pat(pat_id.as_pat()?)?;
- let variant_data = variant.variant_data(db);
+ let variant_data = variant.fields(db);
let field = FieldId { parent: variant, local_id: variant_data.field(&field_name)? };
let (adt, subst) = self.infer()?.type_of_pat.get(pat_id.as_pat()?)?.as_adt()?;
let field_ty =
@@ -803,8 +803,8 @@ impl<'db> SourceAnalyzer<'db> {
};
container = Either::Right(db.normalize_projection(projection, trait_env.clone()));
}
- let handle_variants = |variant, subst: &Substitution, container: &mut _| {
- let fields = db.variant_fields(variant);
+ let handle_variants = |variant: VariantId, subst: &Substitution, container: &mut _| {
+ let fields = variant.fields(db);
let field = fields.field(&field_name.as_name())?;
let field_types = db.field_types(variant);
*container = Either::Right(field_types[field].clone().substitute(Interner, subst));
@@ -1423,7 +1423,7 @@ impl<'db> SourceAnalyzer<'db> {
method_name: &Name,
) -> Option<(TraitId, FunctionId)> {
let trait_id = lang_trait.resolve_trait(db, self.resolver.krate())?;
- let fn_id = db.trait_items(trait_id).method_by_name(method_name)?;
+ let fn_id = trait_id.trait_items(db).method_by_name(method_name)?;
Some((trait_id, fn_id))
}
@@ -1580,7 +1580,7 @@ fn resolve_hir_path_(
// within the trait's associated types.
if let (Some(unresolved), &TypeNs::TraitId(trait_id)) = (&unresolved, &ty) {
if let Some(type_alias_id) =
- db.trait_items(trait_id).associated_type_by_name(unresolved.name)
+ trait_id.trait_items(db).associated_type_by_name(unresolved.name)
{
return Some(PathResolution::Def(ModuleDefId::from(type_alias_id).into()));
}
@@ -1731,7 +1731,7 @@ fn resolve_hir_path_qualifier(
// within the trait's associated types.
if let (Some(unresolved), &TypeNs::TraitId(trait_id)) = (&unresolved, &ty) {
if let Some(type_alias_id) =
- db.trait_items(trait_id).associated_type_by_name(unresolved.name)
+ trait_id.trait_items(db).associated_type_by_name(unresolved.name)
{
return Some(PathResolution::Def(ModuleDefId::from(type_alias_id).into()));
}
diff --git a/src/tools/rust-analyzer/crates/hir/src/symbols.rs b/src/tools/rust-analyzer/crates/hir/src/symbols.rs
index 64f2a910bd117..756650891d4bf 100644
--- a/src/tools/rust-analyzer/crates/hir/src/symbols.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/symbols.rs
@@ -334,7 +334,7 @@ impl<'a> SymbolCollector<'a> {
fn collect_from_trait(&mut self, trait_id: TraitId, trait_do_not_complete: Complete) {
let trait_data = self.db.trait_signature(trait_id);
self.with_container_name(Some(trait_data.name.as_str().into()), |s| {
- for &(ref name, assoc_item_id) in &self.db.trait_items(trait_id).items {
+ for &(ref name, assoc_item_id) in &trait_id.trait_items(self.db).items {
s.push_assoc_item(assoc_item_id, name, Some(trait_do_not_complete));
}
});
diff --git a/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml b/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml
index 53af980c194c5..385b0e1eb7c1d 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
rust-version.workspace = true
[lib]
+doctest = false
[dependencies]
cov-mark = "2.0.0"
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_is_method.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_is_method.rs
index 3e6d0bec68a6f..517906b429a6f 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_is_method.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_is_method.rs
@@ -1,3 +1,5 @@
+use std::slice;
+
use ide_db::assists::GroupLabel;
use stdx::to_lower_snake_case;
use syntax::ast::HasVisibility;
@@ -52,7 +54,7 @@ pub(crate) fn generate_enum_is_method(acc: &mut Assists, ctx: &AssistContext<'_>
let fn_name = format!("is_{}", &to_lower_snake_case(&variant_name.text()));
// Return early if we've found an existing new fn
- let impl_def = find_struct_impl(ctx, &parent_enum, &[fn_name.clone()])?;
+ let impl_def = find_struct_impl(ctx, &parent_enum, slice::from_ref(&fn_name))?;
let target = variant.syntax().text_range();
acc.add_group(
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_projection_method.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_projection_method.rs
index 3974bcf618756..e4b0f83049768 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_projection_method.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_projection_method.rs
@@ -1,3 +1,5 @@
+use std::slice;
+
use ide_db::assists::GroupLabel;
use itertools::Itertools;
use stdx::to_lower_snake_case;
@@ -148,7 +150,7 @@ fn generate_enum_projection_method(
let fn_name = format!("{fn_name_prefix}_{}", &to_lower_snake_case(&variant_name.text()));
// Return early if we've found an existing new fn
- let impl_def = find_struct_impl(ctx, &parent_enum, &[fn_name.clone()])?;
+ let impl_def = find_struct_impl(ctx, &parent_enum, slice::from_ref(&fn_name))?;
let target = variant.syntax().text_range();
acc.add_group(
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs
index 019ddaf1441dc..6527d3706e217 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/term_search.rs
@@ -100,9 +100,7 @@ fn f() { let a: u128 = 1; let b: u128 = todo$0!() }"#,
fn test_complete_todo_with_msg() {
check_assist(
term_search,
- // FIXME: Since we are lacking of `super let`, term search fails due to borrowck failure.
- // Should implement super let and remove `fmt_before_1_89_0`
- r#"//- minicore: todo, unimplemented, fmt_before_1_89_0
+ r#"//- minicore: todo, unimplemented
fn f() { let a: u128 = 1; let b: u128 = todo$0!("asd") }"#,
r#"fn f() { let a: u128 = 1; let b: u128 = a }"#,
)
@@ -112,10 +110,8 @@ fn f() { let a: u128 = 1; let b: u128 = todo$0!("asd") }"#,
fn test_complete_unimplemented_with_msg() {
check_assist(
term_search,
- // FIXME: Since we are lacking of `super let`, term search fails due to borrowck failure.
- // Should implement super let and remove `fmt_before_1_89_0`
- r#"//- minicore: todo, unimplemented, fmt_before_1_89_0
-fn f() { let a: u128 = 1; let b: u128 = todo$0!("asd") }"#,
+ r#"//- minicore: todo, unimplemented
+fn f() { let a: u128 = 1; let b: u128 = unimplemented$0!("asd") }"#,
r#"fn f() { let a: u128 = 1; let b: u128 = a }"#,
)
}
@@ -124,10 +120,8 @@ fn f() { let a: u128 = 1; let b: u128 = todo$0!("asd") }"#,
fn test_complete_unimplemented() {
check_assist(
term_search,
- // FIXME: Since we are lacking of `super let`, term search fails due to borrowck failure.
- // Should implement super let and remove `fmt_before_1_89_0`
- r#"//- minicore: todo, unimplemented, fmt_before_1_89_0
-fn f() { let a: u128 = 1; let b: u128 = todo$0!("asd") }"#,
+ r#"//- minicore: todo, unimplemented
+fn f() { let a: u128 = 1; let b: u128 = unimplemented$0!() }"#,
r#"fn f() { let a: u128 = 1; let b: u128 = a }"#,
)
}
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type.rs
index 9ea78719b20c0..d7189aa5dbbde 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type.rs
@@ -56,7 +56,8 @@ pub(crate) fn wrap_return_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
};
let type_ref = &ret_type.ty()?;
- let ty = ctx.sema.resolve_type(type_ref)?.as_adt();
+ let ty = ctx.sema.resolve_type(type_ref)?;
+ let ty_adt = ty.as_adt();
let famous_defs = FamousDefs(&ctx.sema, ctx.sema.scope(type_ref.syntax())?.krate());
for kind in WrapperKind::ALL {
@@ -64,7 +65,7 @@ pub(crate) fn wrap_return_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
continue;
};
- if matches!(ty, Some(hir::Adt::Enum(ret_type)) if ret_type == core_wrapper) {
+ if matches!(ty_adt, Some(hir::Adt::Enum(ret_type)) if ret_type == core_wrapper) {
// The return type is already wrapped
cov_mark::hit!(wrap_return_type_simple_return_type_already_wrapped);
continue;
@@ -78,10 +79,23 @@ pub(crate) fn wrap_return_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
|builder| {
let mut editor = builder.make_editor(&parent);
let make = SyntaxFactory::with_mappings();
- let alias = wrapper_alias(ctx, &make, &core_wrapper, type_ref, kind.symbol());
- let new_return_ty = alias.unwrap_or_else(|| match kind {
- WrapperKind::Option => make.ty_option(type_ref.clone()),
- WrapperKind::Result => make.ty_result(type_ref.clone(), make.ty_infer().into()),
+ let alias = wrapper_alias(ctx, &make, core_wrapper, type_ref, &ty, kind.symbol());
+ let (ast_new_return_ty, semantic_new_return_ty) = alias.unwrap_or_else(|| {
+ let (ast_ty, ty_constructor) = match kind {
+ WrapperKind::Option => {
+ (make.ty_option(type_ref.clone()), famous_defs.core_option_Option())
+ }
+ WrapperKind::Result => (
+ make.ty_result(type_ref.clone(), make.ty_infer().into()),
+ famous_defs.core_result_Result(),
+ ),
+ };
+ let semantic_ty = ty_constructor
+ .map(|ty_constructor| {
+ hir::Adt::from(ty_constructor).ty_with_args(ctx.db(), [ty.clone()])
+ })
+ .unwrap_or_else(|| ty.clone());
+ (ast_ty, semantic_ty)
});
let mut exprs_to_wrap = Vec::new();
@@ -96,6 +110,17 @@ pub(crate) fn wrap_return_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
for_each_tail_expr(&body_expr, tail_cb);
for ret_expr_arg in exprs_to_wrap {
+ if let Some(ty) = ctx.sema.type_of_expr(&ret_expr_arg) {
+ if ty.adjusted().could_unify_with(ctx.db(), &semantic_new_return_ty) {
+ // The type is already correct, don't wrap it.
+ // We deliberately don't use `could_unify_with_deeply()`, because as long as the outer
+ // enum matches it's okay for us, as we don't trigger the assist if the return type
+ // is already `Option`/`Result`, so mismatched exact type is more likely a mistake
+ // than something intended.
+ continue;
+ }
+ }
+
let happy_wrapped = make.expr_call(
make.expr_path(make.ident_path(kind.happy_ident())),
make.arg_list(iter::once(ret_expr_arg.clone())),
@@ -103,12 +128,12 @@ pub(crate) fn wrap_return_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
editor.replace(ret_expr_arg.syntax(), happy_wrapped.syntax());
}
- editor.replace(type_ref.syntax(), new_return_ty.syntax());
+ editor.replace(type_ref.syntax(), ast_new_return_ty.syntax());
if let WrapperKind::Result = kind {
// Add a placeholder snippet at the first generic argument that doesn't equal the return type.
// This is normally the error type, but that may not be the case when we inserted a type alias.
- let args = new_return_ty
+ let args = ast_new_return_ty
.path()
.unwrap()
.segment()
@@ -188,27 +213,28 @@ impl WrapperKind {
}
// Try to find an wrapper type alias in the current scope (shadowing the default).
-fn wrapper_alias(
- ctx: &AssistContext<'_>,
+fn wrapper_alias<'db>(
+ ctx: &AssistContext<'db>,
make: &SyntaxFactory,
- core_wrapper: &hir::Enum,
- ret_type: &ast::Type,
+ core_wrapper: hir::Enum,
+ ast_ret_type: &ast::Type,
+ semantic_ret_type: &hir::Type<'db>,
wrapper: hir::Symbol,
-) -> Option {
+) -> Option<(ast::PathType, hir::Type<'db>)> {
let wrapper_path = hir::ModPath::from_segments(
hir::PathKind::Plain,
iter::once(hir::Name::new_symbol_root(wrapper)),
);
- ctx.sema.resolve_mod_path(ret_type.syntax(), &wrapper_path).and_then(|def| {
+ ctx.sema.resolve_mod_path(ast_ret_type.syntax(), &wrapper_path).and_then(|def| {
def.filter_map(|def| match def.into_module_def() {
hir::ModuleDef::TypeAlias(alias) => {
let enum_ty = alias.ty(ctx.db()).as_adt()?.as_enum()?;
- (&enum_ty == core_wrapper).then_some(alias)
+ (enum_ty == core_wrapper).then_some((alias, enum_ty))
}
_ => None,
})
- .find_map(|alias| {
+ .find_map(|(alias, enum_ty)| {
let mut inserted_ret_type = false;
let generic_args =
alias.source(ctx.db())?.value.generic_param_list()?.generic_params().map(|param| {
@@ -216,7 +242,7 @@ fn wrapper_alias(
// Replace the very first type parameter with the function's return type.
ast::GenericParam::TypeParam(_) if !inserted_ret_type => {
inserted_ret_type = true;
- make.type_arg(ret_type.clone()).into()
+ make.type_arg(ast_ret_type.clone()).into()
}
ast::GenericParam::LifetimeParam(_) => {
make.lifetime_arg(make.lifetime("'_")).into()
@@ -231,7 +257,10 @@ fn wrapper_alias(
make.path_segment_generics(make.name_ref(name.as_str()), generic_arg_list),
);
- Some(make.ty_path(path))
+ let new_ty =
+ hir::Adt::from(enum_ty).ty_with_args(ctx.db(), [semantic_ret_type.clone()]);
+
+ Some((make.ty_path(path), new_ty))
})
})
}
@@ -605,29 +634,39 @@ fn foo() -> Option {
check_assist_by_label(
wrap_return_type,
r#"
-//- minicore: option
+//- minicore: option, future
+struct F(i32);
+impl core::future::Future for F {
+ type Output = i32;
+ fn poll(self: core::pin::Pin<&mut Self>, cx: &mut core::task::Context<'_>) -> core::task::Poll { 0 }
+}
async fn foo() -> i$032 {
if true {
if false {
- 1.await
+ F(1).await
} else {
- 2.await
+ F(2).await
}
} else {
- 24i32.await
+ F(24i32).await
}
}
"#,
r#"
+struct F(i32);
+impl core::future::Future for F {
+ type Output = i32;
+ fn poll(self: core::pin::Pin<&mut Self>, cx: &mut core::task::Context<'_>) -> core::task::Poll { 0 }
+}
async fn foo() -> Option {
if true {
if false {
- Some(1.await)
+ Some(F(1).await)
} else {
- Some(2.await)
+ Some(F(2).await)
}
} else {
- Some(24i32.await)
+ Some(F(24i32).await)
}
}
"#,
@@ -1666,29 +1705,39 @@ fn foo() -> Result {
check_assist_by_label(
wrap_return_type,
r#"
-//- minicore: result
+//- minicore: result, future
+struct F(i32);
+impl core::future::Future for F {
+ type Output = i32;
+ fn poll(self: core::pin::Pin<&mut Self>, cx: &mut core::task::Context<'_>) -> core::task::Poll { 0 }
+}
async fn foo() -> i$032 {
if true {
if false {
- 1.await
+ F(1).await
} else {
- 2.await
+ F(2).await
}
} else {
- 24i32.await
+ F(24i32).await
}
}
"#,
r#"
+struct F(i32);
+impl core::future::Future for F {
+ type Output = i32;
+ fn poll(self: core::pin::Pin<&mut Self>, cx: &mut core::task::Context<'_>) -> core::task::Poll { 0 }
+}
async fn foo() -> Result {
if true {
if false {
- Ok(1.await)
+ Ok(F(1).await)
} else {
- Ok(2.await)
+ Ok(F(2).await)
}
} else {
- Ok(24i32.await)
+ Ok(F(24i32).await)
}
}
"#,
@@ -2455,6 +2504,56 @@ type Result = core::result::Result, Bar>;
fn foo() -> Result {
Ok(0)
+}
+ "#,
+ WrapperKind::Result.label(),
+ );
+ }
+
+ #[test]
+ fn already_wrapped() {
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: option
+fn foo() -> i32$0 {
+ if false {
+ 0
+ } else {
+ Some(1)
+ }
+}
+ "#,
+ r#"
+fn foo() -> Option {
+ if false {
+ Some(0)
+ } else {
+ Some(1)
+ }
+}
+ "#,
+ WrapperKind::Option.label(),
+ );
+ check_assist_by_label(
+ wrap_return_type,
+ r#"
+//- minicore: result
+fn foo() -> i32$0 {
+ if false {
+ 0
+ } else {
+ Ok(1)
+ }
+}
+ "#,
+ r#"
+fn foo() -> Result {
+ if false {
+ Ok(0)
+ } else {
+ Ok(1)
+ }
}
"#,
WrapperKind::Result.label(),
diff --git a/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml b/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml
index 94c01e333ed44..9bad21fc8e90e 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
rust-version.workspace = true
[lib]
+doctest = false
[dependencies]
cov-mark = "2.0.0"
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/fn_param.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/fn_param.rs
index 6d1e973dc4c5c..809e71cc119e0 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/fn_param.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/fn_param.rs
@@ -195,5 +195,5 @@ fn comma_wrapper(ctx: &CompletionContext<'_>) -> Option<(impl Fn(&str) -> String
matches!(prev_token_kind, SyntaxKind::COMMA | SyntaxKind::L_PAREN | SyntaxKind::PIPE);
let leading = if has_leading_comma { "" } else { ", " };
- Some((move |label: &_| (format!("{leading}{label}{trailing}")), param.text_range()))
+ Some((move |label: &_| format!("{leading}{label}{trailing}"), param.text_range()))
}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
index 6e3a76f346a83..ea5fb39338b2e 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
@@ -4,6 +4,7 @@ use std::iter;
use hir::{ExpandResult, InFile, Semantics, Type, TypeInfo, Variant};
use ide_db::{RootDatabase, active_parameter::ActiveParameter};
use itertools::Either;
+use stdx::always;
use syntax::{
AstNode, AstToken, Direction, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken,
T, TextRange, TextSize,
@@ -869,8 +870,15 @@ fn classify_name_ref<'db>(
return None;
}
+ let mut receiver_ty = receiver.as_ref().and_then(|it| sema.type_of_expr(it));
+ if receiver_is_ambiguous_float_literal {
+ // `123.|` is parsed as a float but should actually be an integer.
+ always!(receiver_ty.as_ref().is_none_or(|receiver_ty| receiver_ty.original.is_float()));
+ receiver_ty = Some(TypeInfo { original: hir::BuiltinType::i32().ty(sema.db), adjusted: None });
+ }
+
let kind = NameRefKind::DotAccess(DotAccess {
- receiver_ty: receiver.as_ref().and_then(|it| sema.type_of_expr(it)),
+ receiver_ty,
kind: DotAccessKind::Field { receiver_is_ambiguous_float_literal },
receiver,
ctx: DotAccessExprCtx { in_block_expr: is_in_block(field.syntax()), in_breakable: is_in_breakable(field.syntax()) }
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
index b2d18b796f195..33f729f016645 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
@@ -2241,3 +2241,37 @@ fn main() {
"#,
);
}
+
+#[test]
+fn ambiguous_float_literal() {
+ check(
+ r#"
+#![rustc_coherence_is_core]
+
+impl i32 {
+ pub fn int_method(self) {}
+}
+impl f64 {
+ pub fn float_method(self) {}
+}
+
+fn foo() {
+ 1.$0
+}
+ "#,
+ expect![[r#"
+ me int_method() fn(self)
+ sn box Box::new(expr)
+ sn call function(expr)
+ sn const const {}
+ sn dbg dbg!(expr)
+ sn dbgr dbg!(&expr)
+ sn deref *expr
+ sn match match expr {}
+ sn ref &expr
+ sn refm &mut expr
+ sn return return expr
+ sn unsafe unsafe {}
+ "#]],
+ );
+}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs
index fcdf10c85616c..179d66936026a 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs
@@ -550,3 +550,30 @@ fn inside_extern_blocks() {
"#]],
)
}
+
+#[test]
+fn tokens_from_macro() {
+ check_edit(
+ "fn as_ref",
+ r#"
+//- proc_macros: identity
+//- minicore: as_ref
+struct Foo;
+
+#[proc_macros::identity]
+impl<'a> AsRef<&'a i32> for Foo {
+ $0
+}
+ "#,
+ r#"
+struct Foo;
+
+#[proc_macros::identity]
+impl<'a> AsRef<&'a i32> for Foo {
+ fn as_ref(&self) -> &&'a i32 {
+ $0
+}
+}
+ "#,
+ );
+}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs
index 125e11e9e3589..c7e2d058257e3 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs
@@ -429,18 +429,18 @@ trait Tr {
impl Tr<$0
"#,
expect![[r#"
- en Enum Enum
- ma makro!(…) macro_rules! makro
+ en Enum Enum
+ ma makro!(…) macro_rules! makro
md module
- sp Self dyn Tr<{unknown}> + 'static
- st Record Record
- st S S
- st Tuple Tuple
- st Unit Unit
+ sp Self dyn Tr<{unknown}>
+ st Record Record
+ st S S
+ st Tuple Tuple
+ st Unit Unit
tt Tr
tt Trait
- un Union Union
- bt u32 u32
+ un Union Union
+ bt u32 u32
kw crate::
kw self::
"#]],
diff --git a/src/tools/rust-analyzer/crates/ide-db/Cargo.toml b/src/tools/rust-analyzer/crates/ide-db/Cargo.toml
index acde1d665dae1..e065adb0f0baa 100644
--- a/src/tools/rust-analyzer/crates/ide-db/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-db/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
rust-version.workspace = true
[lib]
+doctest = false
[dependencies]
cov-mark = "2.0.0"
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs b/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs
index 232648af661ff..0ab880bcfe71e 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs
@@ -2,7 +2,10 @@
use crate::helpers::mod_path_to_ast;
use either::Either;
-use hir::{AsAssocItem, HirDisplay, ImportPathConfig, ModuleDef, SemanticsScope};
+use hir::{
+ AsAssocItem, HirDisplay, HirFileId, ImportPathConfig, ModuleDef, SemanticsScope,
+ prettify_macro_expansion,
+};
use itertools::Itertools;
use rustc_hash::FxHashMap;
use span::Edition;
@@ -136,6 +139,25 @@ impl<'a> PathTransform<'a> {
}
}
+ fn prettify_target_node(&self, node: SyntaxNode) -> SyntaxNode {
+ match self.target_scope.file_id() {
+ HirFileId::FileId(_) => node,
+ HirFileId::MacroFile(file_id) => {
+ let db = self.target_scope.db;
+ prettify_macro_expansion(
+ db,
+ node,
+ &db.expansion_span_map(file_id),
+ self.target_scope.module().krate().into(),
+ )
+ }
+ }
+ }
+
+ fn prettify_target_ast(&self, node: N) -> N {
+ N::cast(self.prettify_target_node(node.syntax().clone())).unwrap()
+ }
+
fn build_ctx(&self) -> Ctx<'a> {
let db = self.source_scope.db;
let target_module = self.target_scope.module();
@@ -163,7 +185,7 @@ impl<'a> PathTransform<'a> {
.for_each(|(k, v)| match (k.split(db), v) {
(Either::Right(k), Some(TypeOrConst::Either(v))) => {
if let Some(ty) = v.ty() {
- type_substs.insert(k, ty);
+ type_substs.insert(k, self.prettify_target_ast(ty));
}
}
(Either::Right(k), None) => {
@@ -178,7 +200,7 @@ impl<'a> PathTransform<'a> {
}
(Either::Left(k), Some(TypeOrConst::Either(v))) => {
if let Some(ty) = v.ty() {
- const_substs.insert(k, ty.syntax().clone());
+ const_substs.insert(k, self.prettify_target_node(ty.syntax().clone()));
}
}
(Either::Left(k), Some(TypeOrConst::Const(v))) => {
@@ -189,7 +211,7 @@ impl<'a> PathTransform<'a> {
// and sometimes require slight modifications; see
// https://doc.rust-lang.org/reference/statements.html#expression-statements
// (default values in curly brackets can cause the same problem)
- const_substs.insert(k, expr.syntax().clone());
+ const_substs.insert(k, self.prettify_target_node(expr.syntax().clone()));
}
}
(Either::Left(k), None) => {
@@ -204,6 +226,7 @@ impl<'a> PathTransform<'a> {
}
_ => (), // ignore mismatching params
});
+ // No need to prettify lifetimes, there's nothing to prettify.
let lifetime_substs: FxHashMap<_, _> = self
.generic_def
.into_iter()
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml b/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml
index 96be51e1b2666..6f1e66948f42c 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
rust-version.workspace = true
[lib]
+doctest = false
[dependencies]
cov-mark = "2.0.0"
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 e2957fcaefb44..ac54ac0950f39 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
@@ -1171,7 +1171,7 @@ trait B {}
fn test(a: &dyn A) -> &dyn B {
a
- //^ error: expected &(dyn B + 'static), found &(dyn A + 'static)
+ //^ error: expected &dyn B, found &dyn A
}
"#,
);
diff --git a/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml b/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml
index 1212fa9f9c65f..0620bd26fefd1 100644
--- a/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
rust-version.workspace = true
[lib]
+doctest = false
[dependencies]
cov-mark = "2.0.0"
diff --git a/src/tools/rust-analyzer/crates/ide/Cargo.toml b/src/tools/rust-analyzer/crates/ide/Cargo.toml
index 2f8ed88fbb5d1..06d2776ebe87a 100644
--- a/src/tools/rust-analyzer/crates/ide/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide/Cargo.toml
@@ -10,6 +10,7 @@ license.workspace = true
rust-version.workspace = true
[lib]
+doctest = false
[dependencies]
cov-mark = "2.0.0"
diff --git a/src/tools/rust-analyzer/crates/ide/src/folding_ranges.rs b/src/tools/rust-analyzer/crates/ide/src/folding_ranges.rs
index 194e8c968f758..9bd8504733a43 100755
--- a/src/tools/rust-analyzer/crates/ide/src/folding_ranges.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/folding_ranges.rs
@@ -2,7 +2,7 @@ use ide_db::{FxHashSet, syntax_helpers::node_ext::vis_eq};
use syntax::{
Direction, NodeOrToken, SourceFile,
SyntaxKind::{self, *},
- TextRange, TextSize,
+ SyntaxNode, TextRange, TextSize,
ast::{self, AstNode, AstToken},
match_ast,
};
@@ -16,16 +16,21 @@ const REGION_END: &str = "// endregion";
pub enum FoldKind {
Comment,
Imports,
- Mods,
+ Region,
Block,
ArgList,
- Region,
- Consts,
- Statics,
Array,
WhereClause,
ReturnType,
MatchArm,
+ // region: item runs
+ Modules,
+ Consts,
+ Statics,
+ TypeAliases,
+ TraitAliases,
+ ExternCrates,
+ // endregion: item runs
}
#[derive(Debug)]
@@ -41,10 +46,7 @@ pub struct Fold {
pub(crate) fn folding_ranges(file: &SourceFile) -> Vec {
let mut res = vec![];
let mut visited_comments = FxHashSet::default();
- let mut visited_imports = FxHashSet::default();
- let mut visited_mods = FxHashSet::default();
- let mut visited_consts = FxHashSet::default();
- let mut visited_statics = FxHashSet::default();
+ let mut visited_nodes = FxHashSet::default();
// regions can be nested, here is a LIFO buffer
let mut region_starts: Vec = vec![];
@@ -93,30 +95,40 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec {
if module.item_list().is_none() {
if let Some(range) = contiguous_range_for_item_group(
module,
- &mut visited_mods,
+ &mut visited_nodes,
) {
- res.push(Fold { range, kind: FoldKind::Mods })
+ res.push(Fold { range, kind: FoldKind::Modules })
}
}
},
ast::Use(use_) => {
- if let Some(range) = contiguous_range_for_item_group(use_, &mut visited_imports) {
+ if let Some(range) = contiguous_range_for_item_group(use_, &mut visited_nodes) {
res.push(Fold { range, kind: FoldKind::Imports })
}
},
ast::Const(konst) => {
- if let Some(range) = contiguous_range_for_item_group(konst, &mut visited_consts) {
+ if let Some(range) = contiguous_range_for_item_group(konst, &mut visited_nodes) {
res.push(Fold { range, kind: FoldKind::Consts })
}
},
ast::Static(statik) => {
- if let Some(range) = contiguous_range_for_item_group(statik, &mut visited_statics) {
+ if let Some(range) = contiguous_range_for_item_group(statik, &mut visited_nodes) {
res.push(Fold { range, kind: FoldKind::Statics })
}
},
- ast::WhereClause(where_clause) => {
- if let Some(range) = fold_range_for_where_clause(where_clause) {
- res.push(Fold { range, kind: FoldKind::WhereClause })
+ ast::TypeAlias(alias) => {
+ if let Some(range) = contiguous_range_for_item_group(alias, &mut visited_nodes) {
+ res.push(Fold { range, kind: FoldKind::TypeAliases })
+ }
+ },
+ ast::TraitAlias(alias) => {
+ if let Some(range) = contiguous_range_for_item_group(alias, &mut visited_nodes) {
+ res.push(Fold { range, kind: FoldKind::TraitAliases })
+ }
+ },
+ ast::ExternCrate(extern_crate) => {
+ if let Some(range) = contiguous_range_for_item_group(extern_crate, &mut visited_nodes) {
+ res.push(Fold { range, kind: FoldKind::ExternCrates })
}
},
ast::MatchArm(match_arm) => {
@@ -137,9 +149,10 @@ pub(crate) fn folding_ranges(file: &SourceFile) -> Vec {
fn fold_kind(kind: SyntaxKind) -> Option {
match kind {
COMMENT => Some(FoldKind::Comment),
- ARG_LIST | PARAM_LIST => Some(FoldKind::ArgList),
+ ARG_LIST | PARAM_LIST | GENERIC_ARG_LIST | GENERIC_PARAM_LIST => Some(FoldKind::ArgList),
ARRAY_EXPR => Some(FoldKind::Array),
RET_TYPE => Some(FoldKind::ReturnType),
+ WHERE_CLAUSE => Some(FoldKind::WhereClause),
ASSOC_ITEM_LIST
| RECORD_FIELD_LIST
| RECORD_PAT_FIELD_LIST
@@ -155,11 +168,14 @@ fn fold_kind(kind: SyntaxKind) -> Option {
}
}
-fn contiguous_range_for_item_group(first: N, visited: &mut FxHashSet) -> Option
+fn contiguous_range_for_item_group(
+ first: N,
+ visited: &mut FxHashSet,
+) -> Option
where
N: ast::HasVisibility + Clone + Hash + Eq,
{
- if !visited.insert(first.clone()) {
+ if !visited.insert(first.syntax().clone()) {
return None;
}
@@ -183,7 +199,7 @@ where
if let Some(next) = N::cast(node) {
let next_vis = next.visibility();
if eq_visibility(next_vis.clone(), last_vis) {
- visited.insert(next.clone());
+ visited.insert(next.syntax().clone());
last_vis = next_vis;
last = next;
continue;
@@ -259,18 +275,6 @@ fn contiguous_range_for_comment(
}
}
-fn fold_range_for_where_clause(where_clause: ast::WhereClause) -> Option {
- let first_where_pred = where_clause.predicates().next();
- let last_where_pred = where_clause.predicates().last();
-
- if first_where_pred != last_where_pred {
- let start = where_clause.where_token()?.text_range().end();
- let end = where_clause.syntax().text_range().end();
- return Some(TextRange::new(start, end));
- }
- None
-}
-
fn fold_range_for_multiline_match_arm(match_arm: ast::MatchArm) -> Option