Commit graph

2950 commits

Author SHA1 Message Date
Michael Goulet
6033e9df02 Don't compute name of associated item if it's an RPITIT 2025-04-20 16:08:39 +00:00
Matthias Krüger
c8a9095f0f
Rollup merge of #138528 - dianne:implicit-deref-patterns, r=Nadrieril
deref patterns: implement implicit deref patterns

This implements implicit deref patterns (per https://hackmd.io/4qDDMcvyQ-GDB089IPcHGg#Implicit-deref-patterns) and adds tests and an unstable book chapter.

Best reviewed commit-by-commit. Overall there's a lot of additions, but a lot of that is tests, documentation, and simple(?) refactoring.

Tracking issue: #87121

r? ``@Nadrieril``
2025-04-18 05:16:28 +02:00
dianne
977c9ab7a2 respect the tcx's recursion limit when peeling 2025-04-16 15:42:12 -07:00
Matthias Krüger
8e5df28a6a
Rollup merge of #139770 - nnethercote:rename-LifetimeName, r=BoxyUwU
Rename `LifetimeName` as `LifetimeKind`.

It's a much better name, more consistent with how we name such things.

Also rename `Lifetime::res` as `Lifetime::kind` to match. I suspect this field used to have the type `LifetimeRes` and then the type was changed but the field name remained the same.

r? ``@BoxyUwU``
2025-04-17 00:14:26 +02:00
Nicholas Nethercote
fe882bf330 Rename LifetimeName as LifetimeKind.
It's a much better name, more consistent with how we name such things.

Also rename `Lifetime::res` as `Lifetime::kind` to match. I suspect this
field used to have the type `LifetimeRes` and then the type was changed
but the field name remained the same.
2025-04-16 07:16:40 +10:00
Michael Goulet
11e5987d01 Don't compute name of associated item if it's an RPITIT 2025-04-15 18:46:26 +00:00
bors
f433fa46b0 Auto merge of #139845 - Zalathar:rollup-u5u5y1v, r=Zalathar
Rollup of 17 pull requests

Successful merges:

 - #138374 (Enable contracts for const functions)
 - #138380 (ci: add runners for vanilla LLVM 20)
 - #138393 (Allow const patterns of matches to contain pattern types)
 - #139517 (std: sys: process: uefi: Use NULL stdin by default)
 - #139554 (std: add Output::exit_ok)
 - #139660 (compiletest: Add an experimental new executor to replace libtest)
 - #139669 (Overhaul `AssocItem`)
 - #139671 (Proc macro span API redesign: Replace proc_macro::SourceFile by Span::{file, local_file})
 - #139750 (std/thread: Use default stack size from menuconfig for NuttX)
 - #139772 (Remove `hir::Map`)
 - #139785 (Let CStrings be either 1 or 2 byte aligned.)
 - #139789 (do not unnecessarily leak auto traits in item bounds)
 - #139791 (drop global where-bounds before merging candidates)
 - #139798 (normalize: prefer `ParamEnv` over `AliasBound` candidates)
 - #139822 (Fix: Map EOPNOTSUPP to ErrorKind::Unsupported on Unix)
 - #139833 (Fix some HIR pretty-printing problems)
 - #139836 (Basic tests of MPMC receiver cloning)

r? `@ghost`
`@rustbot` modify labels: rollup
2025-04-15 08:02:23 +00:00
Stuart Cook
13cd5256ac
Rollup merge of #139669 - nnethercote:overhaul-AssocItem, r=oli-obk
Overhaul `AssocItem`

`AssocItem` has multiple fields that only make sense some of the time. E.g. the `name` can be empty if it's an RPITIT associated type. It's clearer and less error prone if these fields are moved to the relevant `kind` variants.

r? ``@fee1-dead``
2025-04-15 15:47:27 +10:00
Stuart Cook
380ad1b5d4
Rollup merge of #138374 - celinval:issue-136925-const-contract, r=compiler-errors,oli-obk,RalfJung
Enable contracts for const functions

Use `const_eval_select!()` macro to enable contract checking only at runtime. The existing contract logic relies on closures, which are not supported in constant functions.

This commit also removes one level of indirection for ensures clauses since we no longer build a closure around the ensures predicate.

Resolves #136925

**Call-out:** This is still a draft PR since CI is broken due to a new warning message for unreachable code when the bottom of the function is indeed unreachable. It's not clear to me why the warning wasn't triggered before.

r? ```@compiler-errors```
2025-04-15 15:47:24 +10:00
Nicholas Nethercote
78599d83e7 Move name field from AssocItem to AssocKind variants.
To accurately reflect that RPITIT assoc items don't have a name. This
avoids the use of `kw::Empty` to mean "no name", which is error prone.

Helps with #137978.
2025-04-15 08:07:15 +10:00
Nicholas Nethercote
89e93a51c8 Move two methods from AssocKind to AssocItem.
Because all the other similar methods are on `AssocItem`.
2025-04-15 08:07:15 +10:00
Nicholas Nethercote
b26f3d4347 Move opt_rpitit_info field to hir::AssocKind::Type.
From `hir::AssocItem`.
2025-04-15 08:06:59 +10:00
Yotam Ofek
4b63362f3d Use newtype_index!-generated types more idiomatically 2025-04-14 16:17:06 +00:00
Nicholas Nethercote
ce2aa97cd6 Move has_self field to hir::AssocKind::Fn.
`hir::AssocItem` currently has a boolean `fn_has_self_parameter` field,
which is misplaced, because it's only relevant for associated fns, not
for associated consts or types. This commit moves it (and renames it) to
the `AssocKind::Fn` variant, where it belongs.

This requires introducing a new C-style enum, `AssocTag`, which is like
`AssocKind` but without the fields. This is because `AssocKind` values
are passed to various functions like `find_by_ident_and_kind` to
indicate what kind of associated item should be searched for, and having
to specify `has_self` isn't relevant there.

New methods:
- Predicates `AssocItem::is_fn` and `AssocItem::is_method`.
- `AssocItem::as_tag` which converts `AssocItem::kind` to `AssocTag`.

Removed `find_by_name_and_kinds`, which is unused.

`AssocItem::descr` can now distinguish between methods and associated
functions, which slightly improves some error messages.
2025-04-14 16:13:04 +10:00
bors
f836ae4e66 Auto merge of #124141 - nnethercote:rm-Nonterminal-and-TokenKind-Interpolated, r=petrochenkov
Remove `Nonterminal` and `TokenKind::Interpolated`

A third attempt at this; the first attempt was #96724 and the second was #114647.

r? `@ghost`
2025-04-14 03:56:55 +00:00
Stuart Cook
45ebc4060b
Rollup merge of #137447 - folkertdev:simd-extract-insert-dyn, r=scottmcm
add `core::intrinsics::simd::{simd_extract_dyn, simd_insert_dyn}`

fixes https://github.com/rust-lang/rust/issues/137372

adds `core::intrinsics::simd::{simd_extract_dyn, simd_insert_dyn}`, which contrary to their non-dyn counterparts allow a non-const index. Many platforms (but notably not x86_64 or aarch64) have dedicated instructions for this operation, which stdarch can emit with this change.

Future work is to also make the `Index` operation on the `Simd` type emit this operation, but the intrinsic can't be used directly. We'll need some MIR shenanigans for that.

r? `@ghost`
2025-04-11 13:31:43 +10:00
Folkert de Vries
59c55339af
add simd_insert_dyn and simd_extract_dyn 2025-04-10 21:22:07 +02:00
Matthias Krüger
79f357e63d
Rollup merge of #139510 - nnethercote:name-to-ident, r=fee1-dead
Rename some `name` variables as `ident`.

It bugs me when variables of type `Ident` are called `name`. It leads to silly things like `name.name`. `Ident` variables should be called `ident`, and `name` should be used for variables of type `Symbol`.

This commit improves things by by doing `s/name/ident/` on a bunch of `Ident` variables. Not all of them, but a decent chunk.

r? `@fee1-dead`
2025-04-10 17:27:14 +02:00
Matthias Krüger
c808b20360
Rollup merge of #139530 - oli-obk:rustc-intrinsic-cleanup, r=RalfJung
Remove some dead or leftover code related to rustc-intrinsic abi removal

r? ```@RalfJung```

PR that removed the ABI: https://github.com/rust-lang/rust/pull/139455

tracking issue: https://github.com/rust-lang/rust/issues/132735
2025-04-10 11:10:16 +02:00
Nicholas Nethercote
1b3fc585cb Rename some name variables as ident.
It bugs me when variables of type `Ident` are called `name`. It leads to
silly things like `name.name`. `Ident` variables should be called
`ident`, and `name` should be used for variables of type `Symbol`.

This commit improves things by by doing `s/name/ident/` on a bunch of
`Ident` variables. Not all of them, but a decent chunk.
2025-04-10 09:30:55 +10:00
Michael Goulet
830aeb6102 Use a query rather than recomputing the tail repeatedly 2025-04-09 20:26:58 +00:00
Michael Goulet
27836e1e57 Rigidly project missing item due to guaranteed impossible sized predicate 2025-04-09 20:26:57 +00:00
Oli Scherer
b2aa9d0620 Remove some dead or leftover code related to rustc-intrinsic abi removal 2025-04-09 07:57:13 +00:00
bors
97c966bb40 Auto merge of #139552 - matthiaskrgr:rollup-b194mk8, r=matthiaskrgr
Rollup of 10 pull requests

Successful merges:

 - #139494 (Restrict some queries by def-kind more)
 - #139496 (Revert r-a changes of rust-lang/rust#139455)
 - #139506 (add missing word in doc comment (part 2))
 - #139515 (Improve presentation of closure signature mismatch from `Fn` trait goal)
 - #139520 (compiletest maintenance: sort deps and drop dep on `anyhow`)
 - #139523 (Rustc dev guide subtree update)
 - #139526 (Fix deprecation note for std::intrinsics)
 - #139528 (compiletest: Remove the `--logfile` flag)
 - #139541 (Instantiate higher-ranked transmute goal w/ placeholders before emitting sub-obligations)
 - #139547 (Update library tracking issue template to set S-tracking-unimplemented)

r? `@ghost`
`@rustbot` modify labels: rollup
2025-04-09 05:39:18 +00:00
bors
de5b8a4c77 Auto merge of #139536 - matthiaskrgr:rollup-j6goald, r=matthiaskrgr
Rollup of 7 pull requests

Successful merges:

 - #139476 (rm `RegionInferenceContext::var_infos`)
 - #139485 (compiletest: Stricter parsing for diagnostic kinds)
 - #139491 (Update books)
 - #139500 (document panic behavior of Vec::resize and Vec::resize_with)
 - #139501 (Fix stack overflow in exhaustiveness due to recursive HIR opaque hidden types)
 - #139504 (add missing word in doc comment)
 - #139509 (clean: remove Deref<Target=RegionKind> impl for Region and use `.kind()`)

r? `@ghost`
`@rustbot` modify labels: rollup
2025-04-08 22:51:10 +00:00
Matthias Krüger
894f471d1e
Rollup merge of #139494 - compiler-errors:restrict-queries, r=oli-obk
Restrict some queries by def-kind more

Random cleanup. I prefer things to assert more so as to catch bugs :)

