Auto merge of #143254 - matthiaskrgr:rollup-7x8bxek, r=matthiaskrgr

Rollup of 9 pull requests

Successful merges:

 - rust-lang/rust#143019 (Ensure -V --verbose processes both codegen_backend and codegen-backend)
 - rust-lang/rust#143140 (give Pointer::into_parts a more scary name and offer a safer alternative)
 - rust-lang/rust#143175 (Make combining LLD with external LLVM config a hard error)
 - rust-lang/rust#143180 (Use `tracing-forest` instead of `tracing-tree` for bootstrap tracing)
 - rust-lang/rust#143223 (Improve macro stats printing)
 - rust-lang/rust#143228 (Handle build scripts better in `-Zmacro-stats` output.)
 - rust-lang/rust#143229 ([COMPILETEST-UNTANGLE 1/N] Move some some early config checks to the lib and move the compiletest binary)
 - rust-lang/rust#143246 (Subtree update of `rust-analyzer`)
 - rust-lang/rust#143248 (Update books)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors
2025-06-30 22:36:52 +00:00
188 changed files with 2459 additions and 984 deletions
@@ -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) => {
+1 -1
View File
@@ -240,7 +240,7 @@ fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, ty: Type<'gcc>) ->
}
}
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) => {
+1 -1
View File
@@ -268,7 +268,7 @@ fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, llty: &'ll Type) ->
}
}
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) => {
@@ -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);
+1 -1
View File
@@ -574,7 +574,7 @@ fn add_args<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
if addr != 0 {
diag.arg(
"pointer",
Pointer::<Option<CtfeProvenance>>::from_addr_invalid(addr).to_string(),
Pointer::<Option<CtfeProvenance>>::without_provenance(addr).to_string(),
);
}
@@ -747,7 +747,7 @@ fn ptr_from_addr_cast(
// 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 @@ fn ptr_get_alloc(
ptr: Pointer<CtfeProvenance>,
_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()))
}
@@ -1596,7 +1596,8 @@ pub fn ptr_try_get_alloc_id(
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())
}
},
@@ -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 }
}
@@ -518,7 +518,7 @@ fn check_safe_pointer(
Ub(DanglingIntPointer { addr: i, .. }) => DanglingPtrNoProvenance {
ptr_kind,
// FIXME this says "null pointer" when null but we need translate
pointer: format!("{}", Pointer::<Option<AllocId>>::from_addr_invalid(i))
pointer: format!("{}", Pointer::<Option<AllocId>>::without_provenance(i))
},
Ub(PointerOutOfBounds { .. }) => DanglingPtrOutOfBounds {
ptr_kind
@@ -868,7 +868,9 @@ fn in_mutable_memory(&self, val: &PlaceTy<'tcx, M::Provenance>) -> bool {
fn add_data_range(&mut self, ptr: Pointer<Option<M::Provenance>>, 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 @@ fn data_range_offset(ecx: &InterpCx<'tcx, M>, place: &PlaceTy<'tcx, M::Provenanc
.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 @@ fn reset_padding(&mut self, place: &PlaceTy<'tcx, M::Provenance>) -> InterpResul
// 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)?
+3 -1
View File
@@ -1112,7 +1112,9 @@ fn get_backend_from_raw_matches(
matches: &Matches,
) -> Box<dyn CodegenBackend> {
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());
+27 -7
View File
@@ -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(|_| "<unknown crate>".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} {:<name_w$}{:>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$}", name);
name = String::new();
}
} else if name.len() >= 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} {:<name_w$}{:>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),
+3 -2
View File
@@ -168,8 +168,9 @@ pub fn try_get_slice_bytes_for_diagnostics(&self, tcx: TyCtxt<'tcx>) -> Option<&
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)
}
};
@@ -526,7 +526,7 @@ pub fn adjust_from_tcx<'tcx, Prov: Provenance, Bytes: AllocBytes>(
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 @@ pub fn write_scalar(
// 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),
@@ -288,7 +288,7 @@ fn from(prov: CtfeProvenance) -> Self {
impl<Prov> From<Pointer<Prov>> for Pointer<Option<Prov>> {
#[inline(always)]
fn from(ptr: Pointer<Prov>) -> Self {
let (prov, offset) = ptr.into_parts();
let (prov, offset) = ptr.into_raw_parts();
Pointer::new(Some(prov), offset)
}
}
@@ -314,19 +314,17 @@ pub fn addr(self) -> Size
assert!(Prov::OFFSET_IS_ADDR);
self.offset
}
}
impl<Prov> Pointer<Option<Prov>> {
/// 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 @@ pub fn new(provenance: Prov, offset: Size) -> Self {
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 @@ pub fn wrapping_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> Self {
self.wrapping_offset(Size::from_bytes(i as u64), cx)
}
}
impl Pointer<CtfeProvenance> {
/// 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)
}
}
@@ -109,7 +109,7 @@ pub fn from_pointer(ptr: Pointer<Prov>, cx: &impl HasDataLayout) -> Self {
/// 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<Option<Prov>>, 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 @@ pub fn to_pointer(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, Pointer<O
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 @@ pub fn try_to_scalar_int(self) -> Result<ScalarInt, Scalar<AllocId>> {
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))
}
+1 -1
View File
@@ -1755,7 +1755,7 @@ fn pretty_print_const_scalar_ptr(
) -> 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, _) => {
+1 -1
View File
@@ -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()?;
+44 -23
View File
@@ -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"
+2 -2
View File
@@ -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"
+3 -3
View File
@@ -217,12 +217,11 @@ fn check_version(config: &Config) -> Option<String> {
// "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. <https://docs.rs/tracing-tree/latest/tracing_tree/struct.HierarchicalLayer.html>.
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
@@ -2241,7 +2241,7 @@ fn run(self, builder: &Builder<'_>) -> Compiler {
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,
+1 -3
View File
@@ -1003,9 +1003,7 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
}
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 =
@@ -431,4 +431,9 @@ pub fn human_readable_changes(changes: &[ChangeInfo]) -> String {
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`.",
},
];
+4
View File
@@ -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"
+24
View File
@@ -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);
}
+22 -6
View File
@@ -51,12 +51,6 @@
/// some code here that inspects environment variables or even runs executables
/// (e.g. when discovering debugger versions).
pub fn parse_config(args: Vec<String>) -> 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<Utf8PathBuf>) {
);
}
}
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."
);
}
}
-36
View File
@@ -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);
}
+2 -2
View File
@@ -390,7 +390,7 @@ fn adjust_alloc_root_pointer(
) -> InterpResult<'tcx, interpret::Pointer<Provenance>> {
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 @@ fn ptr_get_alloc(
) -> 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
+1 -1
View File
@@ -285,7 +285,7 @@ fn get_alloc_id(self) -> Option<AllocId> {
}
fn fmt(ptr: &interpret::Pointer<Self>, 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:#?}")?;
+2 -4
View File
@@ -68,15 +68,13 @@ fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
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);
}
}
+1 -1
View File
@@ -411,7 +411,7 @@ fn emulate_foreign_item_inner(
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!(
+1 -1
View File
@@ -49,7 +49,7 @@ fn mmap(
&& 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");
+2
View File
@@ -72,6 +72,8 @@ pub fn run_tests(env: &Environment) -> anyhow::Result<()> {
[rust]
channel = "{channel}"
verbose-tests = true
# rust-lld cannot be combined with an external LLVM
lld = false
[build]
rustc = "{rustc}"
+24 -15
View File
@@ -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
+2 -2
View File
@@ -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
+4 -4
View File
@@ -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",
+1 -1
View File
@@ -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",
@@ -10,6 +10,7 @@ license.workspace = true
rust-version.workspace = true
[lib]
doctest = false
[dependencies]
la-arena.workspace = true
@@ -10,6 +10,7 @@ license.workspace = true
rust-version.workspace = true
[lib]
doctest = false
[dependencies]
rustc-hash.workspace = true
@@ -10,6 +10,7 @@ license.workspace = true
rust-version.workspace = true
[lib]
doctest = false
[dependencies]
arrayvec.workspace = true
@@ -25,11 +25,10 @@
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<VariantFields>, Arc<ExpressionStoreSourceMap>);
#[salsa::transparent]
#[salsa::invoke(TraitItems::trait_items_query)]
fn trait_items(&self, e: TraitId) -> Arc<TraitItems>;
#[salsa::invoke(TraitItems::trait_items_with_diagnostics_query)]
fn trait_items_with_diagnostics(&self, tr: TraitId) -> (Arc<TraitItems>, DefDiagnostics);
#[salsa::tracked]
fn variant_fields(&self, id: VariantId) -> Arc<VariantFields> {
self.variant_fields_with_source_map(id).0
}
#[salsa::tracked]
fn trait_signature(&self, trait_: TraitId) -> Arc<TraitSignature> {
self.trait_signature_with_source_map(trait_).0
@@ -9,7 +9,10 @@
#[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 smallvec::SmallVec;
use span::{Edition, SyntaxContext};
use syntax::{AstPtr, SyntaxNodePtr, ast};
use triomphe::Arc;
use tt::TextRange;
use crate::{
@@ -220,6 +224,12 @@ pub fn finish(self) -> ExpressionStore {
}
impl ExpressionStore {
pub fn empty_singleton() -> Arc<Self> {
static EMPTY: LazyLock<Arc<ExpressionStore>> =
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 @@ fn index(&self, index: PathId) -> &Self::Output {
// FIXME: Change `node_` prefix to something more reasonable.
// Perhaps `expr_syntax` and `expr_id`?
impl ExpressionStoreSourceMap {
pub fn empty_singleton() -> Arc<Self> {
static EMPTY: LazyLock<Arc<ExpressionStoreSourceMap>> =
LazyLock::new(|| Arc::new(ExpressionStoreSourceMap::default()));
EMPTY.clone()
}
pub fn expr_or_pat_syntax(&self, id: ExprOrPatId) -> Result<ExprOrPatSource, SyntheticSyntax> {
match id {
ExprOrPatId::ExprId(id) => self.expr_syntax(id),
@@ -2250,7 +2250,7 @@ fn collect_pat(&mut self, pat: ast::Pat, binding_list: &mut BindingList) -> PatI
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 @@ fn collect_format_args(
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 @@ fn collect_format_args_impl(
&mut self,
syntax_ptr: AstPtr<ast::Expr>,
fmt: FormatArgs,
hygiene: HygieneId,
argmap: FxIndexSet<(usize, ArgumentType)>,
lit_pieces: ExprId,
format_options: ExprId,
@@ -2997,8 +2989,11 @@ fn collect_format_args_impl(
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 @@ fn collect_format_args_impl(
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 @@ fn collect_format_args_impl(
.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 {
@@ -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, "<missing>")),
};
let fields = db.variant_fields(owner);
let fields = owner.fields(db);
let mut p = Printer {
db,
@@ -331,13 +331,13 @@ pub fn is_empty(&self) -> bool {
}
#[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
@@ -16,7 +16,7 @@
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 @@ fn collect_trait_assoc_items(
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 @@ fn assoc_item_path(
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()
@@ -9,8 +9,10 @@
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<Box<LangIt
match def {
ModuleDefId::TraitId(trait_) => {
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 @@ pub fn ty_rel_path(&self, db: &dyn DefDatabase, start_crate: Crate, seg: Name) -
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;
@@ -87,9 +87,12 @@
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 @@ fn module(&self, db: &dyn DefDatabase) -> ModuleId {
type StructLoc = ItemLoc<ast::Struct>;
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<VariantFields>, Arc<ExpressionStoreSourceMap>) {
VariantFields::query(db, self.into())
}
}
pub type UnionLoc = ItemLoc<ast::Union>;
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<VariantFields>, Arc<ExpressionStoreSourceMap>) {
VariantFields::query(db, self.into())
}
}
pub type EnumLoc = ItemLoc<ast::Enum>;
impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum);
@@ -282,6 +311,13 @@ pub fn enum_variants_with_diagnostics(
pub type TraitLoc = ItemLoc<ast::Trait>;
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<ast::TraitAlias>;
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<VariantFields>, Arc<ExpressionStoreSourceMap>) {
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<VariantFields> {
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<VariantFields>, Arc<ExpressionStoreSourceMap>) {
VariantFields::query(db, self)
}
pub fn file_id(self, db: &dyn DefDatabase) -> HirFileId {
@@ -38,16 +38,18 @@ pub struct TraitItems {
pub macro_calls: ThinVec<(AstId<ast::Item>, MacroCallId)>,
}
#[salsa::tracked]
impl TraitItems {
#[inline]
pub(crate) fn trait_items_query(db: &dyn DefDatabase, tr: TraitId) -> Arc<TraitItems> {
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<TraitItems>, DefDiagnostics) {
) -> (TraitItems, DefDiagnostics) {
let ItemLoc { container: module_id, id: ast_id } = tr.lookup(db);
let collector =
@@ -55,7 +57,7 @@ pub(crate) fn trait_items_with_diagnostics_query(
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<Item = TypeAliasId> + '_ {
@@ -41,6 +41,7 @@
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 @@ fn record_resolved_import(&mut self, directive: &ImportDirective) {
let resolutions = if true {
vec![]
} else {
self.db
.trait_items(it)
TraitItems::query(self.db, it)
.items
.iter()
.map(|&(ref name, variant)| {
@@ -24,8 +24,8 @@
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 @@ fn resolve_remaining_segments<'a>(
// 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 {
@@ -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<ExpressionStore>,
pub shape: FieldsShape,
}
#[salsa::tracked]
impl VariantFields {
#[inline]
#[salsa::tracked(returns(clone))]
pub(crate) fn query(
db: &dyn DefDatabase,
id: VariantId,
) -> (Arc<Self>, Arc<ExpressionStoreSourceMap>) {
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 @@ pub(crate) fn query(
(FieldsShape::Record, fields)
}
};
(Arc::new(VariantFields { fields, store: Arc::new(store), shape }), Arc::new(source_map))
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(),
),
}
}
#[salsa::tracked(returns(deref))]
pub(crate) fn firewall(db: &dyn DefDatabase, id: VariantId) -> Arc<Self> {
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<Option<ast::FieldList>>,
override_visibility: Option<RawVisibility>,
) -> (Arena<FieldData>, ExpressionStore, ExpressionStoreSourceMap) {
override_visibility: Option<Option<ast::Visibility>>,
) -> Option<(Arena<FieldData>, 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::Type>, ast::RecordField)>()),
|_, _| Name::missing(),
None,
),
}
}
@@ -831,22 +840,34 @@ fn lower_fields<Field: ast::HasAttrs + ast::HasVisibility>(
module: ModuleId,
fields: InFile<impl Iterator<Item = (Option<ast::Type>, Field)>>,
mut field_name: impl FnMut(usize, &Field) -> Name,
override_visibility: Option<RawVisibility>,
) -> (Arena<FieldData>, ExpressionStore, ExpressionStoreSourceMap) {
let mut arena = Arena::new();
override_visibility: Option<Option<ast::Visibility>>,
) -> Option<(Arena<FieldData>, 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<Field: ast::HasAttrs + ast::HasVisibility>(
}
}
}
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 @@ pub fn is_payload_free(&self, db: &dyn DefDatabase) -> bool {
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;
}
@@ -273,7 +273,7 @@ pub(crate) fn field_visibilities_query(
db: &dyn DefDatabase,
variant_id: VariantId,
) -> Arc<ArenaMap<LocalFieldId, Visibility>> {
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();
@@ -10,6 +10,7 @@ license.workspace = true
rust-version.workspace = true
[lib]
doctest = false
[dependencies]
cov-mark = "2.0.0"
@@ -433,20 +433,19 @@ fn unescape(s: &str) -> Option<Cow<'_, str>> {
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
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,
}
(Ok(c), true) => {
buf.reserve_exact(s.len());
buf.push_str(&s[..prev_end]);
buf.push(c);
}
(Err(_), _) => has_error = true,
});
match (has_error, buf.capacity() == 0) {
@@ -12,7 +12,7 @@
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)
}
@@ -10,6 +10,7 @@ license.workspace = true
rust-version.workspace = true
[lib]
doctest = false
[dependencies]
cov-mark = "2.0.0"
@@ -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);
@@ -315,9 +315,8 @@ fn opaque_ty_data(&self, id: chalk_ir::OpaqueTyId<Interner>) -> Arc<OpaqueTyDatu
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();
@@ -307,7 +307,7 @@ fn validate_struct(&mut self, struct_id: StructId) {
/// 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 @@ fn validate_enum_variants(&mut self, enum_id: EnumId) {
/// 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;
};
@@ -494,7 +494,7 @@ fn new(resolver: &hir_def::resolver::Resolver<'_>, db: &dyn HirDatabase) -> Self
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<LocalFieldId> = 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<LocalFieldId> = variant_data
@@ -169,13 +169,13 @@ fn lower_pattern_unadjusted(&mut self, pat: PatId) -> Pat {
}
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 @@ fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
)?,
};
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 @@ fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
}
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| {
@@ -6,7 +6,7 @@
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 @@ fn variant_id_for_adt(
}
// 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<Item = (LocalFieldId, Ty)> + Captures<'a> + Captures<'db> {
) -> impl Iterator<Item = (LocalFieldId, Ty)> {
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 @@ pub(crate) fn lower_pat(&self, pat: &Pat) -> DeconstructedPat<'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 @@ fn ctor_arity(
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()
}
}
_ => {
@@ -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 @@ fn hir_fmt(
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 @@ fn hir_fmt(
f.write_joined(
generic_params
.where_predicates()
.iter()
.filter_map(|it| match it {
WherePredicate::TypeBound { target, bound }
| WherePredicate::ForLifetime { lifetimes: _, target, bound }
@@ -101,7 +101,7 @@ pub fn dyn_compatibility_of_trait_with_callback<F>(
// 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()
@@ -60,7 +60,16 @@ pub(crate) fn store(&self) -> &ExpressionStore {
}
pub(crate) fn where_predicates(&self) -> impl Iterator<Item = &WherePredicate> {
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<Item = GenericParamId> + '_ {
@@ -1813,7 +1813,7 @@ fn resolve_lang_item(&self, item: LangItem) -> Option<LangItemTarget> {
}
fn resolve_output_on(&self, trait_: TraitId) -> Option<TypeAliasId> {
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<TraitId> {
@@ -382,7 +382,7 @@ fn pointer_kind(ty: &Ty, table: &mut InferenceTable<'_>) -> Result<Option<Pointe
return Err(());
};
let struct_data = table.db.variant_fields(id.into());
let struct_data = id.fields(table.db);
if let Some((last_field, _)) = struct_data.fields().iter().last() {
let last_field_ty =
table.db.field_types(id.into())[last_field].clone().substitute(Interner, subst);
@@ -677,7 +677,7 @@ pub fn place_to_name(&self, owner: DefWithBodyId, db: &dyn HirDatabase) -> Strin
match proj {
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 => {
result.push('_');
@@ -720,7 +720,7 @@ pub fn display_place_source_code(&self, owner: DefWithBodyId, db: &dyn HirDataba
// 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 @@ pub fn display_place(&self, owner: DefWithBodyId, db: &dyn HirDatabase) -> Strin
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 @@ fn walk_expr_without_adjust(&mut self, tgt_expr: ExprId) {
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 @@ fn consume_with_pat(&mut self, mut place: HirPlace, tgt_pat: PatId) {
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 @@ fn consume_with_pat(&mut self, mut place: HirPlace, tgt_pat: PatId) {
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();
@@ -542,7 +542,7 @@ fn infer_expr_inner(
_ 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 @@ fn infer_expr_inner(
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 @@ fn infer_expr_inner(
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 @@ pub(crate) fn write_fn_trait_method_resolution(
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 @@ fn infer_overloadable_binop(
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 @@ fn lookup_field(
});
}
&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())
}
@@ -129,9 +129,8 @@ fn infer_mut_expr_without_adjust(&mut self, tgt_expr: ExprId, mutability: Mutabi
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 @@ fn infer_mut_expr_without_adjust(&mut self, tgt_expr: ExprId, mutability: Mutabi
});
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;
@@ -38,7 +38,7 @@ pub(super) fn infer_tuple_struct_pat_like(
decl: Option<DeclContext>,
) -> 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 @@ pub(super) fn infer_tuple_struct_pat_like(
_ 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 @@ pub(super) fn infer_record_pat_like(
_ 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);
@@ -278,7 +278,7 @@ fn resolve_trait_assoc_item(
) -> 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 {
@@ -859,7 +859,7 @@ fn callable_sig_from_fn_trait(
] {
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 @@ fn short_circuit_trivial_tys(ty: &Ty) -> Option<bool> {
// 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()
@@ -132,7 +132,7 @@ fn visit_variant(
variant: VariantId,
subst: &Substitution,
) -> ControlFlow<VisiblyUninhabited> {
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;
@@ -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, _)) => {
@@ -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::<Result<SmallVec<_>, _>>()?;
(r, db.enum_signature(e).repr.unwrap_or_default(), false)
}
@@ -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());
@@ -581,11 +581,28 @@ pub(crate) fn lower_type_bound<'b>(
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 @@ fn lower_dyn_trait(&mut self, bounds: &[TypeBound]) -> Ty {
.unwrap_or(it),
None => it,
},
None => static_lifetime(),
None => error_lifetime(),
},
})
.intern(Interner)
@@ -805,7 +822,7 @@ fn named_associated_type_shorthand_candidates<R>(
) -> Option<R> {
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<ArenaMap<LocalFieldId, Binders<Ty>>>, 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<Name>,
) -> 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<TraitEnvironment> {
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 @@ fn generic_predicates_filtered_by<F>(
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 @@ fn generic_predicates_filtered_by<F>(
}
}
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<Binders<Ty>> {
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<Binders<Ty>> {
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 => {
@@ -173,7 +173,7 @@ pub(crate) fn lower_partly_resolved_path(
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) => {
@@ -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_trait_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(
@@ -657,12 +657,12 @@ pub fn new(
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 @@ fn unsizing_ptr_from_addr(
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 @@ fn rec(
}
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 @@ fn rec(
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 @@ fn run_drop_glue_deep(
) -> 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 @@ fn run_drop_glue_deep(
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 @@ fn from_bytes(bytes: &[u8], is_signed: bool) -> Self {
(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)
}
}
}
@@ -1257,9 +1257,8 @@ fn exec_intrinsic(
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(
@@ -31,7 +31,7 @@ fn detect_simd_ty(&self, ty: &Ty) -> Result<(usize, Ty)> {
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");
@@ -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);
}
"#,
);
}
@@ -503,7 +503,7 @@ fn lower_expr_to_place_without_adjust(
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 @@ fn lower_expr_to_place_without_adjust(
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 @@ fn lower_expr_to_place_without_adjust(
place,
Rvalue::Aggregate(
AggregateKind::Adt(st.into(), subst.clone()),
self.db
.variant_fields(st.into())
st.fields(self.db)
.fields()
.iter()
.map(|it| {
@@ -193,9 +193,8 @@ pub(super) fn lower_expr_as_place_without_adjust(
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 @@ fn lower_overloaded_deref(
.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(
@@ -609,7 +609,7 @@ fn pattern_matching_variant(
}
self.pattern_matching_variant_fields(
shape,
&self.db.variant_fields(v.into()),
v.fields(self.db),
variant,
current,
current_else,
@@ -619,7 +619,7 @@ fn pattern_matching_variant(
}
VariantId::StructId(s) => self.pattern_matching_variant_fields(
shape,
&self.db.variant_fields(s.into()),
s.fields(self.db),
variant,
current,
current_else,
@@ -326,7 +326,7 @@ fn f(this: &mut MirPrettyCtx<'_>, local: LocalId, projections: &[PlaceElem]) {
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) => {
@@ -486,7 +486,7 @@ fn visit_scope(
});
}
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()),
@@ -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
}
"#,
);
@@ -67,11 +67,11 @@ trait B: A {}
fn test<'a>(
_: &(dyn A<Assoc = ()> + Send),
//^ &(dyn A<Assoc = ()> + Send + 'static)
//^ &(dyn A<Assoc = ()> + Send)
_: &'a (dyn Send + A<Assoc = ()>),
//^ &'a (dyn A<Assoc = ()> + Send + 'static)
//^ &'a (dyn A<Assoc = ()> + Send)
_: &dyn B<Assoc = ()>,
//^ &(dyn B<Assoc = ()> + 'static)
//^ &(dyn B<Assoc = ()>)
) {}
"#,
);
@@ -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<'?>
"#,
);
}
@@ -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",
]
"#]],
);
@@ -1153,9 +1153,9 @@ fn test(d: &dyn Trait) {
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<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error + Send>> {
let err: Box<dyn Error> = self;
// ^^^^ expected Box<dyn Error + 'static>, got Box<dyn Error + Send + 'static>
// ^^^^ expected Box<dyn Error + '?>, got Box<dyn Error + Send + '?>
// FIXME, type mismatch should not occur
<dyn Error>::downcast(err).map_err(|_| loop {})
//^^^^^^^^^^^^^^^^^^^^^ type: fn downcast<{unknown}>(Box<dyn Error + 'static>) -> Result<Box<{unknown}>, Box<dyn Error + 'static>>
//^^^^^^^^^^^^^^^^^^^^^ type: fn downcast<{unknown}>(Box<dyn Error + '?>) -> Result<Box<{unknown}>, Box<dyn Error + '?>>
}
}
"#,
@@ -629,7 +629,7 @@ fn internal_into_boxed(self) -> Self::Output {
488..522 '{ ... }': ()
498..502 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}>
498..508 'self.order': O
498..515 'self.o...into()': dyn QueryFragment<DB> + 'static
498..515 'self.o...into()': dyn QueryFragment<DB> + '?
"#]],
);
}
@@ -773,7 +773,7 @@ pub trait Service<Request> {
"#,
expect![[r#"
379..383 'self': &'? mut PeerSet<D>
401..424 '{ ... }': dyn Future<Output = ()> + 'static
401..424 '{ ... }': dyn Future<Output = ()> + '?
411..418 'loop {}': !
416..418 '{}': ()
575..579 'self': &'? mut Self
@@ -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<Box<dyn B + 'static, Global>, Global>
776..793 '<[_]> ...to_vec': fn into_vec<Box<dyn B + 'static, Global>, Global>(Box<[Box<dyn B + 'static, Global>], Global>) -> Vec<Box<dyn B + 'static, Global>, Global>
776..850 '<[_]> ...ct)]))': Vec<Box<dyn B + 'static, Global>, Global>
794..849 '#[rust...uct)])': Box<[Box<dyn B + 'static, Global>; 1], Global>
816..848 '[#[rus...ruct)]': [Box<dyn B + 'static, Global>; 1]
755..756 'v': Vec<Box<dyn B + '?, Global>, Global>
776..793 '<[_]> ...to_vec': fn into_vec<Box<dyn B + '?, Global>, Global>(Box<[Box<dyn B + '?, Global>], Global>) -> Vec<Box<dyn B + '?, Global>, Global>
776..850 '<[_]> ...ct)]))': Vec<Box<dyn B + '?, Global>, Global>
794..849 '#[rust...uct)])': Box<[Box<dyn B + '?, Global>; 1], Global>
816..848 '[#[rus...ruct)]': [Box<dyn B + '?, Global>; 1]
817..847 '#[rust...truct)': Box<Astruct, Global>
839..846 'Astruct': Astruct
"#]],

Some files were not shown because too many files have changed in this diff Show More