Commit Graph

20374 Commits

Author SHA1 Message Date
Scott McMurray ea0c7788c0 re-enable direct bitcasts for Int/Float vector transmutes (but not ones involving pointers) 2025-07-23 08:32:46 -07:00
Scott McMurray 231dddde3e Let codegen_transmute_operand just handle everything
When combined with 143720, this means `rvalue_creates_operand` can just return `true` for *every* `Rvalue`.  (A future PR could consider removing it, though just letting it optimize out is fine for now.)

It's nicer anyway, IMHO, because it avoids needing the layout checks to be consistent in the two places, and thus is an overall reduction in code.  Plus it's a more helpful building block when used in other places this way.
2025-07-23 08:25:13 -07:00
Matthias Krüger 7ec557ce72 Rollup merge of #144298 - Zalathar:empty-span, r=wesleywiser
coverage: Enlarge empty spans during MIR instrumentation, not codegen

This re-lands the part of rust-lang/rust#140847 that was (hopefully) not responsible for the coverage-instrumentation regressions that caused that PR to be reverted.

---

Enlarging empty spans was historically performed during MIR instrumentation, but had to be moved to codegen as part of larger changes in rust-lang/rust#134497, leading to the status quo. But now there should be no reason not to move that step back to its more logical home in instrumentaion.
2025-07-23 15:59:32 +02:00
Matthias Krüger 6f23c08597 Rollup merge of #144290 - makai410:summary-ups, r=jieyouxu
update tests/ui/SUMMARY.md

follow-up of rust-lang/rust#143985 .

r? ```````@jieyouxu```````
2025-07-23 15:59:31 +02:00
Matthias Krüger 16c10c9145 Rollup merge of #144256 - oli-obk:type-id-ice, r=RalfJung
Don't ICE on non-TypeId metadata within TypeId

fixes rust-lang/rust#144253

r? ``````````@RalfJung``````````
2025-07-23 15:59:30 +02:00
Jonathan Brouwer af06bb925f Stop using the old validate_attr logic for stability attributes 2025-07-23 14:31:50 +02:00
Ralf Jung f75595d2cd add codegen test for variadics (also replacing some existing does-this-build tests) 2025-07-23 14:19:14 +02:00
Guillaume Gomez de93fb13fe Add ignore-backends annotations in failing GCC backend ui tests 2025-07-23 13:48:04 +02:00
Jonathan Brouwer 3303534dc8 Update uitest stderrs
Signed-off-by: Jonathan Brouwer <jonathantbrouwer@gmail.com>
2025-07-23 13:33:23 +02:00
Caiweiran 2e49c52855 Fix tests/codegen-llvm/const-vector.rs test failure on riscv64 2025-07-23 11:23:36 +00:00
Caiweiran 3d186ea611 Fix tests/assembly-llvm/dwarf-mixed-versions-lto.rs test failure on riscv64 2025-07-23 11:14:07 +00:00
Scott McMurray 6a5c7e0415 No longer need allocas for consuming Result<!, i32> and similar
In optimized builds GVN gets rid of these already, but in `opt-level=0` we actually make `alloca`s for this, which particularly impacts `?`-style things that use actually-only-one-variant types like this.
2025-07-23 00:09:36 -07:00
Ralf Jung de1b999ff6 atomicrmw on pointers: move integer-pointer cast hacks into backend 2025-07-23 08:32:55 +02:00
Predrag Gruevski 45231fa599 [rustdoc] Display unsafe attrs with edition 2024 unsafe() wrappers. 2025-07-23 00:00:01 +00:00
León Orell Valerian Liehr 9bb9c39fa5 Don't suggest assoc ty bound on non-angle-bracketed problematic assoc ty binding 2025-07-23 01:59:25 +02:00
Alisa Sireneva ed11a39643 Don't special-case llvm.* as nounwind
Certain LLVM intrinsics, such as `llvm.wasm.throw`, can unwind. Marking
them as nounwind causes us to skip cleanup of locals and optimize out
`catch_unwind` under inlining or when `llvm.wasm.throw` is used directly
by user code.

