Adjust spans into the `for` loops context before creating the new desugaring spans.
When lowering `for` loops, the spans for the `into_iter` call and the `Some` pattern used the span of the provided pattern and head expression. If either of those came from a different `SyntaxContext` this would result in some very strange contexts. e.g.:
```rust
macro_rules! m { ($e:expr) => { { $e } } }
for _ in m!(expr) {}
```
This would result in the `into_iter` call have a context chain of `desugar => m!() => root` which is completely nonsensical; `m!()` does not have a `for` loop. The `into_iter` call also ends up located at `{ $e }` rather than inside the `for _ in _` part.
This fixes that by walking the spans up to the `for` loop's context first. This will not handle adjusting the location of macro variable expansions (e.g. `for _ in $e`), but this does adjust the context to match the `for` loops.
---
This ended up causing rust-lang/rust-clippy#16008. Clippy should be using a `debug_assert` rather than `unreachable`, but it still results in a bug either way.
mgca: Add ConstArg representation for const items
tracking issue: rust-lang/rust#132980fixesrust-lang/rust#131046fixesrust-lang/rust#134641
As part of implementing `min_generic_const_args`, we need to distinguish const items that can be used in the type system, such as in associated const equality projections, from const items containing arbitrary const code, which must be kept out of the type system. Specifically, all "type consts" must be either concrete (no generics) or generic with a trivial expression like `N` or a path to another type const item.
To syntactically distinguish these cases, we require, for now at least, that users annotate all type consts with the `#[type_const]` attribute. Then, we validate that the const's right-hand side is indeed eligible to be a type const and represent it differently in the HIR.
We accomplish this representation using a new `ConstItemRhs` enum in the HIR, and a similar but simpler enum in the AST. When `#[type_const]` is **not** applied to a const (e.g. on stable), we represent const item right-hand sides (rhs's) as HIR bodies, like before. However, when the attribute is applied, we instead lower to a `hir::ConstArg`. This syntactically distinguishes between trivial const args (paths) and arbitrary expressions, which are represented using `AnonConst`s. Then in `generics_of`, we can take advantage of the existing machinery to bar the `AnonConst` rhs's from using parent generics.
Constify trait aliases
Allow `const trait Foo = Bar + [const] Baz;` trait alias declarations. Their rules are the same as with super traits of const traits. So `[const] Baz` or `const Baz` is only required for `[const] Foo` or `const Foo` bounds respectively.
tracking issue rust-lang/rust#41517 (part of the general trait alias feature gate, but I can split it out into a separate const trait alias feature gate. I just assumed that const traits would stabilize before trait aliases, and we'd want to stabilize trait aliases together with const trait aliases at the same time)
r? ``@compiler-errors`` ``@fee1-dead``
Contract variable declarations
This change adds contract variables that can be declared in the `requires` clause and can be referenced both in `requires` and `ensures`, subject to usual borrow checking rules. This allows any setup common to both the `requires` and `ensures` clauses to only be done once.
In particular, one future use case would be for [Fulminate](https://dl.acm.org/doi/10.1145/3704879)-like ownership assertions in contracts, that are essentially side-effects, and executing them twice would alter the semantics of the contract.
As of this change, `requires` can now be an arbitrary sequence of statements, with the final expression being of type `bool`. They are executed in sequence as expected, before checking if the final `bool` expression holds.
This PR depends on rust-lang/rust#144438 (which has now been merged).
Contracts tracking issue: https://github.com/rust-lang/rust/issues/128044
**Other changes introduced**:
- Contract macros now wrap the content in braces to produce blocks, meaning there's no need to wrap the content in `{}` when using multiple statements. The change is backwards compatible, in that wrapping the content in `{}` still works as before. The macros also now treat `requires` and `ensures` uniformally, meaning the `requires` closure is built inside the parser, as opposed to in the macro.
**Known limiatations**:
- Contracts with variable declarations are subject to the regular borrow checking rules, and the way contracts are currently lowered limits the usefulness of contract variable declarations. Consider the below example:
```rust
#[requires(let init_x = *x; true)]
#[ensures(move |_| *x == 2 * init_x)]
fn double_in_place(x: &mut i32) {
*x *= 2;
}
```
We have used the new variable declarations feature to remember the initial value pointed to by `x`, however, moving `x` into the `ensures` does not pass the borrow checker, meaning the above function contract is illegal. Ideally, something like the above should be expressable in contracts.
Mark desugared range expression spans with DesugaringKind::RangeExpr
This is a prerequisite to removing `QPath::LangItem` (rust-lang/rust#115178) because otherwise there would be no way to detect a range expression in the HIR.
There are some non-obvious Clippy changes so a Clippy team review would be good.
Further tighten up relaxed bounds
Follow-up to rust-lang/rust#142693, rust-lang/rust#135331 and rust-lang/rust#135841.
Fixesrust-lang/rust#143122.
* Reject relaxed bounds `?Trait` in the bounds of trait aliases.
Just like `trait Trait {}` doesn't mean `trait Trait: Sized {}` and we therefore reject `trait Trait: ?Sized {}`, `trait Trait =;` (sic!) doesn't mean `trait Trait = Sized;` (never did!) and as a logical consequence `trait Trait = ?Sized;` is meaningless and should be forbidden.
* Don't permit `?Sized` in more places (e.g., supertrait bounds, trait object types) if feature `more_maybe_bounds` is enabled.
That internal feature is only meant to allow the user to define & use *new* default traits (that have fewer rules to follow for now to ease experimentation).
* Unconditionally check that the `Trait` in `?Trait` is a default trait.
Previously, we would only perform this check in selected places which was very brittle and led to bugs slipping through.
* Slightly improve diagnostics.
Contract variables can be declared in the `requires` clause and
can be referenced both in `requires` and `ensures`, subject to usual
borrow checking rules.
This allows any setup common to both the `requires` and `ensures`
clauses to only be done once.
The internal feature `more_maybe_bounds` doesn't influence sized elaboration in
HIR ty lowering and therefore doesn't get to dictate where `?Sized` is allowed.
Guard HIR lowered contracts with `contract_checks`
Refactor contract HIR lowering to ensure no contract code is executed when contract-checks are disabled.
The call to `contract_checks` is moved to inside the lowered fn body, and contract closures are built conditionally, ensuring no side-effects present in contracts occur when those are disabled. This partially addresses rust-lang/rust#139548, i.e. the bad behavior no longer happens with contract checks disabled (`-Zcontract-checks=no`).
The change is made in preparation for adding contract variable declarations - variables declared before the `requires` assertion, and accessible from both `requires` and `ensures`, but not in the function body (PR rust-lang/rust#144444). As those declarations may also have side-effects, it's good to guard them with `contract_checks` - the new lowering approach allows for this to be done easily.
Contracts tracking issue: rust-lang/rust#128044
**Known limiatations**:
- It is still possible to early return from the *function* from within a contract, e.g.
```rust
#[ensures({if x > 0 { return 0 }; |_| true})]
fn foo(x: u32) -> i32 {
42
}
```
When `foo` is called with an argument greater than 0, instead of `42`, `0` will be returned.
As this is not a regression, it is not addressed in this PR. However, it may be worth revisiting later down the line, as users may expect a form of early return from *contract specifications*, and so returning from the entire *function* could cause confusion.
- ~Contracts are still not optimised out when disabled. Currently, even when contracts are disabled, the code generated causes existing optimisations to fail, meaning even disabled contracts could impact runtime performance. This issue is blocking rust-lang/rust#136578, and has not been addressed in this PR, i.e. the `mir-opt` and `codegen` tests that fail in rust-lang/rust#136578 still fail with these new HIR lowering changes.~ Contracts should now be optimised out when disabled, however some regressions tests still need to be added to be sure that is indeed the case.