r? oli-obk
2025-04-08 21:25:57 +02:00
Celina G. Val
3feac59b79 Fix unreachable expression warning
Invert the order that we pass the arguments to the
`contract_check_ensures` function to avoid the warning when the tail
of the function is unreachable.

Note that the call itself is also unreachable, but we have already
handled that case by ignoring unreachable call for contract calls.
2025-04-08 10:46:31 -07:00
Matthias Krüger
1cbf8b56af
Rollup merge of #139509 - xizheyin:issue-139359, r=lcnr
clean: remove Deref<Target=RegionKind> impl for Region and use `.kind()`

Closes #139359

r? `@lcnr`
2025-04-08 18:05:34 +02:00
bors
d4f880f8ce Auto merge of #138499 - lcnr:borrowck-typeck_root, r=oli-obk
borrowck typeck children together with their root

This introduces new cycle errors, even with `feature(inline_const_pat)` removed, see the `non-structural-match-types-cycle-err.rs` test.

The new cycle error happens as the layout of `async`-blocks relies on their `optimized_mir`. As that now depends on `mir_borrowck` of its typeck parent, computing the layout of an `async`-block during MIR building, e.g. when evaluating a named `const` pattern. I think there's currently no way to have a named const pattern whose type references an async block while being allowed? cc `@oli-obk` `@RalfJung`

