Fix missing attribute merge on glob foreign re-exports
Fixes https://github.com/rust-lang/rust/issues/113982.
The attributes were not merged with the import's in case of glob re-export of foreign items.
r? `@notriddle`
lint/ctypes: fix `()` return type checks
Fixes#113436.
`()` is normally FFI-unsafe, but is FFI-safe when used as a return type. It is also desirable that a transparent newtype for `()` is FFI-safe when used as a return type.
In order to support this, when a type was deemed FFI-unsafe, because of a `()` type, and was used in return type - then the type was considered FFI-safe. However, this was the wrong approach - it didn't check that the `()` was part of a transparent newtype! The consequence of this is that the presence of a `()` type in a more complex return type would make it the entire type be considered safe (as long as the `()` type was the first that the lint found) - which is obviously incorrect.
Instead, this logic is removed, and after [consultation with t-lang](https://github.com/rust-lang/rust/issues/113436#issuecomment-1640756721), I've fixed the bugs and inconsistencies and made `()` FFI-safe within types.
I also refactor a function, but that's not too exciting.
new unstable option: -Zwrite-long-types-to-disk
This option guards the logic of writing long type names in files and instead using short forms in error messages in rustc_middle/ty/error behind a flag. The main motivation for this change is to disable this behaviour when running ui tests.
This logic can be triggered by running tests in a directory that has a long enough path, e.g. /my/very-long-path/where/rust-codebase/exists/
This means ui tests can fail depending on how long the path to their file is.
Some ui tests actually rely on this behaviour for their assertions, so for those we enable the flag manually.
Double check that hidden types match the expected hidden type
Fixes https://github.com/rust-lang/rust/issues/113278 specifically, but I left a TODO for where we should also add some hardening.
It feels a bit like papering over the issue, but at least this way we don't get unsoundness, but just surprising errors. Errors will be improved and given spans before this PR lands.
r? `@compiler-errors` `@lcnr`
Don't say that a type is uncallable if its fn signature has errors in it
This is fallout from #106309, where we don't consider param-env candidates that reference errors because they unify with everything. This means, however, that we don't consider an APIT like `impl Fn(MissingType)` isn't considered to implement `Fn`, for example.
We can double-check that with a weaker heuristic [`extract_callable_info`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/fn_ctxt/struct.FnCtxt.html#method.extract_callable_info), and suppress the knock-down error using that.
Fixes#113566
Rollup of 7 pull requests
Successful merges:
- #114008 (coverage: Obtain the `__llvm_covfun` section name outside a per-function loop)
- #114014 (builtin_macros: expect raw strings too)
- #114043 (docs(LazyLock): add example pass local LazyLock variable to struct)
- #114051 (Add regression test for invalid "unused const" in method)
- #114052 (Suggest `{Option,Result}::as_ref()` instead of `cloned()` in some cases)
- #114058 (Add help for crate arg when crate name is invalid)
- #114060 (abi: unsized field in union - assert to delay bug )
r? `@ghost`
`@rustbot` modify labels: rollup
abi: unsized field in union - assert to delay bug
Fixes#113279.
> Unions cannot have unsized fields, and as such, layout computation for
unions asserts that each union field is sized (as this would normally
have halted compilation earlier).
>
> However, if a generator ends up with an unsized local - a circumstance
in which an error will always have been emitted earlier, for example, if
attempting to dereference a `&str` - then the generator transform will
produce a union with an unsized field.
>
> Since https://github.com/rust-lang/rust/pull/110107, later passes will be run, such as constant propagation,
and can attempt layout computation on the generator, which will result
in layout computation of `str` in the context of it being a field of a
union - and so the aforementioned assertion would cause an ICE.
>
> It didn't seem appropriate to try and detect this case in the MIR body
and skip this specific pass; tainting the MIR body or delaying a bug
from the generator transform (or elsewhere) wouldn't prevent this either
(as neither would prevent the later pass from running); and tainting when
the deref of `&str` is reported, if that's possible, would unnecessarily
prevent potential other errors from being reported later in compilation,
and is very tailored to this specific case of getting a unsized type in
a generator.
>
> Given that this circumstance can only happen when an error should have
already been reported, the correct fix appears to be just changing the
assert to a delayed bug. This will still assert if there is some
circumstance where this occurs and no error has been reported, but it
won't crash the compiler in this instance.
While debugging this, I noticed a translation ICE in a delayed bug, so I fixed that too:
> During borrowck, the `MultiSpan` from a buffered diagnostic is cloned and
used to emit a delayed bug indicating a diagnostic was buffered - when
the buffered diagnostic is translated, then the cloned `MultiSpan` may
contain labels which can only render with the diagnostic's arguments, but
the delayed bug being emitted won't have those arguments. Adds a function
which clones `MultiSpan` without also cloning the contained labels, and
use this function when creating the buffered diagnostic delayed bug.
Suggest `{Option,Result}::as_ref()` instead of `cloned()` in some cases
Fixes#114050
When we have an expr available that produces the type expectation, we can suggest appending `.as_ref()` to the span, instead of cloning the expr producing the mismatch
Add regression test for invalid "unused const" in method
The warning can be reproduced with 1.63 but not with 1.64.
$ rustc +1.63 tests/ui/lint/unused/const-local-var.rs
warning: constant `F` is never used
--> tests/ui/lint/unused/const-local-var.rs:14:9
|
14 | const F: i32 = 2;
| ^^^^^^^^^^^^^^^^^
|
= note: `#[warn(dead_code)]` on by default
$ rustc +1.64 tests/ui/lint/unused/const-local-var.rs
Add a regression test to prevent the problem from re-appearing.
Closes#69016
Normalize the RHS of an `Unsize` goal in the new solver
`Unsize` goals are... tricky. Not only do they structurally match on their self type, but they're also structural on their other type parameter. I'm pretty certain that it is both incomplete and also just plain undesirable to not consider normalizing the RHS of an unsize goal. More practically, I'd like for this code to work:
```rust
trait A {}
trait B: A {}
impl A for usize {}
impl B for usize {}
trait Mirror {
type Assoc: ?Sized;
}
impl<T: ?Sized> Mirror for T {
type Assoc = T;
}
fn main() {
// usize: Unsize<dyn B>
let x = Box::new(1usize) as Box<<dyn B as Mirror>::Assoc>;
// dyn A: Unsize<dyn B>
let y = x as Box<<dyn A as Mirror>::Assoc>;
}
```
---
In order to achieve this, we add `EvalCtxt::normalize_non_self_ty` (naming modulo bikeshedding), which *must* be used for all non-self type arguments that are structurally matched in candidate assembly. Currently this is only necessary for `Unsize`'s argument, but I could see future traits requiring this (hopefully rarely) in the future. It uses `repeat_while_none` to limit infinite looping, and normalizes the self type until it is no longer an alias.
Also, we need to fix feature gate detection for `trait_upcasting` and `unsized_tuple_coercion` when HIR typeck has unnormalized types. We can do that by checking the `ImplSource` returned by selection, which necessitates adding a new impl source for tuple upcasting.
Unions cannot have unsized fields, and as such, layout computation for
unions asserts that each union field is sized (as this would normally
have halted compilation earlier).
However, if a generator ends up with an unsized local - a circumstance
in which an error will always have been emitted earlier, for example, if
attempting to dereference a `&str` - then the generator transform will
produce a union with an unsized field.
Since #110107, later passes will be run, such as constant propagation,
and can attempt layout computation on the generator, which will result
in layout computation of `str` in the context of it being a field of a
union - and so the aforementioned assertion would cause an ICE.
It didn't seem appropriate to try and detect this case in the MIR body
and skip this specific pass; tainting the MIR body or delaying a bug
from the generator transform (or elsewhere) wouldn't prevent this either
(as neither would prevent the later pass from running); and tainting when
the deref of `&str` is reported, if that's possible, would unnecessarily
prevent potential other errors from being reported later in compilation,
and is very tailored to this specific case of getting a unsized type in
a generator.
Given that this circumstance can only happen when an error should have
already been reported, the correct fix appears to be just changing the
assert to a delayed bug. This will still assert if there is some
circumstance where this occurs and no error has been reported, but it
won't crash the compiler in this instance.
Signed-off-by: David Wood <david@davidtw.co>
interpret: Unify projections for MPlaceTy, PlaceTy, OpTy
For ~forever, we didn't really have proper shared code for handling projections into those three types. This is mostly because `PlaceTy` projections require `&mut self`: they might have to `force_allocate` to be able to represent a project part-way into a local.
This PR finally fixes that, by enhancing `Place::Local` with an `offset` so that such an optimized place can point into a part of a place without having requiring an in-memory representation. If we later write to that place, we will still do `force_allocate` -- for now we don't have an optimized path in `write_immediate` that would avoid allocation for partial overwrites of immediately stored locals. But in `write_immediate` we have `&mut self` so at least this no longer pollutes all our type signatures.
(Ironically, I seem to distantly remember that many years ago, `Place::Local` *did* have an `offset`, and I removed it to simplify things. I guess I didn't realize why it was so useful... I am also not sure if this was actually used to achieve place projection on `&self` back then.)
The `offset` had type `Option<Size>`, where `None` represent "no projection was applied". This is needed because locals *can* be unsized (when they are arguments) but `Place::Local` cannot store metadata: if the offset is `None`, this refers to the entire local, so we can use the metadata of the local itself (which must be indirect); if a projection gets applied, since the local is indirect, it will turn into a `Place::Ptr`. (Note that even for indirect locals we can have `Place::Local`: when the local appears in MIR, we always start with `Place::Local`, and only check `frame.locals` later. We could eagerly normalize to `Place::Ptr` but I don't think that would actually simplify things much.)
Having done all that, we can finally properly abstract projections: we have a new `Projectable` trait that has the basic methods required for projecting, and then all projection methods are implemented for anything that implements that trait. We can even implement it for `ImmTy`! (Not that we need that, but it seems neat.) The visitor can be greatly simplified; it doesn't need its own trait any more but it can use the `Projectable` trait. We also don't need the separate `Mut` visitor any more; that was required only to reflect that projections on `PlaceTy` needed `&mut self`.
It is possible that there are some more `&mut self` that can now become `&self`... I guess we'll notice that over time.
r? `@oli-obk`
Reimplement C-str literals
This reverts #113334, cc `@fmease.`
While converting lexer tokens to ast Tokens in `rustc_parse`, we check the edition of the span of the token. If the edition < 2021, we split the token into two, one being the identifier and other being the str literal.
The warning can be reproduced with 1.63 but not with 1.64.
$ rustc +1.63 tests/ui/lint/unused/const-local-var.rs
warning: constant `F` is never used
--> tests/ui/lint/unused/const-local-var.rs:14:9
|
14 | const F: i32 = 2;
| ^^^^^^^^^^^^^^^^^
|
= note: `#[warn(dead_code)]` on by default
$ rustc +1.64 tests/ui/lint/unused/const-local-var.rs
Add a regression test to prevent the problem from re-appearing.
If a raw string was used in the `env!` invocation, then it should also
be shown in the diagnostic messages as a raw string.
Signed-off-by: David Wood <david@davidtw.co>
fix(resolve): skip panic when resolution is dummy
Fixes#113953
Skip the panic when the binding refers to a dummy node during the finalization.
r? `@petrochenkov`
fix intra-doc links on nested `use` and `extern crate` items
This PR fixes two rustdoc ICEs that happen if there are any intra-doc links on nested `use` or `extern crate` items, for example:
```rust
/// Re-export [`fmt`] and [`io`].
pub use std::{fmt, io}; // "nested" use = use with braces
/// Re-export [`std`].
pub extern crate std;
```
Nested use items were incorrectly considered private and therefore didn't have their intra-doc links resolved. I fixed this by always resolving intra-doc links for nested `use` items that are declared `pub`.
<details>
During AST->HIR lowering, nested `use` items are desugared like this:
```rust
pub use std::{}; // "list stem"
pub use std::fmt;
pub use std::io;
```
Each of these HIR nodes has it's own effective visibility and the list stem is always considered private.
To check the effective visibility of an AST node, the AST node is mapped to a HIR node with `Resolver::local_def_id`, which returns the (private) list stem for nested use items.
</details>
For `extern crate`, there was a hack in rustdoc that stored the `DefId` of the crate itself in the cleaned item, instead of the `DefId` of the `extern crate` item. This made rustdoc look at the resolved links of the extern crate's crate root instead of the `extern crate` item. I've removed this hack and instead translate the `DefId` in the appropriate places.
As as side effect of fixing `extern crate`, i've turned
```rust
#[doc(masked)]
extern crate self as _;
```
into a no-op instead of hiding all trait impls. Proper verification for `doc(masked)` is included as a bonus.
fixes https://github.com/rust-lang/rust/issues/113896
Add #[inline] to core debug assertion helpers
These functions are called a lot and not inlined by default in a dev compiler. Adding `#[inline]` should improve things in a dev workflow and be irrelevant in the distributed library.
lint/ctypes: only try normalize
Fixes#113900.
Now that this lint runs on any external-ABI fn-ptr, normalization won't always succeed, so use `try_normalize_erasing_regions` instead.
rustdoc: handle cross-crate RPITITs correctly
Filter out the internal associated types synthesized during the desugaring of RPITITs, they really shouldn't show up in the docs.
This also fixes#113929 since we're no longer invoking `is_impossible_associated_item` (renamed from `is_impossible_method`) which cannot handle them (leading to an ICE). I don't think it makes sense to try to make `is_impossible_associated_item` handle this exotic kind of associated type (CC original author `@compiler-errors).`
@ T-rustdoc reviewers, currently I'm throwing out ITIT assoc tys before cleaning assoc tys at each usage-site. I'm thinking about making `clean_middle_assoc_item` return an `Option<_>` instead and doing the check inside of it to prevent any call sites from forgetting the check for ITITs. Since I wasn't sure if you would like that approach, I didn't go through with it. Let me know what you think.
<details><summary>Explanation on why <code>is_impossible_associated_item(itit_assoc_ty)</code> leads to an ICE</summary>
Given the following code:
```rs
pub trait Trait { fn def<T>() -> impl Default {} }
impl Trait for () {}
```
The generated associated type looks something like (simplified):
```rs
type {opaque#0}<T>: Default = impl Default; // the name is actually `kw::Empty` but this is the `def_path_str` repr
```
The query `is_impossible_associated_item` goes through all predicates of the associated item – in this case `<T as Sized>` – to check if they contain any generic parameters from the (generic) associated type itself. For predicates that don't contain any *own* generics, it does further processing, part of which is instantiating the predicate with the generic arguments of the impl block (which is only correct if they truly don't contain any own generics since they wouldn't get instantiated this way leading to an ICE).
It checks if `parent_def_id(T) == assoc_ty_def_id` to get to know if `T` is owned by the assoc ty. Unfortunately this doesn't work for ITIT assoc tys. In this case, the parent of `T` is `Trait::def` (!) which is the associated function (I'm pretty sure this is very intentional) which is of course not equal to the assoc ty `Trait::{opaque#0}`.
</details>
`@rustbot` label A-cross-crate-reexports
This option guards the logic of writing long type names in files and
instead using short forms in error messages in rustc_middle/ty/error
behind a flag. The main motivation for this change is to disable this
behaviour when running ui tests.
This logic can be triggered by running tests in a directory that has a
long enough path, e.g. /my/very-long-path/where/rust-codebase/exists/
This means ui tests can fail depending on how long the path to their
file is.
Some ui tests actually rely on this behaviour for their assertions,
so for those we enable the flag manually.
Fix #[inline(always)] on closures with target feature 1.1
Fixes#108655. I think this is the most obvious solution that isn't overly complicated. The comment includes more justification, but I think this is likely better than demoting the `#[inline(always)]` to `#[inline]`, since existing code is unaffected.
Support interpolated block for `try` and `async`
I'm putting this up for T-lang discussion, to decide whether or not they feel like this should be supported. This was raised in #112952, which surprised me. There doesn't seem to be a *technical* reason why we don't support this.
### Precedent:
This is supported:
```rust
macro_rules! always {
($block:block) => {
if true $block
}
}
fn main() {
always!({});
}
```
### Counterpoint:
However, for context, this is *not* supported:
```rust
macro_rules! unsafe_block {
($block:block) => {
unsafe $block
}
}
fn main() {
unsafe_block!({});
}
```
If this support for `async` and `try` with interpolated blocks is *not* desirable, then I can convert them to instead the same diagnostic as `unsafe $block` and make this situation a lot less ambiguous.
----
I'll try to write up more before T-lang triage on Tuesday. I couldn't find anything other than #69760 for why something like `unsafe $block` is not supported, and even that PR doesn't have much information.
Fixes#112952