The motivation for forcibly marking llvm.* as nounwind is no longer
present: most intrinsics are linked as `extern "C"` or other
non-unwinding ABIs, so we won't codegen `invoke` for them anyway.
2025-07-23 02:17:54 +03:00
binarycat 94700f8f3f fix regression test 2025-07-22 17:11:48 -05:00
binarycat 293f95fb0c add regression test for RUST-143222 2025-07-22 17:11:48 -05:00
bors a7a1618e6c Auto merge of #144249 - GuillaumeGomez:asm-tests, r=jieyouxu
Rename `tests/{assembly,codegen}` into `tests/{assembly,codegen}-llvm` and ignore these testsuites if configured backend doesn't match

Follow-up of https://github.com/rust-lang/rust/pull/144125.

This PR changes `compiletest` so that `asm` tests are only run if they match the current codegen backend. To better reflect it, I renamed the `tests/ui/asm` folder into `tests/ui/asm-llvm`. Like that, we can add new asm tests for other backends if we want without needing to add extra code to `compiletest`.

Next step will be to use the new code annotations added in rust-lang/rust#144125 to ignore ui tests failing in cg_gcc until it's fixed on our side.

cc `@antoyo` `@oli-obk`
r? `@Kobzol`
2025-07-22 18:39:58 +00:00
yuk1ty 0aa617001a Add a test case for ui test false-sealed-traits-note.rs 2025-07-22 23:31:10 +09:00
Guillaume Gomez a27f3e3fd1 Rename tests/codegen into tests/codegen-llvm 2025-07-22 14:28:48 +02:00
Guillaume Gomez ed93c1783b Rename tests/assembly into tests/assembly-llvm 2025-07-22 14:27:48 +02:00
Zalathar f877aa7d14 coverage: Enlarge empty spans during MIR instrumentation, not codegen
This allows us to assume that coverage spans will only be discarded during
codegen in very unusual situations.
2025-07-22 19:49:54 +10:00
Matthias Krüger 749f895d95 Rollup merge of #144265 - compiler-errors:copy-ice, r=oli-obk
Dont ICE on copy error being suppressed due to overflow

See comment in test file.

Fixes https://github.com/rust-lang/rust/issues/144165
2025-07-22 10:26:16 +02:00
Matthias Krüger cdc79bdbd9 Rollup merge of #144082 - mladedav:dm/pub-priv-tests, r=petrochenkov
tests: cover more `exported_private_dependencies` cases

This PR adds tests for all missing cases from rust-lang/rust#71043 and some on top of that. I believe with this, that issue can be closed.

Some of the lints can be improved, e.g. `provided_impl_trait` and `impl From<PublicWithStdImpl> for OtherType` lint twice.

cc ```@epage``` in case you want to double check I didn't miss anything.
2025-07-22 10:26:14 +02:00
Makai 6df15a172e update SUMMARY.md 2025-07-22 14:59:46 +08:00
Camille GILLOT 6e8762f769 Use less HIR in check_private_in_public. 2025-07-22 01:40:45 +00:00
Ben Kimock c4eb077616 Ensure we codegen and don't internalize the entrypoint 2025-07-21 19:54:37 -04:00
Jens Reidel e1b6cfe62e Rephrase comment to include some tracking issues
Signed-off-by: Jens Reidel <adrian@travitia.xyz>
2025-07-21 21:57:08 +02:00
Noratrieb dad96b107c Use serde for target spec json deserialize
The previous manual parsing of `serde_json::Value` was a lot of
complicated code and extremely error-prone. It was full of janky
behavior like sometimes ignoring type errors, sometimes erroring for
type errors, sometimes warning for type errors, and sometimes just
ICEing for type errors (the icing on the top).

Additionally, many of the error messages about allowed values were out
of date because they were in a completely different place than the
FromStr impls. Overall, the system caused confusion for users.

I also found the old deserialization code annoying to read. Whenever a
`key!` invocation was found, one had to first look for the right macro
arm, and no go to definition could help.

This PR replaces all this manual parsing with a 2-step process involving
serde.
First, the string is parsed into a `TargetSpecJson` struct. This struct
is a 1:1 representation of the spec JSON. It already parses all the
enums and is very simple to read and write.
Then, the fields from this struct are copied into the actual `Target`.
The reason for this two-step process instead of just serializing into a
`Target` is because of a few reasons

 1. There are a few transformations performed between the two formats
 2. The default logic is implemented this way. Otherwise all the default
    field values would have to be spelled out again, which is
    suboptimal. With this logic, they fall out naturally, because
    everything in the json struct is an `Option`.

