Externally implementable items
Supersedes https://github.com/rust-lang/rust/pull/140010
Tracking issue: https://github.com/rust-lang/rust/issues/125418
Getting started:
```rust
#![feature(eii)]
#[eii(eii1)]
pub fn decl1(x: u64)
// body optional (it's the default)
{
println!("default {x}");
}
// in another crate, maybe
#[eii1]
pub fn decl2(x: u64) {
println!("explicit {x}");
}
fn main() {
decl1(4);
}
```
- tiny perf regression, underlying issue makes multiple things in the compiler slow, not just EII, planning to solve those separately.
- No codegen_gcc support, they don't have bindings for weak symbols yet but could
- No windows support yet for weak definitions
This PR merges the implementation of EII for just llvm + not windows, doesn't yet contain like a new panic handler implementation or alloc handler. With this implementation, it would support implementing the panic handler in terms of EII already since it requires no default implementation so no weak symbols
The PR has been open in various forms for about a year now, but I feel that having some implementation merged to build upon
Overhaul filename handling for cross-compiler consistency
This PR overhauls the way we handle filenames in the compiler and `rmeta` in order to achieve achieve cross-compiler consistency (ie. having the same path no matter if the filename was created in the current compiler session or is coming from `rmeta`).
This is required as some parts of the compiler rely on consistent paths for the soundness of generated code (see rust-lang/rust#148328).
In order to achieved consistency multiple steps are being taken by this PR:
- by making `RealFileName` immutable
- by only having `SourceMap::to_real_filename` create `RealFileName`
- currently `RealFileName` can be created from any `Path` and are remapped afterwards, which creates consistency issue
- by also making `RealFileName` holds it's working directory, embeddable name and the remapped scopes
- this removes the need for a `Session`, to know the current(!) scopes and cwd, which is invalid as they may not be equal to the scopes used when creating the filename
In order for `SourceMap::to_real_filename` to know which scopes to apply `FilePathMapping` now takes the current remapping scopes to apply, which makes `FileNameDisplayPreference` and company useless and are removed.
This PR is split-up in multiple commits (unfortunately not atomic), but should help review the changes.
Unblocks https://github.com/rust-lang/rust/pull/147611
Fixes https://github.com/rust-lang/rust/issues/148328
This commit refactors `SourceMap` and most importantly `RealFileName` to
make it self-contained in order to achieve cross-compiler consistency.
This is achieved:
- by making `RealFileName` immutable
- by only having `SourceMap::to_real_filename` create `RealFileName`
- by also making `RealFileName` holds it's working directory,
it's embeddable name and the remapped scopes
- by making most `FileName` and `RealFileName` methods take a scope as
an argument
In order for `SourceMap::to_real_filename` to know which scopes to apply
`FilePathMapping` now takes the current remapping scopes to apply, which
makes `FileNameDisplayPreference` and company useless and are removed.
The scopes type `RemapPathScopeComponents` was moved from
`rustc_session::config` to `rustc_span`.
The previous system for scoping the local/remapped filenames
`RemapFileNameExt::for_scope` is no longer useful as it's replaced by
methods on `FileName` and `RealFileName`.
148725 moved the default to being homogeneous; this adds heterogeneous ones back under an obvious-bikeshed syntax so people can experiment with that as well.
Essentially resolves 149025 by letting them move to this syntax instead.
Fix ICE when include_str! reads binary files
ICE occurred when an invalid UTF8 file with an absolute path were included.
resolve: rust-lang/rust#149304
Use `let...else` consistently in user-facing diagnostics
resolve: rust-lang/rust#148772
Standardize `let...else` terminology in user-facing diagnostics.
Goal: Consistently use `let...else` in all error/warning messages.
Internal technical names (`let-else`) in comments and documentation remain unchanged.
cc ``@carols10cents,`` ``@jieyouxu``
Port `cfg_select!` to the new attribute parsing system
Best reviewed commit by commit, since it involves some moving around of code
r? `````@jdonszelmann`````
`c_variadic`: Add future-incompatibility warning for `...` arguments without a pattern outside of `extern` blocks
This PR makes `...` arguments without a pattern in non-foreign functions (such as the argument in `unsafe extern "C" fn f(...) {}`) a future-compatibility warning; making this error would be consistent with how `unsafe extern "C" fn f(u32) {}` is handled. Allowing `...` arguments without a pattern in non-foreign functions is a source of confusion for programmers coming from C, where the `...` parameter is never named and instead calling `va_start` is required; disallowing `...` arguments without a pattern also improves the overall consistency of the Rust language by matching the treatment of other arguments without patterns. `...` arguments without a pattern in `extern` blocks (such as `unsafe extern "C" { fn f(...); }`) continue to compile without warnings after this PR, as they are already stable and heavily used (and don't cause the mentioned confusion as they are just being used in function declarations).
As all the syntax gating for `c_variadic` has been done post-expansion, this is technically a breaking change. In particular, code like this has compiled on stable since Rust 1.35.0:
```rust
#[cfg(any())] // Equivalent to the more recent #[cfg(false)]
unsafe extern "C" fn bar(_: u32, ...) {}
```
Since this is more or less a stability hole and a Crater run shows only the `binrw` crate is using this, I think it would be ok to break this. This will require a lang FCP.
The idea of rejecting `...` pre-expansion was first raised here https://github.com/rust-lang/rust/pull/143546#issuecomment-3043142052.
Tracking issue: rust-lang/rust#44930
cc `@folkertdev` `@workingjubilee`
r? `@joshtriplett`
Recover `[T: N]` as `[T; N]`
`;` is similar and (keyboard-wise) next to `:`, so a verbose suggestion may help to see the difference.
Parent PR: rust-lang/rust#143905
---
`@rustbot` label +A-parser +A-array +A-diagnostics +A-suggestion-diagnostics +D-papercut
Remove a remnant of `dyn*` from the parser
Follow-up to https://github.com/rust-lang/rust/pull/146664 and https://github.com/rust-lang/rust/pull/143036.
`is_explicit_dyn_type` still checked for `TokenKind::Star` which made no sense now that `dyn*` is no more.
Removing it doesn't represent a functional change and merely affects diagnostics. That's because the check only dictated whether to interpret `dyn` as the start of a trait object type in Rust 2015 (where this identifier is only a *contextual* keyword). However, we would still fail at the `*` later on as it doesn't start a bound.
While at it, I also took the time to clean up in the vicinity.
Add correct suggestion for multi-references for self type in method
Currently the suggestion for this code
```rust
fn main() {}
struct A {
field: i32,
}
impl A {
fn f(&&self) {}
}
```
looks like this, which is incorrect and missleading
```rust
Compiling playground v0.0.1 (/playground)
error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)`
--> src/main.rs:8:16
|
8 | fn f(&&self) {}
| ^ expected one of 9 possible tokens
|
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
help: explicitly ignore the parameter name
|
8 | fn f(_: &&self) {}
| ++
```
So this fixes it and make more correct suggestions
```rust
error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)`
--> /home/gh-Kivooeo/test_/src/main.rs:8:16
|
8 | fn f(&&self) {}
| ^ expected one of 9 possible tokens
|
help: `self` should be `self`, `&self` or `&mut self`, please remove extra references
|
8 - fn f(&&self) {}
8 + fn f(&self) {}
```
Implementation is pretty self-documenting, but if you have suggestions on how to improve this (according to current test, which may be not fully covering all cases, this is works very well) or have some funny edge cases to show, I would appreciate it
r? compiler
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.
Give correct suggestion for a typo in raw pointers
This adds a check for when user wrote `const* T` instead of `*const T`, I just saw how a C-person made this typo and compiler suggests this
```rust
--> src/main.rs:2:17
|
2 | let p: const* u8 = 0 as _;
| ^
|
help: add `mut` or `const` here
|
2 | let p: const*mut u8 = 0 as _;
| +++
2 | let p: const*const u8 = 0 as _;
| +++++
```
which is very incorrect
also fixes https://github.com/rust-lang/rust/issues/136602
r? compiler
Implement pin-project in pattern matching for `&pin mut|const T`
This PR implements part of rust-lang/rust#130494. It supports pin-project in pattern matching for `&pin mut|const T`.
~Pin-projection by field access (i.e. `&pin mut|const place.field`) is not fully supported yet since pinned-borrow is not ready (rust-lang/rust#135731).~
CC ``````@traviscross``````
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.