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`
Pass correct param-env to `error_implies`
Duplicated comment from the test:
In the error reporting code, when reporting fulfillment errors for goals A and B, we try to see if elaborating A will result in another goal that can equate with B. That would signal that B is "implied by" A, allowing us to skip reporting it, which is beneficial for cutting down on the number of diagnostics we report.
In the new trait solver especially, but even in the old trait solver through things like defining opaque type usages, this `can_equate` call was not properly taking the param-env of the goals, resulting in nested obligations that had empty param-envs. If one of these nested obligations was a `ConstParamHasTy` goal, then we would ICE, since those goals are particularly strict about the param-env they're evaluated in.
This is morally a fix for <https://github.com/rust-lang/rust/issues/139314>, but that repro uses details about how defining usages in the `check_opaque_well_formed` code can spring out of type equality, and will likely stop failing soon coincidentally once we start using `PostBorrowck` mode in that check. Instead, we use lazy normalization to end up generating an alias-eq goal whose nested goals woul trigger the ICE instead, since this is a lot more stable.
Fixes https://github.com/rust-lang/rust/issues/139314
r? ``@oli-obk`` or reassign
Initial support for auto traits with default bounds
This PR is part of ["MCP: Low level components for async drop"](https://github.com/rust-lang/compiler-team/issues/727)
Tracking issue: #138781
Summary: https://github.com/rust-lang/rust/pull/120706#issuecomment-1934006762
### Intro
Sometimes we want to use type system to express specific behavior and provide safety guarantees. This behavior can be specified by various "marker" traits. For example, we use `Send` and `Sync` to keep track of which types are thread safe. As the language develops, there are more problems that could be solved by adding new marker traits:
- to forbid types with an async destructor to be dropped in a synchronous context a trait like `SyncDrop` could be used [Async destructors, async genericity and completion futures](https://sabrinajewson.org/blog/async-drop).
- to support [scoped tasks](https://without.boats/blog/the-scoped-task-trilemma/) or in a more general sense to provide a [destruction guarantee](https://zetanumbers.github.io/book/myosotis.html) there is a desire among some users to see a `Leak` (or `Forget`) trait.
- Withoutboats in his [post](https://without.boats/blog/changing-the-rules-of-rust/) reflected on the use of `Move` trait instead of a `Pin`.
All the traits proposed above are supposed to be auto traits implemented for most types, and usually implemented automatically by compiler.
For backward compatibility these traits have to be added implicitly to all bound lists in old code (see below). Adding new default bounds involves many difficulties: many standard library interfaces may need to opt out of those default bounds, and therefore be infected with confusing `?Trait` syntax, migration to a new edition may contain backward compatibility holes, supporting new traits in the compiler can be quite difficult and so forth. Anyway, it's hard to evaluate the complexity until we try the system on a practice.
In this PR we introduce new optional lang items for traits that are added to all bound lists by default, similarly to existing `Sized`. The examples of such traits could be `Leak`, `Move`, `SyncDrop` or something else, it doesn't matter much right now (further I will call them `DefaultAutoTrait`'s). We want to land this change into rustc under an option, so it becomes available in bootstrap compiler. Then we'll be able to do standard library experiments with the aforementioned traits without adding hundreds of `#[cfg(not(bootstrap))]`s. Based on the experiments, we can come up with some scheme for the next edition, in which such bounds are added in a more targeted way, and not just everywhere.
Most of the implementation is basically a refactoring that replaces hardcoded uses of `Sized` with iterating over a list of traits including both `Sized` and the new traits when `-Zexperimental-default-bounds` is enabled (or just `Sized` as before, if the option is not enabled).
### Default bounds for old editions
All existing types, including generic parameters, are considered `Leak`/`Move`/`SyncDrop` and can be forgotten, moved or destroyed in generic contexts without specifying any bounds. New types that cannot be, for example, forgotten and do not implement `Leak` can be added at some point, and they should not be usable in such generic contexts in existing code.
To both maintain this property and keep backward compatibility with existing code, the new traits should be added as default bounds _everywhere_ in previous editions. Besides the implicit `Sized` bound contexts that includes supertrait lists and trait lists in trait objects (`dyn Trait1 + ... + TraitN`). Compiler should also generate implicit `DefaultAutoTrait` implementations for foreign types (`extern { type Foo; }`) because they are also currently usable in generic contexts without any bounds.
#### Supertraits
Adding the new traits as supertraits to all existing traits is potentially necessary, because, for example, using a `Self` param in a trait's associated item may be a breaking change otherwise:
```rust
trait Foo: Sized {
fn new() -> Option<Self>; // ERROR: `Option` requires `DefaultAutoTrait`, but `Self` is not `DefaultAutoTrait`
}
// desugared `Option`
enum Option<T: DefaultAutoTrait + Sized> {
Some(T),
None,
}
```
However, default supertraits can significantly affect compiler performance. For example, if we know that `T: Trait`, the compiler would deduce that `T: DefaultAutoTrait`. It also implies proving `F: DefaultAutoTrait` for each field `F` of type `T` until an explicit impl is be provided.
If the standard library is not modified, then even traits like `Copy` or `Send` would get these supertraits.
In this PR for optimization purposes instead of adding default supertraits, bounds are added to the associated items:
```rust
// Default bounds are generated in the following way:
trait Trait {
fn foo(&self) where Self: DefaultAutoTrait {}
}
// instead of this:
trait Trait: DefaultAutoTrait {
fn foo(&self) {}
}
```
It is not always possible to do this optimization because of backward compatibility:
```rust
pub trait Trait<Rhs = Self> {}
pub trait Trait1 : Trait {} // ERROR: `Rhs` requires `DefaultAutoTrait`, but `Self` is not `DefaultAutoTrait`
```
or
```rust
trait Trait {
type Type where Self: Sized;
}
trait Trait2<T> : Trait<Type = T> {} // ERROR: `???` requires `DefaultAutoTrait`, but `Self` is not `DefaultAutoTrait`
```
Therefore, `DefaultAutoTrait`'s are still being added to supertraits if the `Self` params or type bindings were found in the trait header.
#### Trait objects
Trait objects requires explicit `+ Trait` bound to implement corresponding trait which is not backward compatible:
```rust
fn use_trait_object(x: Box<dyn Trait>) {
foo(x) // ERROR: `foo` requires `DefaultAutoTrait`, but `dyn Trait` is not `DefaultAutoTrait`
}
// implicit T: DefaultAutoTrait here
fn foo<T>(_: T) {}
```
So, for a trait object `dyn Trait` we should add an implicit bound `dyn Trait + DefaultAutoTrait` to make it usable, and allow relaxing it with a question mark syntax `dyn Trait + ?DefaultAutoTrait` when it's not necessary.
#### Foreign types
If compiler doesn't generate auto trait implementations for a foreign type, then it's a breaking change if the default bounds are added everywhere else:
```rust
// implicit T: DefaultAutoTrait here
fn foo<T: ?Sized>(_: &T) {}
extern "C" {
type ExternTy;
}
fn forward_extern_ty(x: &ExternTy) {
foo(x); // ERROR: `foo` requires `DefaultAutoTrait`, but `ExternTy` is not `DefaultAutoTrait`
}
```
We'll have to enable implicit `DefaultAutoTrait` implementations for foreign types at least for previous editions:
```rust
// implicit T: DefaultAutoTrait here
fn foo<T: ?Sized>(_: &T) {}
extern "C" {
type ExternTy;
}
impl DefaultAutoTrait for ExternTy {} // implicit impl
fn forward_extern_ty(x: &ExternTy) {
foo(x); // OK
}
```
### Unresolved questions
New default bounds affect all existing Rust code complicating an already complex type system.
- Proving an auto trait predicate requires recursively traversing the type and proving the predicate for it's fields. This leads to a significant performance regression. Measurements for the stage 2 compiler build show up to 3x regression.
- We hope that fast path optimizations for well known traits could mitigate such regressions at least partially.
- New default bounds trigger some compiler bugs in both old and new trait solver.
- With new default bounds we encounter some trait solver cycle errors that break existing code.
- We hope that these cases are bugs that can be addressed in the new trait solver.
Also migration to a new edition could be quite ugly and enormous, but that's actually what we want to solve. For other issues there's a chance that they could be solved by a new solver.
Move methods from `Map` to `TyCtxt`, part 5.
This eliminates all methods on `Map`. Actually removing `Map` will occur in a follow-up PR.
A follow-up to #137504.
r? `@Zalathar`
Various local trait item iteration cleanups
Adding a trait impl for `Foo` unconditionally affected all queries that are interested in a completely independent trait `Bar`. Perf has no effect on this. We probably don't have a good perf test for this tho.
r? `@compiler-errors`
I am unsure about 9d05efb66f as it doesn't improve anything wrt incremental, because we still do all the checks for valid `Drop` impls, which subsequently will still invoke many queries and basically keep the depgraph the same.
I want to do
9549077a47/compiler/rustc_middle/src/ty/trait_def.rs (L141)
but would leave that to a follow-up PR, this one changes enough things as it is
Do not mix normalized and unnormalized caller bounds when constructing param-env for `receiver_is_dispatchable`
See comments in code and in test I added.
r? `@BoxyUwU` since you reviewed the last PR, or reassign
Fixes#138937
Prefer built-in sized impls (and only sized impls) for rigid types always
This PR changes the confirmation of `Sized` obligations to unconditionally prefer the built-in impl, even if it has nested obligations. This also changes all other built-in impls (namely, `Copy`/`Clone`/`DiscriminantKind`/`Pointee`) to *not* prefer built-in impls over param-env impls. This aligns the old solver with the behavior of the new solver.
---
In the old solver, we register many builtin candidates with the `BuiltinCandidate { has_nested: bool }` candidate kind. The precedence this candidate takes over other candidates is based on the `has_nested` field. We only prefer builtin impls over param-env candidates if `has_nested` is `false`
2b4694a698/compiler/rustc_trait_selection/src/traits/select/mod.rs (L1804-L1866)
Preferring param-env candidates when the builtin candidate has nested obligations *still* ends up leading to detrimental inference guidance, like:
```rust
fn hello<T>() where (T,): Sized {
let x: (_,) = Default::default();
// ^^ The `Sized` obligation on the variable infers `_ = T`.
let x: (i32,) = x;
// We error here, both a type mismatch and also b/c `T: Default` doesn't hold.
}
```
Therefore this PR adjusts the candidate precedence of `Sized` obligations by making them a distinct candidate kind and unconditionally preferring them over all other candidate kinds.
Special-casing `Sized` this way is necessary as there are a lot of traits with a `Sized` super-trait bound, so a `&'a str: From<T>` where-bound results in an elaborated `&'a str: Sized` bound. People tend to not add explicit where-clauses which overlap with builtin impls, so this tends to not be an issue for other traits.
We don't know of any tests/crates which need preference for other builtin traits. As this causes builtin impls to diverge from user-written impls we would like to minimize the affected traits. Otherwise e.g. moving impls for tuples to std by using variadic generics would be a breaking change. For other builtin impls it's also easier for the preference of builtin impls over where-bounds to result in issues.
---
There are two ways preferring builtin impls over where-bounds can be incorrect and undesirable:
- applying the builtin impl results in undesirable region constraints. E.g. if only `MyType<'static>` implements `Copy` then a goal like `(MyType<'a>,): Copy` would require `'a == 'static` so we must not prefer it over a `(MyType<'a>,): Copy` where-bound
- this is mostly not an issue for `Sized` as all `Sized` impls are builtin and don't add any region constraints not already required for the type to be well-formed
- however, even with `Sized` this is still an issue if a nested goal also gets proven via a where-bound: [playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=30377da5b8a88f654884ab4ebc72f52b)
- if the builtin impl has associated types, we should not prefer it over where-bounds when normalizing that associated type. This can result in normalization adding more region constraints than just proving trait bounds. https://github.com/rust-lang/rust/issues/133044
- not an issue for `Sized` as it doesn't have associated types.
r? lcnr
`hir::Lifetime::ident` currently sometimes uses `kw::Empty` for elided
lifetimes and sometimes uses `kw::UnderscoreLifetime`, and the
distinction is used when creating some error suggestions, e.g. in
`Lifetime::suggestion` and `ImplicitLifetimeFinder::visit_ty`. I found
this *really* confusing, and it took me a while to understand what was
going on.
This commit replaces all uses of `kw::Empty` in `hir::Lifetime::ident`
with `kw::UnderscoreLifetime`. It adds a new field
`hir::Lifetime::is_path_anon` that mostly replaces the old
empty/underscore distinction and makes things much clearer.
Some other notable changes:
- Adds a big comment to `Lifetime` talking about permissable field
values.
- Adds some assertions in `new_named_lifetime` about what ident values
are permissible for the different `LifetimeRes` values.
- Adds a `Lifetime::new` constructor that does some checking to make
sure the `is_elided` and `is_anonymous` states are valid.
- `add_static_impl_trait_suggestion` now looks at `Lifetime::res`
instead of the ident when creating the suggestion. This is the one
case where `is_path_anon` doesn't replace the old empty/underscore
distinction.
- A couple of minor pretty-printing improvements.
Rollup of 10 pull requests
Successful merges:
- #130883 (Add environment variable query)
- #138624 (Add mipsel maintainer)
- #138672 (Avoiding calling queries when collecting active queries)
- #138935 (Update wg-prio triagebot config)
- #138946 (Un-bury chapters from the chapter list in rustc book)
- #138964 (Implement lint against using Interner and InferCtxtLike in random compiler crates)
- #138977 (Don't deaggregate InvocationParent just to reaggregate it again)
- #138980 (Collect items referenced from var_debug_info)
- #138985 (Use the correct binder scope for elided lifetimes in assoc consts)
- #138987 (Always emit `native-static-libs` note, even if it is empty)
r? `@ghost`
`@rustbot` modify labels: rollup
Use `Option<Ident>` for lowered param names.
Parameter patterns are lowered to an `Ident` by `lower_fn_params_to_names`, which is used when lowering bare function types, trait methods, and foreign functions. Currently, there are two exceptional cases where the lowered param can become an empty `Ident`.
- If the incoming pattern is an empty `Ident`. This occurs if the parameter is anonymous, e.g. in a bare function type.
- If the incoming pattern is neither an ident nor an underscore. Any such parameter will have triggered a compile error (hence the `span_delayed_bug`), but lowering still occurs.
This commit replaces these empty `Ident` results with `None`, which eliminates a number of `kw::Empty` uses, and makes it impossible to fail to check for these exceptional cases.
Note: the `FIXME` comment in `is_unwrap_or_empty_symbol` is removed. It actually should have been removed in #138482, the precursor to this PR. That PR changed the lowering of wild patterns to `_` symbols instead of empty symbols, which made the mentioned underscore check load-bearing.
r? ``@compiler-errors``
Fix next solver handling of shallow trait impl check
I'm trying to remove unnecessary direct calls to `select`, and this one seemed like a good place to start 😆
r? `@compiler-errors` or `@lcnr`
Parameter patterns are lowered to an `Ident` by
`lower_fn_params_to_names`, which is used when lowering bare function
types, trait methods, and foreign functions. Currently, there are two
exceptional cases where the lowered param can become an empty `Ident`.
- If the incoming pattern is an empty `Ident`. This occurs if the
parameter is anonymous, e.g. in a bare function type.
- If the incoming pattern is neither an ident nor an underscore. Any
such parameter will have triggered a compile error (hence the
`span_delayed_bug`), but lowering still occurs.
This commit replaces these empty `Ident` results with `None`, which
eliminates a number of `kw::Empty` uses, and makes it impossible to fail
to check for these exceptional cases.
Note: the `FIXME` comment in `is_unwrap_or_empty_symbol` is removed. It
actually should have been removed in #138482, the precursor to this PR.
That PR changed the lowering of wild patterns to `_` symbols instead of
empty symbols, which made the mentioned underscore check load-bearing.
Rollup of 7 pull requests
Successful merges:
- #138384 (Move `hir::Item::ident` into `hir::ItemKind`.)
- #138508 (Clarify "owned data" in E0515.md)
- #138531 (Store test diffs in job summaries and improve analysis formatting)
- #138533 (Only use `DIST_TRY_BUILD` for try jobs that were not selected explicitly)
- #138556 (Fix ICE: attempted to remap an already remapped filename)
- #138608 (rustc_target: Add target feature constraints for LoongArch)
- #138619 (Flatten `if`s in `rustc_codegen_ssa`)
r? `@ghost`
`@rustbot` modify labels: rollup
Move `hir::Item::ident` into `hir::ItemKind`.
`hir::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`, `Const`, `Fn`, `Macro`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`, Trait`, TraitAalis`.
- It's always empty for these item kinds: `ForeignMod`, `GlobalAsm`, `Impl`.
- For `Use`, it is non-empty for `UseKind::Single` and empty for `UseKind::{Glob,ListStem}`.
All of this is quite non-obvious; the only documentation is a single comment saying "The name might be a dummy name in case of anonymous items". Some sites that handle items check for an empty ident, some don't. This is a very C-like way of doing things, but this is Rust, we have sum types, we can do this properly and never forget to check for the exceptional case and never YOLO possibly empty identifiers (or possibly dummy spans) around and hope that things will work out.
This is step towards `kw::Empty` elimination (#137978).
r? `@fmease`
`hir::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Macro`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
Trait`, TraitAalis`.
- It's always empty for these item kinds: `ForeignMod`, `GlobalAsm`,
`Impl`.
- For `Use`, it is non-empty for `UseKind::Single` and empty for
`UseKind::{Glob,ListStem}`.
All of this is quite non-obvious; the only documentation is a single
comment saying "The name might be a dummy name in case of anonymous
items". Some sites that handle items check for an empty ident, some
don't. This is a very C-like way of doing things, but this is Rust, we
have sum types, we can do this properly and never forget to check for
the exceptional case and never YOLO possibly empty identifiers (or
possibly dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- A similar transformation makes sense for `ast::Item`, but this is
already a big change. That can be done later.
- Lots of assertions are added to item lowering to ensure that
identifiers are empty/non-empty as expected. These will be removable
when `ast::Item` is done later.
- `ItemKind::Use` doesn't get an `Ident`, but `UseKind::Single` does.
- `lower_use_tree` is significantly simpler. No more confusing `&mut
Ident` to deal with.
- `ItemKind::ident` is a new method, it returns an `Option<Ident>`. It's
used with `unwrap` in a few places; sometimes it's hard to tell
exactly which item kinds might occur. None of these unwraps fail on
the test suite. It's conceivable that some might fail on alternative
input. We can deal with those if/when they happen.
- In `trait_path` the `find_map`/`if let` is replaced with a loop, and
things end up much clearer that way.
- `named_span` no longer checks for an empty name; instead the call site
now checks for a missing identifier if necessary.
- `maybe_inline_local` doesn't need the `glob` argument, it can be
computed in-function from the `renamed` argument.
- `arbitrary_source_item_ordering::check_mod` had a big `if` statement
that was just getting the ident from the item kinds that had one. It
could be mostly replaced by a single call to the new `ItemKind::ident`
method.
- `ItemKind` grows from 56 to 64 bytes, but `Item` stays the same size,
and that's what matters, because `ItemKind` only occurs within `Item`.
Denote `ControlFlow` as `#[must_use]`
I've repeatedly hit bugs in the compiler due to `ControlFlow` not being marked `#[must_use]`. There seems to be an accepted ACP to make the type `#[must_use]` (https://github.com/rust-lang/libs-team/issues/444), so this PR implements that part of it.
Most of the usages in the compiler that trigger this new warning are "root" usages (calling into an API that uses control-flow internally, but for which the callee doesn't really care) and have been suppressed by `let _ = ...`, but I did legitimately find one instance of a missing `?` and one for a never-used `ControlFlow` value in #137448.
Presumably this needs an FCP too, so I'm opening this and nominating it for T-libs-api.
This PR also touches the tools (incl. rust-analyzer), but if this went into FCP, I'd split those out into separate PRs which can land before this one does.
r? libs-api
`@rustbot` label: T-libs-api I-libs-api-nominated
Fix HIR printing of parameters
HIR pretty printing does the wrong thing for anonymous parameters, and there is no test coverage for it. This PR remedies both of those things.
r? ``@lcnr``
Currently (PatKind::Wild` (i.e. `_`) gets turned by
`lower_fn_params_to_names` into an empty identifier, which means it is
printed incorrectly by HIR pretty printing.
And likewise for `lower_fn_params_to_names`, which affects some error
messages.
This commit fixes them. This requires a slight tweak in a couple of
places to continue using parameter numbers in some error messages. And
it improves the output of `tests/ui/typeck/cyclic_type_ice.rs`:
`/* _ */` is a better suggestion than `/* */`.
Add an opt-out in pretty printing for RTN rendering
Today, we render RPITIT types like `impl Sized { T::method(..) }` when RTN is enabled. This is very useful for diagnostics, since it's often not clear what the `impl Sized` type means by itself, and it makes it clear that that's an RPITIT that can be bounded using RTN syntax. See #115624.
However, since we don't distinguish types that are rendered for the purposes of printing messages vs suggestions, this representation leaks into suggestions and turns into code that can't be parsed. This PR adds a new `with_types_for_suggestion! {}` and `with_types_for_signature! {}` options to the pretty printing architecture to make it clear that we're rendering a type for code suggestions.
This can be applied later as we find that we need it.
Do not register `Self: AutoTrait` when confirming auto trait (in old solver)
Every built-in auto impl for a trait goal like `Ty: Auto` immediately registers another obligation of `Ty: Auto` as one of its nested obligations, leading to us stressing the cycle detection machinery a lot more than we need to. This is because all traits have a `Self: Trait` predicate.
To fix this, remove the call to `impl_or_trait_obligations` in `vtable_auto_impl`, since auto traits do not have where clauses.
r? lcnr
change definitely unproductive cycles to error
builds on top of #136824 by adding a third variant to `PathKind` for paths which may change to be coinductive in the future but must not be so right now. Most notably, impl where-clauses of not yet coinductive traits.
With this, we can change cycles which are definitely unproductive to a proper error. This fixes https://github.com/rust-lang/trait-system-refactor-initiative/issues/114. This does not affect stable as we keep these cycles as ambiguous during coherence.
r? ````````@compiler-errors```````` ````````@nikomatsakis````````
Elaborate trait assumption in `receiver_is_dispatchable`
Fixes#138172. See comment on the linked test.
Probably not a fix for the general problem, bc I think this may still be incomplete for other weird `where` clauses on the receiver. But 🤷, supertraits seems like an obvious one to fix.
Continuing the work from #137350.
Removes the unused methods: `expect_variant`, `expect_field`,
`expect_foreign_item`.
Every method gains a `hir_` prefix.
Rollup of 10 pull requests
Successful merges:
- #137715 (Allow int literals for pattern types with int base types)
- #138002 (Disable CFI for weakly linked syscalls)
- #138051 (Add support for downloading GCC from CI)
- #138231 (Prevent ICE in autodiff validation by emitting user-friendly errors)
- #138245 (stabilize `ci_rustc_if_unchanged_logic` test for local environments)
- #138256 (Do not feed anon const a type that references generics that it does not have)
- #138284 (Do not write user type annotation for const param value path)
- #138296 (Remove `AdtFlags::IS_ANONYMOUS` and `Copy`/`Clone` condition for anonymous ADT)
- #138352 (miri native_calls: ensure we actually expose *mutable* provenance to the memory FFI can access)
- #138354 (remove redundant `body` arguments)
r? `@ghost`
`@rustbot` modify labels: rollup
Remove `AdtFlags::IS_ANONYMOUS` and `Copy`/`Clone` condition for anonymous ADT
cc #131045, which removed anonymous ADTs from the compiler
I forgot more stuff I guess.
Add `#[define_opaques]` attribute and require it for all type-alias-impl-trait sites that register a hidden type
Instead of relying on the signature of items to decide whether they are constraining an opaque type, the opaque types that the item constrains must be explicitly listed.
A previous version of this PR used an actual attribute, but had to keep the resolved `DefId`s in a side table.
Now we just lower to fields in the AST that have no surface syntax, instead a builtin attribute macro fills in those fields where applicable.
Note that for convenience referencing opaque types in associated types from associated methods on the same impl will not require an attribute. If that causes problems `#[defines()]` can be used to overwrite the default of searching for opaques in the signature.
One wart of this design is that closures and static items do not have generics. So since I stored the opaques in the generics of functions, consts and methods, I would need to add a custom field to closures and statics to track this information. During a T-types discussion we decided to just not do this for now.
fixes#131298
Revert <https://github.com/rust-lang/rust/pull/138084> to buy time to
consider options that avoids breaking downstream usages of cargo on
distributed `rustc-src` artifacts, where such cargo invocations fail due
to inability to inherit `lints` from workspace root manifest's
`workspace.lints` (this is only valid for the source rust-lang/rust
workspace, but not really the distributed `rustc-src` artifacts).
This breakage was reported in
<https://github.com/rust-lang/rust/issues/138304>.
This reverts commit 48caf81484, reversing
changes made to c6662879b2.
compiler: Use `size_of` from the prelude instead of imported
Use `std::mem::{size_of, size_of_val, align_of, align_of_val}` from the prelude instead of importing or qualifying them. Apply this change across the compiler.
These functions were added to all preludes in Rust 1.80.
r? ``@compiler-errors``
Use `std::mem::{size_of, size_of_val, align_of, align_of_val}` from the
prelude instead of importing or qualifying them.
These functions were added to all preludes in Rust 1.80.
Improve error message for `AsyncFn` trait failure for RPIT
Use a `WellFormedDerived` obligation cause to make sure we can turn an `AsyncFnKindHelper` trait goal into its parent `AsyncFn*` goal, then fix the logic for reporting `AsyncFn*` kind mismatches.
Best reviewed without whitespace.
Fixes#137905
r? oli-obk
Remove `MaybeForgetReturn` suggestion
#115196 implemented a suggestion to add a missing `return` when there is an ambiguity error, when that ambiguity error could be constrained by the return type of the function.
I initially reviewed it and thought it could be useful; however, looking back at that code now, I feel like it's a bit too much of a hack to be worth keeping around in typeck, especially given how rare it's expected to fire in practice. This is especially true because it depends on `StashKey::MaybeForgetReturn`, which is only stashed when we have *Sized* obligation ambiguity errors. Let's remove it for now.
I'd like to note that it's basically impossible to get this suggestion to apply in its current state except for what I'd consider somewhat artificial examples, involving no generic trait bounds. For example, it's not triggered for:
```rust
struct W<T>(T);
fn bar<T: Default>() -> W<T> { todo!() }
fn foo() -> W<i32> {
if true {
bar();
}
W(0)
}
```
Nor is it triggered for:
```
fn foo() -> i32 {
if true {
Default::default();
}
0
}
```
It's basically only triggered iff there's only one ambiguity error on the type, which is `Sized`.
Generally, suggesting something that affects control flow is a pretty dramatic suggestion; therefore, both the accuracy and precision of this diagnostic should be pretty high.
One other, somewhat unrelated observation is that this might be using stashed diagnostics incorrectly (or at least unnecessarily). Stashed diagnostics are used when error detection is fragmented over several major stages of the compiler, like a parse or resolver error which later can be recovered in typeck. However, this one is a bit different since it is fully handled within typeck -- perhaps that suggests that if this were to be reimplemented, it wouldn't need to be so complicated of an implementation.
Only use implied bounds hack if bevy, and use deeply normalize in implied bounds hack
Consolidates the implied bounds computation mode into a single function, which deeply normalizes, and if it's in **compat** mode (for bevy), it extracts outlives bounds from the infcx.
Previously, we were using the implied bounds compat mode in two cases:
1. During WF, if it detects `ParamSet`
2. EVERYWHERE ELSE (lol) -- e.g. borrowck, predicate entailment, etc.
While I think this is fine, and the net effect was just that we emitted fewer diagnostics, it makes me uncomfortable that all crates were using the supposed "compat" code.
Fixes#137767
mgca: Lower all const paths as `ConstArgKind::Path`
When `#![feature(min_generic_const_args)]` is enabled, we now lower all
const paths in generic arg position to `hir::ConstArgKind::Path`. We
then lower assoc const paths to `ty::ConstKind::Unevaluated` since we
can no longer use the anon const expression lowering machinery. In the
process of implementing this, I factored out `hir_ty_lowering` code that
is now shared between lowering assoc types and assoc consts.
This PR also introduces a `#[type_const]` attribute for trait assoc
consts that are allowed as const args. However, we still need to
implement code to check that assoc const definitions satisfy
`#[type_const]` if present (basically is it a const path or a
monomorphic anon const).
r? `@BoxyUwU`
When `#![feature(min_generic_const_args)]` is enabled, we now lower all
const paths in generic arg position to `hir::ConstArgKind::Path`. We
then lower assoc const paths to `ty::ConstKind::Unevaluated` since we
can no longer use the anon const expression lowering machinery. In the
process of implementing this, I factored out `hir_ty_lowering` code that
is now shared between lowering assoc types and assoc consts.
This PR also introduces a `#[type_const]` attribute for trait assoc
consts that are allowed as const args. However, we still need to
implement code to check that assoc const definitions satisfy
`#[type_const]` if present (basically is it a const path or a
monomorphic anon const).
Update query normalizer docs to not position it as the greatest pioneer in the space of normalization
I don't think its true that we intend to replace all normalization with the query normalizer- its more likely that once the new solver is stable we can replace the query normalizer with normal normalization calls as the new solver caches much more than the old solver
r? ``@compiler-errors``
Remove `ParamEnv::without_caller_bounds`
This doesn't really do anything that `ParamEnv::empty` doesn't do nowadays as `ParamEnv` *only* stores caller bounds since other information has been moved out into `TypingMode`
r? ```@compiler-errors``` ```@lcnr```
Introduce `feature(generic_const_parameter_types)`
Allows to define const generic parameters whose type depends on other generic parameters, e.g. `Foo<const N: usize, const ARR: [u8; N]>;`
Wasn't going to implement for this for a while until we could implement it with `bad_inference.rs` resolved but apparently the project simd folks would like to be able to use this for some intrinsics and the inference issue isn't really a huge problem there aiui. (cc ``@workingjubilee`` )
Use `Binder<Vec<Ty>>` instead of `Vec<Binder<Ty>>` in both solvers for sized/auto traits/etc.
It's more conceptually justified IMO, especially when binders get implications.
r? lcnr
Don't suggest constraining unstable associated types
Fixes#137624
This could be made a bit more specific, considering the local crate's stability or nightly status or something, but I think in general we should not be suggesting associated type bounds on unstable associated items.
Teach structured errors to display short `Ty<'_>`
Make it so that in every structured error annotated with `#[derive(Diagnostic)]` that has a field of type `Ty<'_>`, the printing of that value into a `String` will look at the thread-local storage `TyCtxt` in order to shorten to a length appropriate with the terminal width. When this happen, the resulting error will have a note with the file where the full type name was written to.
```
error[E0618]: expected function, found `((..., ..., ..., ...), ..., ..., ...)``
--> long.rs:7:5
|
6 | fn foo(x: D) { //~ `x` has type `(...
| - `x` has type `((..., ..., ..., ...), ..., ..., ...)`
7 | x(); //~ ERROR expected function, found `(...
| ^--
| |
| call expression requires function
|
= note: the full name for the type has been written to 'long.long-type-14182675702747116984.txt'
= note: consider using `--verbose` to print the full type name to the console
```
Follow up to and response to the comments on #136898.
r? ``@oli-obk``
Make it so that every structured error annotated with `#[derive(Diagnostic)]` that has a field of type `Ty<'_>`, the printing of that value into a `String` will look at the thread-local storage `TyCtxt` in order to shorten to a length appropriate with the terminal width. When this happen, the resulting error will have a note with the file where the full type name was written to.
```
error[E0618]: expected function, found `((..., ..., ..., ...), ..., ..., ...)``
--> long.rs:7:5
|
6 | fn foo(x: D) { //~ `x` has type `(...
| - `x` has type `((..., ..., ..., ...), ..., ..., ...)`
7 | x(); //~ ERROR expected function, found `(...
| ^--
| |
| call expression requires function
|
= note: the full name for the type has been written to 'long.long-type-14182675702747116984.txt'
= note: consider using `--verbose` to print the full type name to the console
```
In the standard library, the `Extend` impl for `Iterator` (specialised
with `TrustedLen`) has a parameter which is constrained by a projection
predicate. This projection predicate provides a value for an inference
variable but host effect evaluation wasn't resolving variables first.
Adding the extra resolve can the number of errors in some tests when they
gain host effect predicates, but this is not unexpected as calls to
`resolve_vars_if_possible` can cause more error tainting to happen.
Co-authored-by: Boxy <rust@boxyuwu.dev>
Use `edition = "2024"` in the compiler (redux)
Most of this is binding mode changes, which I fixed by running `x.py fix`.
Also adds some miscellaneous `unsafe` blocks for new unsafe standard library functions (the setenv ones), and a missing `unsafe extern` block in some enzyme codegen code, and fixes some precise capturing lifetime changes (but only when they led to errors).
cc ``@ehuss`` ``@traviscross``
Prune dead regionck code
We never encounter `ObligationCauseCode`s that correspond to region obligations that originate from "within" a body, since we don't do HIR regionck anymore on bodies. So prune some dead code.
Tweak E0277 when predicate comes indirectly from ?
When a `?` operation requires an `Into` conversion with additional bounds (like having a concrete error but wanting to convert to a trait object), we handle it speficically and provide the same kind of information we give other `?` related errors.
```
error[E0277]: `?` couldn't convert the error: `E: std::error::Error` is not satisfied
--> $DIR/bad-question-mark-on-trait-object.rs:7:13
|
LL | fn foo() -> Result<(), Box<dyn std::error::Error>> {
| -------------------------------------- required `E: std::error::Error` because of this
LL | Ok(bar()?)
| -----^ the trait `std::error::Error` is not implemented for `E`
| |
| this has type `Result<_, E>`
|
note: `E` needs to implement `std::error::Error`
--> $DIR/bad-question-mark-on-trait-object.rs:1:1
|
LL | struct E;
| ^^^^^^^^
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
= note: required for `Box<dyn std::error::Error>` to implement `From<E>`
```
Avoid talking about `FromResidual` when other more relevant information is being given, particularly from `rust_on_unimplemented`.
Fix#137238.
-----
CC #137232, which was a smaller step related to this.
```
error[E0277]: `?` couldn't convert the error: `E: std::error::Error` is not satisfied
--> $DIR/bad-question-mark-on-trait-object.rs:7:13
|
LL | fn foo() -> Result<(), Box<dyn std::error::Error>> {
| -------------------------------------- required `E: std::error::Error` because of this
LL | Ok(bar()?)
| -----^ the trait `std::error::Error` is not implemented for `E`
| |
| this has type `Result<_, E>`
|
note: `E` needs to implement `std::error::Error`
--> $DIR/bad-question-mark-on-trait-object.rs:1:1
|
LL | struct E;
| ^^^^^^^^
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
= note: required for `Box<dyn std::error::Error>` to implement `From<E>`
error[E0277]: `?` couldn't convert the error to `X`
--> $DIR/bad-question-mark-on-trait-object.rs:18:13
|
LL | fn bat() -> Result<(), X> {
| ------------- expected `X` because of this
LL | Ok(bar()?)
| -----^ the trait `From<E>` is not implemented for `X`
| |
| this can't be annotated with `?` because it has type `Result<_, E>`
|
note: `X` needs to implement `From<E>`
--> $DIR/bad-question-mark-on-trait-object.rs:4:1
|
LL | struct X;
| ^^^^^^^^
note: alternatively, `E` needs to implement `Into<X>`
--> $DIR/bad-question-mark-on-trait-object.rs:1:1
|
LL | struct E;
| ^^^^^^^^
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
```
When a `?` operation requires an `Into` conversion with additional bounds (like having a concrete error but wanting to convert to a trait object), we handle it speficically and provide the same kind of information we give other `?` related errors.
```
error[E0277]: `?` couldn't convert the error: `E: std::error::Error` is not satisfied
--> $DIR/bad-question-mark-on-trait-object.rs:5:13
|
LL | fn foo() -> Result<(), Box<dyn std::error::Error>> {
| -------------------------------------- required `E: std::error::Error` because of this
LL | Ok(bar()?)
| ^ the trait `std::error::Error` is not implemented for `E`
|
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
= note: required for `Box<dyn std::error::Error>` to implement `From<E>`
```
Avoid talking about `FromResidual` when other more relevant information is being given, particularly from `rust_on_unimplemented`.
Register `USAGE_OF_TYPE_IR_INHERENT`, remove inherent usages
I implemented a lint to discourage the usage of `rustc_type_ir::inherent` but never actually enabled it. People started using `rustc_type_ir::inherent` methods through globs, lol.
r? fmease or reassign as you please
Make fewer crates depend on `rustc_ast_ir`
I think it simplifies the crate graph and also exposes people less to confusion if downstream crates don't interact with `rustc_ast_ir` directly and instead just use its functionality reexported through more familiar paths.
r? oli-obk since you introduced ast-ir
Don't mention `FromResidual` on bad `?`
Unless `try_trait_v2` is enabled, don't mention that `FromResidual` isn't implemented for a specific type when the implicit `From` conversion of a `?` fails. For the end user on stable, `?` might as well be a compiler intrinsic, so we remove that note to avoid further confusion and allowing other parts of the error to be more prominent.
```
error[E0277]: `?` couldn't convert the error to `u8`
--> $DIR/bad-interconversion.rs:4:20
|
LL | fn result_to_result() -> Result<u64, u8> {
| --------------- expected `u8` because of this
LL | Ok(Err(123_i32)?)
| ------------^ the trait `From<i32>` is not implemented for `u8`
| |
| this can't be annotated with `?` because it has type `Result<_, i32>`
|
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
= help: the following other types implement trait `From<T>`:
`u8` implements `From<Char>`
`u8` implements `From<bool>`
```
Emit dropck normalization errors in borrowck
Borrowck generally assumes that any queries it runs for type checking will succeed, thinking that HIR typeck will have errored first if there was a problem. However as of #98641, dropck isn't run on HIR, so there's no direct guarantee that it doesn't error. While a type being well-formed might be expected to ensure that its fields are well-formed, this is not the case for types containing a type projection:
```rust
pub trait AuthUser {
type Id;
}
pub trait AuthnBackend {
type User: AuthUser;
}
pub struct AuthSession<Backend: AuthnBackend> {
data: Option<<<Backend as AuthnBackend>::User as AuthUser>::Id>,
}
pub trait Authz: Sized {
type AuthnBackend: AuthnBackend<User = Self>;
}
pub fn run_query<User: Authz>(auth: AuthSession<User::AuthnBackend>) {}
// ^ No User: AuthUser bound is required or inferred.
```
While improvements to trait solving might fix this in the future, for now we go for a pragmatic solution of emitting an error from borrowck (by rerunning dropck outside of a query) and making drop elaboration check if an error has been emitted previously before panicking for a failed normalization.
Closes#103899Closes#135039
r? `@compiler-errors` (feel free to re-assign)
Unless `try_trait_v2` is enabled, don't mention that `FromResidual` isn't implemented for a specific type when the implicit `From` conversion of a `?` fails. For the end user on stable, `?` might as well be a compiler intrinsic, so we remove that note to avoid further confusion and allowing other parts of the error to be more prominent.
```
error[E0277]: `?` couldn't convert the error to `u8`
--> $DIR/bad-interconversion.rs:4:20
|
LL | fn result_to_result() -> Result<u64, u8> {
| --------------- expected `u8` because of this
LL | Ok(Err(123_i32)?)
| ------------^ the trait `From<i32>` is not implemented for `u8`
| |
| this can't be annotated with `?` because it has type `Result<_, i32>`
|
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
= help: the following other types implement trait `From<T>`:
`u8` implements `From<Char>`
`u8` implements `From<bool>`
```
Continuing the work started in #136466.
Every method gains a `hir_` prefix, though for the ones that already
have a `par_` or `try_par_` prefix I added the `hir_` after that.
HIR type checking no longer runs dropck, so we may get new errors when
we run it in borrowck. If this happens then rerun the query in a local
infcx and report errors for it.
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`.
The end goal is to eliminate `Map` altogether.
I added a `hir_` prefix to all of them, that seemed simplest. The
exceptions are `module_items` which became `hir_module_free_items` because
there was already a `hir_module_items`, and `items` which became
`hir_free_items` for consistency with `hir_module_free_items`.