Overall, the mapping is pretty simple, with the vast majority of fields
just doing a 1:1 mapping that is captured by two macros. I have
deliberately avoided making the macros generic to keep them simple.

All the `FromStr` impls now have the error message right inside them,
which increases the chance of it being up to date. Some "`from_str`"
impls were turned into proper `FromStr` impls to support this.

The new code is much less involved, delegating all the JSON parsing
logic to serde, without any manual type matching.

This change introduces a few breaking changes for consumers. While it is
possible to use this format on stable, it is very much subject to
change, so breaking changes are expected. The hope is also that because
of the way stricter behavior, breaking changes are easier to deal with,
as they come with clearer error messages.

1. Invalid types now always error, everywhere. Previously, they would
   sometimes error, and sometimes just be ignored (which meant the users
   JSON was still broken, just silently!)
2. This now makes use of `deny_unknown_fields` instead of just warning
   on unused fields, which was done previously. Serde doesn't make it
   easy to get such warning behavior, which was the primary reason that
   this now changed. But I think error behavior is very reasonable too.
   If someone has random stale fields in their JSON, it is likely
   because these fields did something at some point but no longer do,
   and the user likely wants to be informed of this so they can figure
   out what to do.

   This is also relevant for the future. If we remove a field but
   someone has it set, it probably makes sense for them to take a look
   whether they need this and should look for alternatives, or whether
   they can just delete it. Overall, the JSON is made more explicit.

This is the only expected breakage, but there could also be small
breakage from small mistakes. All targets roundtrip though, so it can't
be anything too major.
2025-07-21 19:32:44 +02:00
许杰友 Jieyou Xu (Joe) 55a477efb2 Rollup merge of #144246 - jieyouxu:no-dual-test, r=lqd,RalfJung
Don't use another main test file as auxiliary

In this case, the exact extern crate isn't very important, it just needs to not be another main test file.

This is part of the changes needed to address the spurious failures from a main test `../removing-extern-crate.rs` being both an auxiliary and a main test file, causing fs races due to multiple `rustc` processes in multiple test threads trying to build the main test file both as a main test and also as an auxiliary at around the same time.

Part 1 of rust-lang/rust#144237.

r? ``@RalfJung`` (or compiler)
2025-07-22 00:54:32 +08:00
许杰友 Jieyou Xu (Joe) ef4a7fb1b7 Rollup merge of #144080 - jieyouxu:realign, r=BoxyUwU
Mitigate `#[align]` name resolution ambiguity regression with a rename

Mitigates beta regression rust-lang/rust#143834 after a beta backport.

### Background on the beta regression

The name resolution regression arises due to rust-lang/rust#142507 adding a new feature-gated built-in attribute named `#[align]`. However, unfortunately even [introducing new feature-gated unstable built-in attributes can break user code](https://www.github.com/rust-lang/rust/issues/134963) such as

```rs
macro_rules! align {
    () => {
        /* .. */
    };
}

pub(crate) use align; // `use` here becomes ambiguous
```

### Mitigation approach

This PR renames `#[align]` to `#[rustc_align]` to mitigate the beta regression by:

1. Undoing the introduction of a new built-in attribute with a common name, i.e. `#[align]`.
2. Renaming `#[align]` to `#[rustc_align]`. The renamed attribute being `rustc_align` will not introduce new stable breakages, as attributes beginning with `rustc` are reserved and perma-unstable. This does mean existing nightly code using `fn_align` feature will additionally need to specify `#![feature(rustc_attrs)]`.

