Actually walk into lifetimes and attrs in `EarlyContextAndPass`
Visitors that don't also call `walk_*` are kinda a footgun...
I believe all the other early lint functions walk into their types correctly at this point.
Add more info on type/trait mismatches for different crate versions
When encountering a type or trait mismatch for two types coming from two different crates with the same name, detect if it is either mixing two types/traits from the same crate on different versions:
```
error[E0308]: mismatched types
--> replaced
|
LL | do_something_type(Type);
| ----------------- ^^^^ expected `dependency::Type`, found `dep_2_reexport::Type`
| |
| arguments to this function are incorrect
|
note: two different versions of crate `dependency` are being used; two types coming from two different versions of the same crate are different types even if they look the same
--> replaced
|
LL | pub struct Type(pub i32);
| ^^^^^^^^^^^^^^^ this is the expected type `dependency::Type`
|
::: replaced
|
LL | pub struct Type;
| ^^^^^^^^^^^^^^^ this is the found type `dep_2_reexport::Type`
|
::: replaced
|
LL | extern crate dep_2_reexport;
| ---------------------------- one version of crate `dependency` is used here, as a dependency of crate `foo`
LL | extern crate dependency;
| ------------------------ one version of crate `dependency` is used here, as a direct dependency of the current crate
= help: you can use `cargo tree` to explore your dependency tree
note: function defined here
--> replaced
|
LL | pub fn do_something_type(_: Type) {}
| ^^^^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> replaced
|
LL | do_something_trait(Box::new(Type) as Box<dyn Trait2>);
| ------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `dependency::Trait2`, found trait `dep_2_reexport::Trait2`
| |
| arguments to this function are incorrect
|
note: two different versions of crate `dependency` are being used; two types coming from two different versions of the same crate are different types even if they look the same
--> replaced
|
LL | pub trait Trait2 {}
| ^^^^^^^^^^^^^^^^ this is the expected trait `dependency::Trait2`
|
::: replaced
|
LL | pub trait Trait2 {}
| ^^^^^^^^^^^^^^^^ this is the found trait `dep_2_reexport::Trait2`
|
::: replaced
|
LL | extern crate dep_2_reexport;
| ---------------------------- one version of crate `dependency` is used here, as a dependency of crate `foo`
LL | extern crate dependency;
| ------------------------ one version of crate `dependency` is used here, as a direct dependency of the current crate
= help: you can use `cargo tree` to explore your dependency tree
note: function defined here
--> replaced
|
LL | pub fn do_something_trait(_: Box<dyn Trait2>) {}
| ^^^^^^^^^^^^^^^^^^
```
or if it is different crates that were renamed to the same name:
```
error[E0308]: mismatched types
--> $DIR/type-mismatch-same-crate-name.rs:21:20
|
LL | a::try_foo(foo2);
| ---------- ^^^^ expected `main:🅰️:Foo`, found a different `main:🅰️:Foo`
| |
| arguments to this function are incorrect
|
note: two types coming from two different crates are different types even if they look the same
--> $DIR/auxiliary/crate_a2.rs:1:1
|
LL | pub struct Foo;
| ^^^^^^^^^^^^^^ this is the found type `crate_a2::Foo`
|
::: $DIR/auxiliary/crate_a1.rs:1:1
|
LL | pub struct Foo;
| ^^^^^^^^^^^^^^ this is the expected type `crate_a1::Foo`
|
::: $DIR/type-mismatch-same-crate-name.rs:13:17
|
LL | let foo2 = {extern crate crate_a2 as a; a::Foo};
| --------------------------- one type comes from crate `crate_a2` is used here, which is renamed locally to `a`
...
LL | extern crate crate_a1 as a;
| --------------------------- one type comes from crate `crate_a1` is used here, which is renamed locally to `a`
note: function defined here
--> $DIR/auxiliary/crate_a1.rs:10:8
|
LL | pub fn try_foo(x: Foo){}
| ^^^^^^^
error[E0308]: mismatched types
--> $DIR/type-mismatch-same-crate-name.rs:27:20
|
LL | a::try_bar(bar2);
| ---------- ^^^^ expected trait `main:🅰️:Bar`, found a different trait `main:🅰️:Bar`
| |
| arguments to this function are incorrect
|
note: two types coming from two different crates are different types even if they look the same
--> $DIR/auxiliary/crate_a2.rs:3:1
|
LL | pub trait Bar {}
| ^^^^^^^^^^^^^ this is the found trait `crate_a2::Bar`
|
::: $DIR/auxiliary/crate_a1.rs:3:1
|
LL | pub trait Bar {}
| ^^^^^^^^^^^^^ this is the expected trait `crate_a1::Bar`
|
::: $DIR/type-mismatch-same-crate-name.rs:13:17
|
LL | let foo2 = {extern crate crate_a2 as a; a::Foo};
| --------------------------- one trait comes from crate `crate_a2` is used here, which is renamed locally to `a`
...
LL | extern crate crate_a1 as a;
| --------------------------- one trait comes from crate `crate_a1` is used here, which is renamed locally to `a`
note: function defined here
--> $DIR/auxiliary/crate_a1.rs:11:8
|
LL | pub fn try_bar(x: Box<Bar>){}
| ^^^^^^^
```
This new output unifies the E0308 errors detail with the pre-existing E0277 errors, and better differentiates the "`extern crate` renamed" and "same crate, different versions" cases.
lint: change help for pointers to dyn types in FFI
### Context
while playing around, I encountered the warning for dyn types in `extern "C"` functions, but even after that I assumed that a (rust) raw pointer could be interpreted in C ('s ABI) as a `void *`... to be fair part of why I ignored the warning is because I wanted to poke at the generated assembly, not make useful code.
### Example
```rust
extern "C"
fn caller(callee: *const dyn Fn(i32)->i32){
// -- snip --
}
```
old warning:
```
warning: `extern` fn uses type `dyn Fn(i32) -> i32`, which is not FFI-safe
--> file/name.rs:42:19
|
42 | fn caller(callee: *const dyn Fn(i32)->i32) {
| ^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
= note: trait objects have no C equivalent
= note: `#[warn(improper_ctypes_definitions)]` on by default
```
new warning:
```
warning: `extern` fn uses type `dyn Fn(i32) -> i32`, which is not FFI-safe
--> file/name.rs:42:19
|
42 | fn caller(callee: *const dyn Fn(i32)->i32) -> (){
| ^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
= note: this pointer to an unsized type contains metadata, which makes it incompatible with a C pointer
= note: `#[warn(improper_ctypes_definitions)]` on by default
```
On nightly, we mention the trait is unstable
```
error[E0277]: the trait bound `T: Unstable` is not satisfied
--> $DIR/unstable-trait-suggestion.rs:13:9
|
LL | foo(t)
| --- ^ the trait `Unstable` is not implemented for `T`
| |
| required by a bound introduced by this call
|
note: required by a bound in `foo`
--> $DIR/unstable-trait-suggestion.rs:9:11
|
LL | fn foo<T: Unstable>(_: T) {}
| ^^^^^^^^ required by this bound in `foo`
help: consider restricting type parameter `T` but it is an `unstable` trait
|
LL | pub fn demo<T: Unstable>(t: T) {
| ++++++++++
```
On stable, we don't suggest the trait at all
```
error[E0277]: the trait bound `T: Unstable` is not satisfied
--> $DIR/unstable-trait-suggestion.rs:13:9
|
LL | foo(t)
| --- ^ the trait `Unstable` is not implemented for `T`
| |
| required by a bound introduced by this call
|
note: required by a bound in `foo`
--> $DIR/unstable-trait-suggestion.rs:9:11
|
LL | fn foo<T: Unstable>(_: T) {}
| ^^^^^^^^ required by this bound in `foo`
```
When encountering a type or trait mismatch for two types coming from two different crates with the same name, detect if it is either mixing two types/traits from the same crate on different versions:
```
error[E0308]: mismatched types
--> replaced
|
LL | do_something_type(Type);
| ----------------- ^^^^ expected `dependency::Type`, found `dep_2_reexport::Type`
| |
| arguments to this function are incorrect
|
note: two different versions of crate `dependency` are being used; two types coming from two different versions of the same crate are different types even if they look the same
--> replaced
|
LL | pub struct Type(pub i32);
| ^^^^^^^^^^^^^^^ this is the expected type `dependency::Type`
|
::: replaced
|
LL | pub struct Type;
| ^^^^^^^^^^^^^^^ this is the found type `dep_2_reexport::Type`
|
::: replaced
|
LL | extern crate dep_2_reexport;
| ---------------------------- one version of crate `dependency` is used here, as a dependency of crate `foo`
LL | extern crate dependency;
| ------------------------ one version of crate `dependency` is used here, as a direct dependency of the current crate
= help: you can use `cargo tree` to explore your dependency tree
note: function defined here
--> replaced
|
LL | pub fn do_something_type(_: Type) {}
| ^^^^^^^^^^^^^^^^^
error[E0308]: mismatched types
--> replaced
|
LL | do_something_trait(Box::new(Type) as Box<dyn Trait2>);
| ------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `dependency::Trait2`, found trait `dep_2_reexport::Trait2`
| |
| arguments to this function are incorrect
|
note: two different versions of crate `dependency` are being used; two types coming from two different versions of the same crate are different types even if they look the same
--> replaced
|
LL | pub trait Trait2 {}
| ^^^^^^^^^^^^^^^^ this is the expected trait `dependency::Trait2`
|
::: replaced
|
LL | pub trait Trait2 {}
| ^^^^^^^^^^^^^^^^ this is the found trait `dep_2_reexport::Trait2`
|
::: replaced
|
LL | extern crate dep_2_reexport;
| ---------------------------- one version of crate `dependency` is used here, as a dependency of crate `foo`
LL | extern crate dependency;
| ------------------------ one version of crate `dependency` is used here, as a direct dependency of the current crate
= help: you can use `cargo tree` to explore your dependency tree
note: function defined here
--> replaced
|
LL | pub fn do_something_trait(_: Box<dyn Trait2>) {}
| ^^^^^^^^^^^^^^^^^^
```
or if it is different crates that were renamed to the same name:
```
error[E0308]: mismatched types
--> $DIR/type-mismatch-same-crate-name.rs:21:20
|
LL | a::try_foo(foo2);
| ---------- ^^^^ expected `main:🅰️:Foo`, found a different `main:🅰️:Foo`
| |
| arguments to this function are incorrect
|
note: two types coming from two different crates are different types even if they look the same
--> $DIR/auxiliary/crate_a2.rs:1:1
|
LL | pub struct Foo;
| ^^^^^^^^^^^^^^ this is the found type `crate_a2::Foo`
|
::: $DIR/auxiliary/crate_a1.rs:1:1
|
LL | pub struct Foo;
| ^^^^^^^^^^^^^^ this is the expected type `crate_a1::Foo`
|
::: $DIR/type-mismatch-same-crate-name.rs:13:17
|
LL | let foo2 = {extern crate crate_a2 as a; a::Foo};
| --------------------------- one type comes from crate `crate_a2` is used here, which is renamed locally to `a`
...
LL | extern crate crate_a1 as a;
| --------------------------- one type comes from crate `crate_a1` is used here, which is renamed locally to `a`
note: function defined here
--> $DIR/auxiliary/crate_a1.rs:10:8
|
LL | pub fn try_foo(x: Foo){}
| ^^^^^^^
error[E0308]: mismatched types
--> $DIR/type-mismatch-same-crate-name.rs:27:20
|
LL | a::try_bar(bar2);
| ---------- ^^^^ expected trait `main:🅰️:Bar`, found a different trait `main:🅰️:Bar`
| |
| arguments to this function are incorrect
|
note: two types coming from two different crates are different types even if they look the same
--> $DIR/auxiliary/crate_a2.rs:3:1
|
LL | pub trait Bar {}
| ^^^^^^^^^^^^^ this is the found trait `crate_a2::Bar`
|
::: $DIR/auxiliary/crate_a1.rs:3:1
|
LL | pub trait Bar {}
| ^^^^^^^^^^^^^ this is the expected trait `crate_a1::Bar`
|
::: $DIR/type-mismatch-same-crate-name.rs:13:17
|
LL | let foo2 = {extern crate crate_a2 as a; a::Foo};
| --------------------------- one trait comes from crate `crate_a2` is used here, which is renamed locally to `a`
...
LL | extern crate crate_a1 as a;
| --------------------------- one trait comes from crate `crate_a1` is used here, which is renamed locally to `a`
note: function defined here
--> $DIR/auxiliary/crate_a1.rs:11:8
|
LL | pub fn try_bar(x: Box<Bar>){}
| ^^^^^^^
```
This new output unifies the E0308 errors detail with the pre-existing E0277 errors, and better differentiates the "`extern crate` renamed" and "same crate, different versions" cases.
Implementation of `fmt::FormattingOptions`
Tracking issue: #118117
Public API:
```rust
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct FormattingOptions { … }
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Sign {
Plus,
Minus
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum DebugAsHex {
Lower,
Upper
}
impl FormattingOptions {
pub fn new() -> Self;
pub fn sign(&mut self, sign: Option<Sign>) -> &mut Self;
pub fn sign_aware_zero_pad(&mut self, sign_aware_zero_pad: bool) -> &mut Self;
pub fn alternate(&mut self, alternate: bool) -> &mut Self;
pub fn fill(&mut self, fill: char) -> &mut Self;
pub fn align(&mut self, alignment: Option<Alignment>) -> &mut Self;
pub fn width(&mut self, width: Option<usize>) -> &mut Self;
pub fn precision(&mut self, precision: Option<usize>) -> &mut Self;
pub fn debug_as_hex(&mut self, debug_as_hex: Option<DebugAsHex>) -> &mut Self;
pub fn get_sign(&self) -> Option<Sign>;
pub fn get_sign_aware_zero_pad(&self) -> bool;
pub fn get_alternate(&self) -> bool;
pub fn get_fill(&self) -> char;
pub fn get_align(&self) -> Option<Alignment>;
pub fn get_width(&self) -> Option<usize>;
pub fn get_precision(&self) -> Option<usize>;
pub fn get_debug_as_hex(&self) -> Option<DebugAsHex>;
pub fn create_formatter<'a>(self, write: &'a mut (dyn Write + 'a)) -> Formatter<'a>;
}
impl<'a> Formatter<'a> {
pub fn new(write: &'a mut (dyn Write + 'a), options: FormattingOptions) -> Self;
pub fn with_options<'b>(&'b mut self, options: FormattingOptions) -> Formatter<'b>;
pub fn sign(&self) -> Option<Sign>;
pub fn options(&self) -> FormattingOptions;
}
```
Relevant changes from the public API in the tracking issue (I'm leaving out some stuff I consider obvious mistakes, like missing `#[derive(..)]`s and `pub` specifiers):
- `enum DebugAsHex`/`FormattingOptions::debug_as_hex`/`FormattingOptions::get_debug_as_hex`: To support `{:x?}` as well as `{:X?}`. I had completely missed these options in the ACP. I'm open for any and all bikeshedding, not married to the name.
- `fill`/`get_fill` now takes/returns `char` instead of `Option<char>`. This simply mirrors what `Formatter::fill` returns (with default being `' '`).
- Changed `zero_pad`/`get_zero_pad` to `sign_aware_zero_pad`/`get_sign_aware_zero_pad`. This also mirrors `Formatter::sign_aware_zero_pad`. While I'm not a fan of this quite verbose name, I do believe that having the interface of `Formatter` and `FormattingOptions` be compatible is more important.
- For the same reason, renamed `alignment`/`get_alignment` to `aling`/`get_align`.
- Deviating from my initial idea, `Formatter::with_options` returns a `Formatter` which has the lifetime of the `self` reference as its generic lifetime parameter (in the original API spec, the generic lifetime of the returned `Formatter` was the generic lifetime used by `self` instead). Otherwise, one could construct two `Formatter`s that both mutably borrow the same underlying buffer, which would be unsound. This solution still has performance benefits over simply using `Formatter::new`, so I believe it is worthwhile to keep this method.
Hide errors whose suggestions would contain error constants or types
best reviewed commit-by-commit.
This is work towards cleaning up everything around `lit_to_const` and its mir equivalent.
fixes#123809
Do not implement unsafe auto traits for types with unsafe fields
If a type has unsafe fields, its safety invariants are not simply the conjunction of its field types' safety invariants. Consequently, it's invalid to reason about the safety properties of these types in a purely structural manner — i.e., the manner in which `auto` traits are implemented. Consequently, auto implementations of unsafe auto traits should not be generated for types with unsafe fields.
Tracking: #132922
r? `@compiler-errors`
Stabilize noop_waker
Tracking Issue: #98286
This is a handy feature that's been used widely in tests and example async code and it'd be nice to make it available to users.
cc `@rust-lang/wg-async`
rust_for_linux: -Zreg-struct-return commandline flag for X86 (#116973)
Command line flag `-Zreg-struct-return` for X86 (32-bit) for rust-for-linux.
This flag enables the same behavior as the `abi_return_struct_as_int` target spec key.
- Tracking issue: https://github.com/rust-lang/rust/issues/116973
If a type has unsafe fields, its safety invariants are not simply
the conjunction of its field types' safety invariants. Consequently,
it's invalid to reason about the safety properties of these types
in a purely structural manner — i.e., the manner in which `auto`
traits are implemented.
Makes progress towards #132922.
Adapt codegen tests for NUW inference
These were broken by 462cb3cd6c
Let me know if you think we should have a FIXME / tracking issue to update the tests after the LLVM 20 upgrade to make these required.
`@rustbot` label: +llvm-main
r? `@nikic`
Normalize target-cpus.rs stdout test for LLVM changes
LLVM has recently added support for the `lime1` CPU in 35cce408ee, so the `target-cpus.rs` test currently produces different output depending on the LLVM version.
This CL adds a normalization directive, to remove the new CPU from the output list.
Alternatives fixes I can think of:
* Add two revisions of the test (one per LLVM version)
* Ignore the test on one of the LLVM versions
* I dislike this, because it's possible that the test won't get updated for the next LLVM version.
I don't think the exact list of target CPUs is relevant for this test, so it shouldn't be too bad if the normalization sticks around longer than necessary.
`@rustbot` label: +llvm-main
Replace black with ruff in `tidy`
`ruff` can both lint and format Python code (in fact, it should be a mostly drop-in replacement for `black` in terms of formatting), so it's not needed to use `black` anymore. This PR removes `black` and replaces it with `ruff`, to get rid of one Python dependency, and also to make Python formatting faster (although that's a small thing).
If we decide to merge this, we'll need to "reformat the world" - `ruff` is not perfectly compatible with `black`, and it also looks like `black` was actually ignoring some files before. I tried it locally (`./x test tidy --extra-checks=py:fmt --bless`) and it also reformatted some code in subtrees (e.g. `clippy` or `rustc_codegen_gcc`) - I'm not sure how to handle that.
implement checks for tail calls
Quoting the [RFC draft](https://github.com/phi-go/rfcs/blob/guaranteed-tco/text/0000-explicit-tail-calls.md):
> The argument to become is a function (or method) call, that exactly matches the function signature and calling convention of the callee. The intent is to ensure a matching ABI. Note that lifetimes may differ as long as they pass borrow checking, see [below](https://github.com/phi-go/rfcs/blob/guaranteed-tco/text/0000-explicit-tail-calls.md#return-type-coercion) for specifics on the return type.
> Tail calling closures and tail calling from closures is not allowed. This is due to the high implementation effort, see below, this restriction can be lifted by a future RFC.
> Invocations of operators were considered as valid targets but were rejected on grounds of being too error-prone. In any case, these can still be called as methods.
> Tail calling [variadic functions](https://doc.rust-lang.org/beta/unstable-book/language-features/c-variadic.html) and tail calling from variadic functions is not allowed. As support for variadic function is stabilized on a per target level, support for tail-calls regarding variadic functions would need to follow a similar approach. To avoid this complexity and to minimize implementation effort for backends, this interaction is currently not allowed but support can be added with a future RFC.
-----
The checks are implemented as a query, similarly to `check_unsafety`.
The code is cherry-picked straight out of #112657 which was written more than a year ago, so I expect we might need to change some things ^^"
Rollup of 10 pull requests
Successful merges:
- #118833 (Add lint against function pointer comparisons)
- #122161 (Fix suggestion when shorthand `self` has erroneous type)
- #133233 (Add context to "const in pattern" errors)
- #133761 (Update books)
- #133843 (Do not emit empty suggestion)
- #133863 (Rename `core_pattern_type` and `core_pattern_types` lib feature gates to `pattern_type_macro`)
- #133872 (No need to create placeholders for GAT args in confirm_object_candidate)
- #133874 (`fn_sig_for_fn_abi` should return a `ty::FnSig`, no need for a binder)
- #133890 (Add a new test ui/incoherent-inherent-impls/no-other-unrelated-errors to check E0116 does not cause unrelated errors)
- #133892 (Revert #133817)
r? `@ghost`
`@rustbot` modify labels: rollup
Add a new test ui/incoherent-inherent-impls/no-other-unrelated-errors to check E0116 does not cause unrelated errors
rustc xxx (we do not know) to 1.82.0 emits unrelated errors when E0116 is present (see #125814).
We do not know what caused and fixed it, but add a test to confirm rustc does not cause the same error in the future.
Rename `core_pattern_type` and `core_pattern_types` lib feature gates to `pattern_type_macro`
That's what the gates are actually gating, and the single char difference in naming was not helpful either
fixes#128987