Revert #138019 after further discussion about how hir-pretty printing should work
After some more discussion, #138019 was probably merged a little fast. Though there probably is a real bug in pretty printing, it is not feasible to add similar pretty printing routines for all attributes, and making this specific exception is likely not desired either. For more context, see post-merge comments on #138019
I kept the tests around, but reverted the hir-pretty change.
r? ```@compiler-errors```
Implement `#[cfg]` in `where` clauses
This PR implements #115590, which supports `#[cfg]` attributes in `where` clauses.
The biggest change is, that it adds `AttrsVec` and `NodeId` to the `ast::WherePredicate` and `HirId` to the `hir::WherePredicate`.
Handle asm const similar to inline const
Previously, asm consts are handled similar to anon consts rather than inline consts. Anon consts are not good at dealing with lifetimes, because `type_of` has lifetimes erased already. Inline consts can deal with lifetimes because they live in an outer typeck context. And since `global_asm!` lacks an outer typeck context, we have implemented asm consts with anon consts while they're in fact more similar to inline consts.
This was changed in #137180, and this means that handling asm consts as inline consts are possible. While as `@compiler-errors` pointed out, `const` currently can't be used with any types with lifetime, this is about to change if #128464 is implemented. This PR is a preparatory PR for that feature.
As an unintentional side effect, fix#117877.
cc `@Amanieu`
r? `@compiler-errors`
It mirrors `ExprKind::Binary`, and contains a `BinOpKind`. This makes
`AssocOp` more like `ExprKind`. Note that the variants removed from
`AssocOp` are all named differently to `BinOpToken`, e.g. `Multiply`
instead of `Mul`, so that's an inconsistency removed.
The commit adds `precedence` and `fixity` methods to `BinOpKind`, and
calls them from the corresponding methods in `AssocOp`. This avoids the
need to create an `AssocOp` from a `BinOpKind` in a bunch of places, and
`AssocOp::from_ast_binop` is removed.
`AssocOp::to_ast_binop` is also no longer needed.
Overall things are shorter and nicer.
Improve a bit HIR pretty printer
This PR improve (a bit) the HIR pretty printer.
It does so by:
- Not printing elided lifetimes (those are not expressible in surface Rust anyway)
- And by rendering implicit self with the shorthand syntax
I also tried fixing some indentation and other things but gave up for now.
Best reviewed commit by commit.
Give `global_asm` a fake body to store typeck results, represent `sym fn` as a hir expr to fix `sym fn` operands with lifetimes
There are a few intertwined problems with `sym fn` operands in both inline and global asm macros.
Specifically, unlike other anon consts, they may evaluate to a type with free regions in them without actually having an item-level type annotation to give them a "proper" type. This is in contrast to named constants, which always have an item-level type annotation, or unnamed constants which are constrained by their position (e.g. a const arg in a turbofish, or a const array length).
Today, we infer the type of the operand by looking at the HIR typeck results; however, those results are region-erased, so during borrowck we ICE since we don't expect to encounter erased regions. We can't just fill this type with something like `'static`, since we may want to use real (free) regions:
```rust
fn foo<'a>() {
asm!("/* ... */", sym bar::<&'a ()>);
}
```
The first idea may be to represent `sym fn` operands using *inline* consts instead of anon consts. This makes sense, since inline consts can reference regions from the parent body (like the `'a` in the example above). However, this introduces a problem with `global_asm!`, which doesn't *have* a parent body; inline consts *must* be associated with a parent body since they are not a body owner of their own. In #116087, I attempted to fix this by using two separate `sym` operands for global and inline asm. However, this led to a lot of confusion and also some unattractive code duplication.
In this PR, I adjust the lowering of `global_asm!` so that it's lowered in a "fake" HIR body. This body contains a single expression which is `ExprKind::InlineAsm`; we don't *use* this HIR body, but it's used in typeck and borrowck so that we can properly infer and validate the the lifetimes of `sym fn` operands.
I then adjust the lowering of `sym fn` to instead be represented with a HIR expression. This is both because it's no longer necessary to represent this operand as an anon const, since it's *just* a path expression, and also more importantly to sidestep yet another ICE (https://github.com/rust-lang/rust/issues/137179), which has to do with the existing code breaking an invariant of def-id creation and anon consts. Specifically, we are not allowed to synthesize a def-id for an anon const when that anon const contains expressions with def-ids whose parent is *not* that anon const. This is somewhat related to https://github.com/rust-lang/rust/pull/130443#issuecomment-2445678945, which is also a place in the compiler where synthesizing anon consts leads to def-id parenting issue.
As a side-effect, this consolidates the type checking for inline and global asm, so it allows us to simplify `InlineAsmCtxt` a bit. It also allows us to delete a bit of hacky code from anon const `type_of` which was there to detect `sym fn` operands specifically. This also could be generalized to support `const` asm operands with types with lifetimes in them. Since we specifically reject these consts today, I'm not going to change the representation of those consts (but they'd just be turned into inline consts).
r? oli-obk -- mostly b/c you're patient and also understand the breadth of the code that this touches, please reassign if you don't want to review this.
Fixes#111709Fixes#96304Fixes#137179
First of all, note that `Map` has three different relevant meanings.
- The `intravisit::Map` trait.
- The `map::Map` struct.
- The `NestedFilter::Map` associated type.
The `intravisit::Map` trait is impl'd twice.
- For `!`, where the methods are all unreachable.
- For `map::Map`, which gets HIR stuff from the `TyCtxt`.
As part of getting rid of `map::Map`, this commit changes `impl
intravisit::Map for map::Map` to `impl intravisit::Map for TyCtxt`. It's
fairly straightforward except various things are renamed, because the
existing names would no longer have made sense.
- `trait intravisit::Map` becomes `trait intravisit::HirTyCtxt`, so named
because it gets some HIR stuff from a `TyCtxt`.
- `NestedFilter::Map` assoc type becomes `NestedFilter::MaybeTyCtxt`,
because it's always `!` or `TyCtxt`.
- `Visitor::nested_visit_map` becomes `Visitor::maybe_tcx`.
I deliberately made the new trait and associated type names different to
avoid the old `type Map: Map` situation, which I found confusing. We now
have `type MaybeTyCtxt: HirTyCtxt`.
`rustc_span::symbol` defines some things that are re-exported from
`rustc_span`, such as `Symbol` and `sym`. But it doesn't re-export some
closely related things such as `Ident` and `kw`. So you can do `use
rustc_span::{Symbol, sym}` but you have to do `use
rustc_span::symbol::{Ident, kw}`, which is inconsistent for no good
reason.
This commit re-exports `Ident`, `kw`, and `MacroRulesNormalizedIdent`,
and changes many `rustc_span::symbol::` qualifiers in `compiler/` to
`rustc_span::`. This is a 200+ net line of code reduction, mostly
because many files with two `use rustc_span` items can be reduced to
one.
Initial implementation of `#[feature(default_field_values]`, proposed in https://github.com/rust-lang/rfcs/pull/3681.
Support default fields in enum struct variant
Allow default values in an enum struct variant definition:
```rust
pub enum Bar {
Foo {
bar: S = S,
baz: i32 = 42 + 3,
}
}
```
Allow using `..` without a base on an enum struct variant
```rust
Bar::Foo { .. }
```
`#[derive(Default)]` doesn't account for these as it is still gating `#[default]` only being allowed on unit variants.
Support `#[derive(Default)]` on enum struct variants with all defaulted fields
```rust
pub enum Bar {
#[default]
Foo {
bar: S = S,
baz: i32 = 42 + 3,
}
}
```
Check for missing fields in typeck instead of mir_build.
Expand test with `const` param case (needs `generic_const_exprs` enabled).
Properly instantiate MIR const
The following works:
```rust
struct S<A> {
a: Vec<A> = Vec::new(),
}
S::<i32> { .. }
```
Add lint for default fields that will always fail const-eval
We *allow* this to happen for API writers that might want to rely on users'
getting a compile error when using the default field, different to the error
that they would get when the field isn't default. We could change this to
*always* error instead of being a lint, if we wanted.
This will *not* catch errors for partially evaluated consts, like when the
expression relies on a const parameter.
Suggestions when encountering `Foo { .. }` without `#[feature(default_field_values)]`:
- Suggest adding a base expression if there are missing fields.
- Suggest enabling the feature if all the missing fields have optional values.
- Suggest removing `..` if there are no missing fields.
Eliminate magic numbers from expression precedence
Context: see https://github.com/rust-lang/rust/pull/133140.
This PR continues on backporting Syn's expression precedence design into rustc. Rustc's design used mysterious integer quantities represented variously as `i8` or `usize` (e.g. `PREC_CLOSURE = -40i8`), a special significance around `0` that is never named, and an extra `PREC_FORCE_PAREN` precedence level that does not correspond to any expression. Syn's design uses a C-like enum with variants that clearly correspond to specific sets of expression kinds.
This PR is a refactoring that has no intended behavior change on its own, but it unblocks other precedence work that rustc's precedence design was poorly suited to accommodate.
- Asymmetrical precedence, so that a pretty-printer can tell `(return 1) + 1` needs parens but `1 + return 1` does not.
- Squashing the `Closure` and `Jump` cases into a single precedence level.
- Numerous remaining false positives and false negatives in rustc pretty-printer's parenthesization of macro metavariables, for example in `$e < rhs` where $e is `lhs as Thing<T>`.
FYI `@fmease` — you don't need to review if rustbot picks someone else, but you mentioned being interested in the followup PRs.
Remove `hir::ArrayLen`
This refactoring removes `hir::ArrayLen`, replacing it with `hir::ConstArg`. To represent inferred array lengths (previously `hir::ArrayLen::Infer`), a new variant `ConstArgKind::Infer` is added.
r? `@BoxyUwU`