Expand `for_loops_over_fallibles` lint to lint on fallibles behind references.
Extends the scope of the (warn-by-default) lint `for_loops_over_fallibles` from just `for _ in x` where `x: Option<_>/Result<_, _>` to also cover `x: &(mut) Option<_>/Result<_>`
```rs
fn main() {
// Current lints
for _ in Some(42) {}
for _ in Ok::<_, i32>(42) {}
// New lints
for _ in &Some(42) {}
for _ in &mut Some(42) {}
for _ in &Ok::<_, i32>(42) {}
for _ in &mut Ok::<_, i32>(42) {}
// Should not lint
for _ in Some(42).into_iter() {}
for _ in Some(42).iter() {}
for _ in Some(42).iter_mut() {}
for _ in Ok::<_, i32>(42).into_iter() {}
for _ in Ok::<_, i32>(42).iter() {}
for _ in Ok::<_, i32>(42).iter_mut() {}
}
```
<details><summary><code>cargo build</code> diff</summary>
```diff
diff --git a/old.out b/new.out
index 84215aa..ca195a7 100644
--- a/old.out
+++ b/new.out
`@@` -1,33 +1,93 `@@`
warning: for loop over an `Option`. This is more readably written as an `if let` statement
--> src/main.rs:3:14
|
3 | for _ in Some(42) {}
| ^^^^^^^^
|
= note: `#[warn(for_loops_over_fallibles)]` on by default
help: to check pattern in a loop use `while let`
|
3 | while let Some(_) = Some(42) {}
| ~~~~~~~~~~~~~~~ ~~~
help: consider using `if let` to clear intent
|
3 | if let Some(_) = Some(42) {}
| ~~~~~~~~~~~~ ~~~
warning: for loop over a `Result`. This is more readably written as an `if let` statement
--> src/main.rs:4:14
|
4 | for _ in Ok::<_, i32>(42) {}
| ^^^^^^^^^^^^^^^^
|
help: to check pattern in a loop use `while let`
|
4 | while let Ok(_) = Ok::<_, i32>(42) {}
| ~~~~~~~~~~~~~ ~~~
help: consider using `if let` to clear intent
|
4 | if let Ok(_) = Ok::<_, i32>(42) {}
| ~~~~~~~~~~ ~~~
-warning: `for-loops-over-fallibles` (bin "for-loops-over-fallibles") generated 2 warnings
- Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.04s
+warning: for loop over a `&Option`. This is more readably written as an `if let` statement
+ --> src/main.rs:7:14
+ |
+7 | for _ in &Some(42) {}
+ | ^^^^^^^^^
+ |
+help: to check pattern in a loop use `while let`
+ |
+7 | while let Some(_) = &Some(42) {}
+ | ~~~~~~~~~~~~~~~ ~~~
+help: consider using `if let` to clear intent
+ |
+7 | if let Some(_) = &Some(42) {}
+ | ~~~~~~~~~~~~ ~~~
+
+warning: for loop over a `&mut Option`. This is more readably written as an `if let` statement
+ --> src/main.rs:8:14
+ |
+8 | for _ in &mut Some(42) {}
+ | ^^^^^^^^^^^^^
+ |
+help: to check pattern in a loop use `while let`
+ |
+8 | while let Some(_) = &mut Some(42) {}
+ | ~~~~~~~~~~~~~~~ ~~~
+help: consider using `if let` to clear intent
+ |
+8 | if let Some(_) = &mut Some(42) {}
+ | ~~~~~~~~~~~~ ~~~
+
+warning: for loop over a `&Result`. This is more readably written as an `if let` statement
+ --> src/main.rs:9:14
+ |
+9 | for _ in &Ok::<_, i32>(42) {}
+ | ^^^^^^^^^^^^^^^^^
+ |
+help: to check pattern in a loop use `while let`
+ |
+9 | while let Ok(_) = &Ok::<_, i32>(42) {}
+ | ~~~~~~~~~~~~~ ~~~
+help: consider using `if let` to clear intent
+ |
+9 | if let Ok(_) = &Ok::<_, i32>(42) {}
+ | ~~~~~~~~~~ ~~~
+
+warning: for loop over a `&mut Result`. This is more readably written as an `if let` statement
+ --> src/main.rs:10:14
+ |
+10 | for _ in &mut Ok::<_, i32>(42) {}
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+help: to check pattern in a loop use `while let`
+ |
+10 | while let Ok(_) = &mut Ok::<_, i32>(42) {}
+ | ~~~~~~~~~~~~~ ~~~
+help: consider using `if let` to clear intent
+ |
+10 | if let Ok(_) = &mut Ok::<_, i32>(42) {}
+ | ~~~~~~~~~~ ~~~
+
+warning: `for-loops-over-fallibles` (bin "for-loops-over-fallibles") generated 6 warnings
+ Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.02s
```
</details>
-----
Question:
* ~~Currently, the article `an` is used for `&Option`, and `&mut Option` in the lint diagnostic, since that's what `Option` uses. Is this okay or should it be changed? (likewise, `a` is used for `&Result` and `&mut Result`)~~ The article `a` is used for `&Option`, `&mut Option`, `&Result`, `&mut Result` and (as before) `Result`. Only `Option` uses `an` (as before).
`@rustbot` label +A-lint
Fix OutsideLoop's error suggestion: adding label `'block` for `if` block.
For OutsideLoop we should not suggest add `'block` label in `if` block, or we wiil get another err: block label not supported here.
fixes#123261
Add some tests for public-private dependencies.
This adds some tests to show more scenarios for the `exported_private_dependencies` lint. Several of these illustrate that the lint is not working as expected, and I have annotated those places with `FIXME`.
Note also that this includes some diamond dependency structures which compiletest doesn't exactly support. However, I don't think it should be a problem, it just results in the common dependency being built twice.
Rollup of 7 pull requests
Successful merges:
- #125043 (reference type safety invariant docs: clarification)
- #125306 (Force the inner coroutine of an async closure to `move` if the outer closure is `move` and `FnOnce`)
- #125355 (Use Backtrace::force_capture instead of Backtrace::capture in rustc_log)
- #125382 (rustdoc: rename `issue-\d+.rs` tests to have meaningful names (part 7))
- #125391 (Minor serialize/span tweaks)
- #125395 (Remove unnecessary `.md` from the documentation sidebar)
- #125399 (Stop using `to_hir_binop` in codegen)
r? `@ghost`
`@rustbot` modify labels: rollup
Stop using `to_hir_binop` in codegen
This came up in https://github.com/rust-lang/rust/pull/125359#discussion_r1609401311 , and looking into it we can just use the `mir::BinOp`s directly instead of `hir::BinOpKind`s.
(AKA rather than going `mir::BinOp` → `hir::BinOpKind` → `IntPredicate`, just go `mir::BinOp` → `IntPredicate`.)
Use Backtrace::force_capture instead of Backtrace::capture in rustc_log
After https://github.com/rust-lang/rust/pull/125063, the compiler and custom drivers won't automatically set the RUST_BACKTRACE environment variable anymore, so we have to call `Backtrace::force_capture` instead of `Backtrace::capture` to unconditionally capture a backtrace.
rustc_log handles enabling backtraces via env vars itself, so we don't want RUST_BACKTRACE to make a difference.
Force the inner coroutine of an async closure to `move` if the outer closure is `move` and `FnOnce`
See the detailed comment in `upvar.rs`.
Fixes#124867.
Fixes#124487.
r? oli-obk
reference type safety invariant docs: clarification
The old text could have been read as saying that you can call a function if these requirements are upheld, which is definitely not true as they are an underapproximation of the actual safety invariant.
I removed the part about functions relaxing the requirements via their documentation... this seems incoherent with saying that it may actually be unsound to ever temporarily violate the requirement. Furthermore, a function *cannot* just relax this for its return value, that would in general be unsound. And the part about "unsafe code in a safe function may assume these invariants are ensured of arguments passed by the caller" also interacts with relaxing things: clearly, if the invariant has been relaxed, unsafe code cannot rely on it any more. There may be a place to give general guidance on what kinds of function contracts can exist, but the reference type is definitely not the right place to write that down.
I also took a clarification from https://github.com/rust-lang/rust/pull/121965 that is orthogonal to the rest of that PR.
Cc ```@joshlf``` ```@scottmcm```
This has no noticeable effect, but it makes these cases follow the
guidelines in the comments on `Spacing`, which say that `Joint` should
be used "for each token that (a) should be pretty-printed without a
space after it, and (b) is followed by a punctuation token".
These two tokens are both followed by a comma, which is a punctuation
token.
- Name the colon span as `colon_span` to distinguish it from the other
`span` local variable.
- Just use basic pattern matching, which is easier to read than `map_or`.
Typical uses of ThinLTO don't have any use for this as a standalone
file, but distributed ThinLTO uses this to make the linker phase more
efficient. With clang you'd do something like `clang -flto=thin
-fthin-link-bitcode=foo.indexing.o -c foo.c` and then get both foo.o
(full of bitcode) and foo.indexing.o (just the summary or index part of
the bitcode). That's then usable by a two-stage linking process that's
more friendly to distributed build systems like bazel, which is why I'm
working on this area.
I talked some to @teresajohnson about naming in this area, as things
seem to be a little confused between various blog posts and build
systems. "bitcode index" and "bitcode summary" tend to be a little too
ambiguous, and she tends to use "thin link bitcode" and "minimized
bitcode" (which matches the descriptions in LLVM). Since the clang
option is thin-link-bitcode, I went with that to try and not add a new
spelling in the world.
Per @dtolnay, you can work around the lack of this by using `lld
--thinlto-index-only` to do the indexing on regular .o files of
bitcode, but that is a bit wasteful on actions when we already have all
the information in rustc and could just write out the matching minimized
bitcode. I didn't test that at all in our infrastructure, because by the
time I learned that I already had this patch largely written.
An async closure may implement `FnMut`/`Fn` if it has no self-borrows
There's no reason that async closures may not implement `FnMut` or `Fn` if they don't actually borrow anything with the closure's env lifetime. Specifically, #123660 made it so that we don't always need to borrow captures from the closure's env.
See the doc comment on `should_reborrow_from_env_of_parent_coroutine_closure`:
c00957a3e2/compiler/rustc_hir_typeck/src/upvar.rs (L1777-L1823)
If there are no such borrows, then we are free to implement `FnMut` and `Fn` as permitted by our closure's inferred `ClosureKind`.
As far as I can tell, this change makes `async || {}` work in precisely the set of places they used to work before #120361.
Fixes#125247.
r? oli-obk
Disallow cast with trailing braced macro in let-else
This fixes an edge case I noticed while porting #118880 and #119062 to syn.
Previously, rustc incorrectly accepted code such as:
```rust
let foo = &std::ptr::null as &'static dyn std::ops::Fn() -> *const primitive! {
8
} else {
return;
};
```
even though a right curl brace `}` directly before `else` in a `let...else` statement is not supposed to be valid syntax.
Pattern types: Prohibit generic args on const params
Addresses https://github.com/rust-lang/rust/pull/123689/files#r1562676629.
NB: Technically speaking, *not* prohibiting generics args on const params is not a bug as `pattern_types` is an *internal* feature and as such any uncaught misuses of it are considered to be the fault of the user. However, permitting this makes me slightly uncomfortable esp. since we might want to make pattern types available to the public at some point and I don't want this oversight to be able to slip into the language (for comparison, ICEs triggered by the use of internal features are like super fine).
Furthermore, this is an ad hoc fix. A more general fix would be changing the representation of the pattern part of pattern types in such a way that it can reuse preexisting lowering routines for exprs / anon consts. See also this [Zulip discussion](https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/pattern.20type.20HIR.20nodes/near/432410768) and #124650.
Also note that we currently don't properly typeck the pattern of pat tys. This however is out of scope for this PR.
cc ``@oli-obk``
r? ``@spastorino`` as discussed
miri: rename intrinsic_fallback_checks_ub to intrinsic_fallback_is_spec
Checking UB is not the only concern, we also have to make sure we are not losing out on non-determinism.
r? ``@oli-obk`` (not urgent, take your time)
Add a footer in FileEncoder and check for it in MemDecoder
We have a few reports of ICEs due to decoding failures, where the fault does not lie with the compiler. The goal of this PR is to add some very lightweight and on-by-default validation to the compiler's outputs. If validation fails, we emit a fatal error for rmeta files in general that mentions the path that didn't load, and for incremental compilation artifacts we emit a verbose warning that tries to explain the situation and treat the artifacts as outdated.
The validation currently implemented here is very crude, and yet I think we have 11 ICE reports currently open (you can find them by searching issues for `1002111927320821928687967599834759150`) which this simple validation would have detected. The structure of the code changes here should permit the addition of further validation code, such as a checksum, if it is merited. I would like to have code to detect corruption such as reported in https://github.com/rust-lang/rust/issues/124719, but I'm not yet sure how to do that efficiently, and this PR is already a good size.
The ICE reports I have in mind that this PR would have smoothed over are:
https://github.com/rust-lang/rust/issues/124469https://github.com/rust-lang/rust/issues/123352https://github.com/rust-lang/rust/issues/123376 [^1]
https://github.com/rust-lang/rust/issues/99763https://github.com/rust-lang/rust/issues/93900.
---
[^1]: This one might be a compiler bug, but even if it is I think the workflow described is pushing the envelope of what we can support. This issue is one of the reasons this warning still asks people to file an issue.
offset: allow zero-byte offset on arbitrary pointers
As per prior `@rust-lang/opsem` [discussion](https://github.com/rust-lang/opsem-team/issues/10) and [FCP](https://github.com/rust-lang/unsafe-code-guidelines/issues/472#issuecomment-1793409130):
- Zero-sized reads and writes are allowed on all sufficiently aligned pointers, including the null pointer
- Inbounds-offset-by-zero is allowed on all pointers, including the null pointer
- `offset_from` on two pointers derived from the same allocation is always allowed when they have the same address
This removes surprising UB (in particular, even C++ allows "nullptr + 0", which we currently disallow), and it brings us one step closer to an important theoretical property for our semantics ("provenance monotonicity": if operations are valid on bytes without provenance, then adding provenance can't make them invalid).
The minimum LLVM we require (v17) includes https://reviews.llvm.org/D154051, so we can finally implement this.
The `offset_from` change is needed to maintain the equivalence with `offset`: if `let ptr2 = ptr1.offset(N)` is well-defined, then `ptr2.offset_from(ptr1)` should be well-defined and return N. Now consider the case where N is 0 and `ptr1` dangles: we want to still allow offset_from here.
I think we should change offset_from further, but that's a separate discussion.
Fixes https://github.com/rust-lang/rust/issues/65108
[Tracking issue](https://github.com/rust-lang/rust/issues/117945) | [T-lang summary](https://github.com/rust-lang/rust/pull/117329#issuecomment-1951981106)
Cc `@nikic`
Make sure that the method resolution matches in `note_source_of_type_mismatch_constraint`
`note_source_of_type_mismatch_constraint` is a pile of hacks that I implemented to cover up another pile of hacks.
It does a bunch of re-confirming methods, but it wasn't previously checking that the methods it was looking (back) up were equal to the methods we previously had. This PR adds those checks.
Fixes#118185