I cannot think of other cases where we currently rely on the MIR of a typeck children while borrowchecking their parent. The crater run came back without any breakage. My work here will prevent any future features which rely on this as we'll get locked into borrowchecking them together as I continue to work on https://github.com/rust-lang/types-team/issues/129, cc `@rust-lang/types.`

r? compiler-errors
2025-04-08 16:01:37 +00:00
Stuart Cook
133cec7363
Rollup merge of #139346 - compiler-errors:non-lifetime-binder-diag-hir-wf-check, r=oli-obk
Don't construct preds w escaping bound vars in `diagnostic_hir_wf_check`

See comment inline.

Fixes #139330

r? oli-obk
2025-04-08 20:55:07 +10:00
Stuart Cook
5913c5248b
Rollup merge of #139124 - xtexx:gh-139082, r=compiler-errors
compiler: report error when trait object type param reference self

Fixes #139082.

Emits an error when `Self` is found in the projection bounds of a trait
object. In type aliases, `Self` has no meaning, so `type A = &'static
dyn B` where `trait B = Fn() -> Self` will expands to `type A = &'static
Fn() -> Self` which is illegal, causing the region solver to bail out
when hitting the uninferred Self.

r? ````@compiler-errors```` ````@fee1-dead````
2025-04-08 20:55:04 +10:00
xizheyin
c7272a6cbc
clean code: remove Deref<Target=RegionKind> impl for Region and use .kind()
Signed-off-by: xizheyin <xizheyin@smail.nju.edu.cn>
2025-04-08 10:51:41 +08:00
lcnr
f05a23be5c borrowck typeck children together with their parent 2025-04-08 00:34:40 +02:00
Michael Goulet
268c56e144 Implement overflow for infinite implied lifetime bounds 2025-04-07 21:01:24 +00:00
Celina G. Val
b9754f9e7b Enable contracts for const functions
Use `const_eval_select!()` macro to enable contract checking only at
runtime. The existing contract logic relies on closures,
which are not supported in constant functions.