This PR is very much a short-term mitigation to alleviate time pressure from having to fully fix the current limitation of inevitable name resolution regressions that would arise from adding any built-in attributes. Long-term solutions are discussed in [#t-lang > namespacing macro attrs to reduce conflicts with new adds](https://rust-lang.zulipchat.com/#narrow/channel/213817-t-lang/topic/namespacing.20macro.20attrs.20to.20reduce.20conflicts.20with.20new.20adds/with/529249622).

### Alternative mitigation options

[Various mitigation options were considered during the compiler triage meeting](https://github.com/rust-lang/rust/issues/143834#issuecomment-3084415277), and those consideration are partly reproduced here:

- Reverting the PR doesn't seem very minimal/trivial, and carries risks of its own.
- Rename to a less-common but aim-to-stabilization name is itself not safe nor convenient, because (1) that risks introducing new regressions (i.e. ambiguity against the new name), and (2) lang would have to FCP the new name hastily for the mitigation to land timely and have a chance to be backported. This also makes the path towards stabilization annoying.
- Rename the attribute to a rustc attribute, which will be perma-unstable and does not cause new ambiguities in stable code.
    - This alleviates the time pressure to address *this* regression, or for lang to have to rush an FCP for some new name that can still break user code.
    - This avoids backing out a whole implementation.

### Review advice

This PR is best reviewed commit-by-commit.

- Commit 1 adds a test `tests/ui/attributes/fn-align-nameres-ambiguity-143834.rs` which demonstrates the current name resolution regression re. `align`. This test fails against current master.
- Commit 2 carries out the renames and test reblesses. Notably, commit 2 will cause `tests/ui/attributes/fn-align-nameres-ambiguity-143834.rs` to change from fail (nameres regression) to pass.

This PR, if the approach still seems acceptable, will need a beta-backport to address the beta regression.
2025-07-22 00:54:28 +08:00
许杰友 Jieyou Xu (Joe) 2e0748b185 Rollup merge of #143985 - makai410:rp-rename, r=oli-obk
rustc_public: de-StableMIR-ize

This PR updates relevant docs about StableMIR, basically just rewording StableMIR/SMIR to rustc_public/rustc_public's IR.

The README.md in the `rustc_public` crate is out-dated. I plan to rewrite it after we fork rustc_public into its own repository.

This PR doesn't change the fact that we still use `-Z unpretty=stable-mir` as a rustc parameter for printing the IR, since I feel it's a bit verbose and weird if we use `-Z unpretty=rustc-public-ir`. I was wondering if we can have a short and easy alias for rustc_public's IR.
2025-07-22 00:54:27 +08:00
许杰友 Jieyou Xu (Joe) 1f8b531b54 Rollup merge of #143768 - Randl:const-try, r=oli-obk
Constify Try, From, TryFrom and relevant traits
2025-07-22 00:54:26 +08:00
许杰友 Jieyou Xu (Joe) a99f3af990 Rollup merge of #143430 - cjgillot:extra-lifetime-swap, r=oli-obk
Lower extra lifetimes before normal generic params.

Fixes https://github.com/rust-lang/rust/issues/143413
2025-07-22 00:54:25 +08:00
许杰友 Jieyou Xu (Joe) 5e3eb25125 Rollup merge of #142097 - ZuseZ4:offload-host1, r=oli-obk
gpu offload host code generation

r? ghost

This will generate most of the host side code to use llvm's offload feature.
The first PR will only handle automatic mem-transfers to and from the device.
So if a user calls a kernel, we will copy inputs back and forth, but we won't do the actual kernel launch.
Before merging, we will use LLVM's Info infrastructure to verify that the memcopies match what openmp offloa generates in C++. `LIBOMPTARGET_INFO=-1 ./my_rust_binary` should print that a memcpy to and later from the device is happening.

A follow-up PR will generate the actual device-side kernel which will then do computations on the GPU.
A third PR will implement manual host2device and device2host functionality, but the goal is to minimize cases where a user has to overwrite our default handling due to performance issues.

I'm trying to get a full MVP out first, so this just recognizes GPU functions based on magic names. The final frontend will obviously move this over to use proper macros, like I'm already doing it for the autodiff work.
This work will also be compatible with std::autodiff, so one can differentiate GPU kernels.

Tracking:
- https://github.com/rust-lang/rust/issues/131513
2025-07-22 00:54:24 +08:00
Esteban Küber 8df93e6966 Tweak spans when encountering multiline initializer in move error
```
error[E0507]: cannot move out of `f`, a captured variable in an `FnMut` closure
  --> $DIR/borrowck-call-is-borrow-issue-12224.rs:57:13
   |
LL |     let mut f = move |g: Box<dyn FnMut(isize)>, b: isize| {
   |         ----- captured outer variable
...
LL |     f(Box::new(|a| {
   |                --- captured by this `FnMut` closure
LL |
LL |         foo(f);
   |             ^ move occurs because `f` has type `{closure@$DIR/borrowck-call-is-borrow-issue-12224.rs:52:17: 52:58}`, which does not implement the `Copy` trait
```

instead of

```
error[E0507]: cannot move out of `f`, a captured variable in an `FnMut` closure
  --> $DIR/borrowck-call-is-borrow-issue-12224.rs:57:13
   |
LL |       let mut f = move |g: Box<dyn FnMut(isize)>, b: isize| {
   |  _________-----___-
   | |         |
   | |         captured outer variable
LL | |         let _ = s.len();
LL | |     };
   | |_____- move occurs because `f` has type `{closure@$DIR/borrowck-call-is-borrow-issue-12224.rs:52:17: 52:58}`, which does not implement the `Copy` trait
LL |       f(Box::new(|a| {
   |                  --- captured by this `FnMut` closure
LL |
LL |           foo(f);
   |               ^ `f` is moved here
```
2025-07-21 16:21:23 +00:00
Esteban Küber 5082e6a300 Generalize logic pointing at binding moved into closure
Account not only for `fn` parameters when moving non-`Copy` values into closure, but also for let bindings.

```
error[E0507]: cannot move out of `bar`, a captured variable in an `FnMut` closure
  --> $DIR/borrowck-move-by-capture.rs:9:29
   |
LL |     let bar: Box<_> = Box::new(3);
   |         ---  ------ move occurs because `bar` has type `Box<isize>`, which does not implement the `Copy` trait
   |         |
   |         captured outer variable
LL |     let _g = to_fn_mut(|| {
   |                        -- captured by this `FnMut` closure
LL |         let _h = to_fn_once(move || -> isize { *bar });
   |                             ^^^^^^^^^^^^^^^^   ---- variable moved due to use in closure
   |                             |
   |                             `bar` is moved here
   |
help: consider cloning the value before moving it into the closure
   |
LL ~         let value = bar.clone();
LL ~         let _h = to_fn_once(move || -> isize { value });
   |
```

```
error[E0507]: cannot move out of `y`, a captured variable in an `Fn` closure
  --> $DIR/unboxed-closures-move-upvar-from-non-once-ref-closure.rs:12:9
   |
LL |     let y = vec![format!("World")];
   |         -   ---------------------- move occurs because `y` has type `Vec<String>`, which does not implement the `Copy` trait
   |         |
   |         captured outer variable
LL |     call(|| {
   |          -- captured by this `Fn` closure
LL |         y.into_iter();
   |         ^ ----------- `y` moved due to this method call
   |         |
   |         `y` is moved here
   |
note: `into_iter` takes ownership of the receiver `self`, which moves `y`
  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
help: you can `clone` the value and consume it, but this might not be your desired behavior
   |
LL |         <Vec<String> as Clone>::clone(&y).into_iter();
   |         +++++++++++++++++++++++++++++++ +
help: consider cloning the value if the performance cost is acceptable
   |
LL |         y.clone().into_iter();
   |          ++++++++
```
2025-07-21 16:21:23 +00:00
Esteban Küber 690ae523e5 Tweak borrowck label pointing at !Copy value moved into closure
When encountering a non-`Copy` value that is moved into a closure which is coming directly from a fn parameter, point at the parameter's type when mentioning it is not `Copy`.

Before:

```
error[E0507]: cannot move out of `foo`, a captured variable in an `Fn` closure
  --> f111.rs:14:25
   |
13 | fn do_stuff(foo: Option<Foo>) {
   |             --- captured outer variable
14 |     require_fn_trait(|| async {
   |                      -- ^^^^^ `foo` is moved here
   |                      |
   |                      captured by this `Fn` closure
15 |         if foo.map_or(false, |f| f.foo()) {
   |            ---
   |            |
   |            variable moved due to use in coroutine
   |            move occurs because `foo` has type `Option<Foo>`, which does not implement the `Copy` trait
```

After:

```
error[E0507]: cannot move out of `foo`, a captured variable in an `Fn` closure
  --> f111.rs:14:25
   |
13 | fn do_stuff(foo: Option<Foo>) {
   |             ---  ----------- move occurs because `foo` has type `Option<Foo>`, which does not implement the `Copy` trait
   |             |
   |             captured outer variable
14 |     require_fn_trait(|| async {
   |                      -- ^^^^^ `foo` is moved here
   |                      |
   |                      captured by this `Fn` closure
15 |         if foo.map_or(false, |f| f.foo()) {
   |            --- variable moved due to use in coroutine
```
2025-07-21 16:21:23 +00:00
Michael Goulet b5d36e5294 Dont ICE on copy error being suppressed due to overflow 2025-07-21 16:07:29 +00:00
Oli Scherer b2f8b40633 Don't ICE on non-TypeId metadata within TypeId 2025-07-21 14:23:20 +00:00
Evgenii Zheltonozhskii 3c76e3d002 Constify Try, From, TryFrom 2025-07-21 12:49:45 +03:00
Oli Scherer 4653b7acbd Stabilize const TypeId::of 2025-07-21 09:11:21 +00:00
Jieyou Xu 74ba9cbae4 Don't use another main test file as auxiliary
In this case, the exact extern crate isn't very important.

This is part of the changes needed to address the spurious failures from
a main test `../removing-extern-crate.rs` being both an auxiliary and a
main test file, causing fs races due to multiple `rustc` processes in
multiple test threads trying to build the main test file both as a main
test and also as an auxiliary at around the same time.
2025-07-21 16:58:54 +08:00
bors 67819923ac Auto merge of #144238 - jhpratt:rollup-xb8aida, r=jhpratt
Rollup of 8 pull requests

Successful merges:

 - rust-lang/rust#144144 (tests: Skip supported-crate-types test on musl hosts)
 - rust-lang/rust#144159 (opt-dist: change build_dir field to be an actual build dir)
 - rust-lang/rust#144162 (Debug impls for DropElaborators)
 - rust-lang/rust#144189 (Add non-regression test for rust-lang/rust#144168)
 - rust-lang/rust#144216 (Don't consider unstable fields always-inhabited)
 - rust-lang/rust#144229 (Miri subtree update)
 - rust-lang/rust#144230 (Option::as_slice: fix comment)
 - rust-lang/rust#144235 (Fix run-make tests on musl hosts)

r? `@ghost`
`@rustbot` modify labels: rollup
2025-07-21 08:42:52 +00:00
Jacob Pratt 830b8237de Rollup merge of #144216 - Nadrieril:revert-pin-hack, r=compiler-errors
Don't consider unstable fields always-inhabited

This reverts the hack in https://github.com/rust-lang/rust/pull/133889 now that `Pin`'s field is no longer public.

Fixes https://github.com/rust-lang/rust/issues/143468.

r? ```@compiler-errors```
2025-07-20 23:11:22 -04:00
Jacob Pratt b81b2a7ecf Rollup merge of #144189 - lqd:test-144168, r=petrochenkov
Add non-regression test for #144168

This is a non-regression test for issue rust-lang/rust#144168, reduced from `zerocopy`, to go with https://github.com/rust-lang/rust/pull/144172 since it had no test yet, and we didn't want to delay it from landing.

Closes rust-lang/rust#144168

I've checked that the test does fail without rust-lang/rust#144172.
2025-07-20 23:11:21 -04:00
Jacob Pratt 9fdfaef403 Rollup merge of #144144 - Gelbpunkt:musl-crate-types-test, r=compiler-errors
tests: Skip supported-crate-types test on musl hosts

This test depends on the target-specific default of crt-static for musl targets. However, running the testsuite on a musl host requires setting `crt-static` to `false`, as it wouldn't otherwise be possible to build rustc. This in turn will enable `-Ctarget-feature=-crt-static` for all tests, mismatching the expected `+crt-static` for the musl target tested in this testcase.

Since this test specifically tests the default value of `crt-static` for the musl target, ignoring it entirely makes more sense than manually setting `-Ctarget-feature=+crt-static` here, but both would be valid approaches.
2025-07-20 23:11:20 -04:00
bors e05ab47e6c Auto merge of #143833 - scottmcm:final-mcp-838, r=compiler-errors
Ban projecting into SIMD types [MCP838]

Closes https://github.com/rust-lang/compiler-team/issues/838

The actual compiler change here is tiny; there's just a bazillion tests to update.

~~Since I'm sure I've missed some, for now~~
~~r ghost~~

try-job: test-various
try-job: x86_64-gnu-nopt
2025-07-21 02:31:56 +00:00
Camille GILLOT 538b0004bc Also bail out if predicates contain errors. 2025-07-20 23:15:24 +00:00