This commit also removes one level of indirection for ensures clauses,
however, it currently has a spurious warning message when the bottom
of the function is unreachable.
2025-04-07 11:17:33 -07:00
Michael Goulet
14d1215719 Restrict some queries by def-kind more 2025-04-07 18:10:28 +00:00
Stuart Cook
9209c5eb60
Rollup merge of #139455 - Skgland:remove_rust-intrinsic_ABI, r=oli-obk
Remove support for `extern "rust-intrinsic"` blocks

Part of rust-lang/rust#132735

Looked manageable and there didn't appear to have been progress in the last two weeks,
so decided to give it a try.
2025-04-07 22:29:20 +10:00
Stuart Cook
f4c429fde5
Rollup merge of #139365 - Bryanskiy:leak-perf, r=lcnr
Default auto traits: fix perf

Skip computing `requires_default_supertraits` if `experimental-default-bounds` option is not enabled. Possible perf fix for https://github.com/rust-lang/rust/pull/120706

r? lcnr
2025-04-07 22:29:19 +10:00
Stuart Cook
27c6e40755
Rollup merge of #139112 - m-ou-se:super-let, r=lcnr
Implement `super let`

Tracking issue: https://github.com/rust-lang/rust/issues/139076

This implements `super let` as proposed in #139080, based on the following two equivalence rules.

1. For all expressions `$expr` in any context, these are equivalent:
  - `& $expr`
  - `{ super let a = & $expr; a }`

2. And, additionally, these are equivalent in any context when `$expr` is a temporary (aka rvalue):
  - `& $expr`
  - `{ super let a = $expr; & a }`

So far, this experiment has a few interesting results:

## Interesting result 1

In this snippet:

```rust
super let a = f(&temp());
```

I originally expected temporary `temp()` would be dropped at the end of the statement (`;`), just like in a regular `let`, because `temp()` is not subject to temporary lifetime extension.

However, it turns out that that would break the fundamental equivalence rules.

For example, in

```rust
g(&f(&temp()));
```

the temporary `temp()` will be dropped at the `;`.

The first equivalence rule tells us this must be equivalent:

```rust
g({ super let a = &f(&temp()); a });
```

But that means that `temp()` must live until the last `;` (after `g()`), not just the first `;` (after `f()`).

While this was somewhat surprising to me at first, it does match the exact behavior we need for `pin!()`: The following _should work_. (See also https://github.com/rust-lang/rust/issues/138718)

```rust
g(pin!(f(&mut temp())));
```

Here, `temp()` lives until the end of the statement. This makes sense from the perspective of the user, as no other `;` or `{}` are visible. Whether `pin!()` uses a `{}` block internally or not should be irrelevant.

This means that _nothing_ in a `super let` statement will be dropped at the end of that super let statement. It does not even need its own scope.

This raises questions that are useful for later on:

- Will this make temporaries live _too long_ in cases where `super let` is used not in a hidden block in a macro, but as a visible statement in code like the following?

    ```rust
    let writer = {
        super let file = File::create(&format!("/home/{user}/test"));
        Writer::new(&file)
    };
    ```

- Is a `let` statement in a block still the right syntax for this? Considering it has _no_ scope of its own, maybe neither a block nor a statement should be involved

This leads me to think that instead of `{ super let $pat = $init; $expr }`, we might want to consider something like `let $pat = $init in $expr` or `$expr where $pat = $init`. Although there are also issues with these, as it isn't obvious anymore if `$init` should be subject to temporary lifetime extension. (Do we want both `let _ = _ in ..` and `super let _ = _ in ..`?)

## Interesting result 2

What about `super let x;` without initializer?

```rust
let a = {
    super let x;
    x = temp();
    &x
};
```

This works fine with the implementation in this PR: `x` is extended to live as long as `a`.

While it matches my expectations, a somewhat interesting thing to realize is that these are _not_ equivalent:

- `super let x = $expr;`
- `super let x; x = $expr;`

In the first case, all temporaries in $expr will live at least as long as (the result of) the surrounding block.
In the second case, temporaries will be dropped at the end of the assignment statement. (Because the assignment statement itself "is not `super`".)

This difference in behavior might be confusing, but it _might_ be useful.
One might want to extend the lifetime of a variable without extending all the temporaries in the initializer expression.

On the other hand, that can also be expressed as:

- `let x = $expr; super let x = x;` (w/o temporary lifetime extension), or
- `super let x = { $expr };` (w/ temporary lifetime extension)

So, this raises these questions:

- Do we want to accept `super let x;` without initializer at all?

- Does it make sense for statements other than let statements to be "super"? An expression statement also drops temporaries at its `;`, so now that we discovered that `super let` basically disables that `;` (see interesting result 1), is there a use to having other statements without their own scope? (I don't think that's ever useful?)

## Interesting result 3

This works now:

```rust
super let Some(x) = a.get(i) else { return };
```

I didn't put in any special cases for `super let else`. This is just the behavior that 'naturally' falls out when implementing `super let` without thinking of the `let else` case.

- Should `super let else` work?

## Interesting result 4

This 'works':

```rust
fn main() {
    super let a = 123;
}
```

I didn't put in any special cases for `super let` at function scope. I had expected the code to cause an ICE or other weird failure when used at function body scope, because there's no way to let the variable live as long as the result of the function.

This raises the question:

- Does this mean that this behavior is the natural/expected behavior when `super let` is used at function scope? Or is this just a quirk and should we explicitly disallow `super let` in a function body? (Probably the latter.)

---

The questions above do not need an answer to land this PR. These questions should be considered when redesigning/rfc'ing/stabilizing the feature.
2025-04-07 22:29:18 +10:00
Stuart Cook
82df6229b6
Rollup merge of #139035 - nnethercote:PatKind-Missing, r=oli-obk
Add new `PatKind::Missing` variants

To avoid some ugly uses of `kw::Empty` when handling "missing" patterns, e.g. in bare fn tys. Helps with #137978. Details in the individual commits.

r? ``@oli-obk``
2025-04-07 22:29:17 +10:00
Michael Goulet
c51c448fae More trivial tweaks 2025-04-07 05:07:11 +00:00
Skgland
5eb535c568
remove compiler support for extern "rust-intrinsic" blocks 2025-04-06 21:32:58 +02:00
bors
bad13a970a Auto merge of #139390 - matthiaskrgr:rollup-l64euwx, r=matthiaskrgr
Rollup of 9 pull requests

Successful merges:

 - #139041 (Remove `rustc_middle::ty::util::ExplicitSelf`.)
 - #139328 (Fix 2024 edition doctest panic output)
 - #139339 (unstable book: document tait)
 - #139348 (AsyncDestructor: replace fields with impl_did)
 - #139353 (Fix `Debug` impl for `LateParamRegionKind`.)
 - #139366 (ToSocketAddrs: fix typo)
 - #139374 (Use the span of the whole bound when the diagnostic talks about a bound)
 - #139378 (Use target-agnostic LLD flags in bootstrap for `use-lld`)
 - #139384 (Add `compiletest` adhoc_group for `r? compiletest`)

r? `@ghost`
`@rustbot` modify labels: rollup
2025-04-04 23:03:57 +00:00
Michael Goulet
f343b9d1fd Don't construct preds w escaping bound vars in diagnostic_hir_wf_check 2025-04-04 21:09:32 +00:00
Matthias Krüger
f074bbff7a
Rollup merge of #139374 - oli-obk:const-trait-bound, r=compiler-errors
Use the span of the whole bound when the diagnostic talks about a bound

While it makes sense that the host predicate only points to the `~const` part, as whether the actual trait bound is satisfied is checked separately, the user facing diagnostic is talking about the entire trait bound, at which point it makes more sense to just highlight the entire bound

r? `@compiler-errors` or `@fee1-dead`
2025-04-04 21:55:00 +02:00
Matthias Krüger
00f608af18
Rollup merge of #139041 - nnethercote:rm-rustc_middle-ty-util-ExplicitSelf, r=BoxyUwU
Remove `rustc_middle::ty::util::ExplicitSelf`.

It's an old (2017 or earlier) type that describes a `self` receiver. It's only used in `rustc_hir_analysis` for two error messages, and much of the complexity isn't used. I suspect it used to be used for more things.

This commit removes it, and moves a greatly simplified version of the `determine` method into `rustc_hir_analysis`, renamed as `get_self_string`. The big comment on the method is removed because it no longer seems relevant.

r? `@BoxyUwU`
2025-04-04 21:54:56 +02:00
bors
17ffbc81a3 Auto merge of #138785 - lcnr:typing-mode-borrowck, r=compiler-errors,oli-obk
add `TypingMode::Borrowck`

Shares the first commit with #138499, doesn't really matter which PR to land first 😊 😁

Introduces `TypingMode::Borrowck` which unlike `TypingMode::Analysis`, uses the hidden type computed by HIR typeck as the initial value of opaques instead of an unconstrained infer var. This is a part of https://github.com/rust-lang/types-team/issues/129.

Using this new `TypingMode` is unfortunately a breaking change for now, see tests/ui/impl-trait/non-defining-uses/as-projection-term.rs. Using an inference variable as the initial value results in non-defining uses in the defining scope. We therefore only enable it if with `-Znext-solver=globally` or `-Ztyping-mode-borrowck`

To do that the PR contains the following changes:
- `TypeckResults::concrete_opaque_type` are already mapped to the definition of the opaque type
  - writeback now checks that the non-lifetime parameters of the opaque are universal
  - for this, `fn check_opaque_type_parameter_valid` is moved from `rustc_borrowck` to `rustc_trait_selection`
- we add a new `query type_of_opaque_hir_typeck` which, using the same visitors as MIR typeck, attempts to merge the hidden types from HIR typeck from all defining scopes
  - done by adding a `DefiningScopeKind` flag to toggle between using borrowck and HIR typeck
  - the visitors stop checking that the MIR type matches the HIR type. This is trivial as the HIR type are now used as the initial hidden types of the opaque. This check is useful as a safeguard when not using `TypingMode::Borrowck`, but adding it to the new structure is annoying and it's not soundness critical, so I intend to not add it back.
- add a `TypingMode::Borrowck`  which behaves just like `TypingMode::Analysis` except when normalizing opaque types
   - it uses `type_of_opaque_hir_typeck(opaque)` as the initial value after replacing its regions with new inference vars
   - it uses structural lookup in the new solver

fixes #112201, fixes #132335, fixes #137751

r? `@compiler-errors` `@oli-obk`
2025-04-04 19:54:42 +00:00
Oli Scherer
a69a219f96 Use the span of the whole bound when the diagnostic talks about a bound 2025-04-04 13:39:50 +00:00
Bryanskiy
0522ed059d Default auto traits: fix perf 2025-04-04 15:32:00 +03:00
Mara Bos
3e6cc7689d Boolean hate. 2025-04-04 09:44:22 +02:00