Skip to content

Commit 5f4e067

Browse files
committed
Auto merge of #94814 - matthiaskrgr:rollup-a5sk366, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #94440 (Better error for normalization errors from parent crates that use `#![feature(generic_const_exprs)]`) - #94587 (Document new recommended use of `FromIterator::from_iter`) - #94644 (Fix soundness issue in scoped threads.) - #94740 (Unify impl blocks by wrapping them into a div) - #94753 (Improve rustdoc book) - #94796 (Allow `cargo run` instead of `cargo run -p bootstrap`) - #94805 (Revert accidental stabilization) - #94809 (RustWrapper: add missing include) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents ba14a83 + 07e4fbd commit 5f4e067

37 files changed

+338
-150
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
[workspace]
2+
default-members = ["src/bootstrap"]
23
members = [
34
"src/bootstrap",
45
"compiler/rustc",

compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "llvm/Object/Archive.h"
1010
#include "llvm/Object/COFFImportFile.h"
1111
#include "llvm/Object/ObjectFile.h"
12+
#include "llvm/Pass.h"
1213
#include "llvm/Bitcode/BitcodeWriterPass.h"
1314
#include "llvm/Support/Signals.h"
1415
#include "llvm/ADT/Optional.h"

compiler/rustc_trait_selection/src/traits/const_evaluatable.rs

+63-25
Original file line numberDiff line numberDiff line change
@@ -35,34 +35,14 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
3535
span: Span,
3636
) -> Result<(), NotConstEvaluatable> {
3737
debug!("is_const_evaluatable({:?})", uv);
38-
if infcx.tcx.features().generic_const_exprs {
39-
let tcx = infcx.tcx;
38+
let tcx = infcx.tcx;
39+
40+
if tcx.features().generic_const_exprs {
4041
match AbstractConst::new(tcx, uv)? {
4142
// We are looking at a generic abstract constant.
4243
Some(ct) => {
43-
for pred in param_env.caller_bounds() {
44-
match pred.kind().skip_binder() {
45-
ty::PredicateKind::ConstEvaluatable(uv) => {
46-
if let Some(b_ct) = AbstractConst::new(tcx, uv)? {
47-
// Try to unify with each subtree in the AbstractConst to allow for
48-
// `N + 1` being const evaluatable even if theres only a `ConstEvaluatable`
49-
// predicate for `(N + 1) * 2`
50-
let result =
51-
walk_abstract_const(tcx, b_ct, |b_ct| {
52-
match try_unify(tcx, ct, b_ct) {
53-
true => ControlFlow::BREAK,
54-
false => ControlFlow::CONTINUE,
55-
}
56-
});
57-
58-
if let ControlFlow::Break(()) = result {
59-
debug!("is_const_evaluatable: abstract_const ~~> ok");
60-
return Ok(());
61-
}
62-
}
63-
}
64-
_ => {} // don't care
65-
}
44+
if satisfied_from_param_env(tcx, ct, param_env)? {
45+
return Ok(());
6646
}
6747

6848
// We were unable to unify the abstract constant with
@@ -163,6 +143,33 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
163143
}
164144
}
165145

146+
// If we're evaluating a foreign constant, under a nightly compiler without generic
147+
// const exprs, AND it would've passed if that expression had been evaluated with
148+
// generic const exprs, then suggest using generic const exprs.
149+
if concrete.is_err()
150+
&& tcx.sess.is_nightly_build()
151+
&& !uv.def.did.is_local()
152+
&& !tcx.features().generic_const_exprs
153+
&& let Ok(Some(ct)) = AbstractConst::new(tcx, uv)
154+
&& satisfied_from_param_env(tcx, ct, param_env) == Ok(true)
155+
{
156+
tcx.sess
157+
.struct_span_fatal(
158+
// Slightly better span than just using `span` alone
159+
if span == rustc_span::DUMMY_SP { tcx.def_span(uv.def.did) } else { span },
160+
"failed to evaluate generic const expression",
161+
)
162+
.note("the crate this constant originates from uses `#![feature(generic_const_exprs)]`")
163+
.span_suggestion_verbose(
164+
rustc_span::DUMMY_SP,
165+
"consider enabling this feature",
166+
"#![feature(generic_const_exprs)]\n".to_string(),
167+
rustc_errors::Applicability::MaybeIncorrect,
168+
)
169+
.emit();
170+
rustc_errors::FatalError.raise();
171+
}
172+
166173
debug!(?concrete, "is_const_evaluatable");
167174
match concrete {
168175
Err(ErrorHandled::TooGeneric) => Err(match uv.has_infer_types_or_consts() {
@@ -178,6 +185,37 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
178185
}
179186
}
180187

188+
fn satisfied_from_param_env<'tcx>(
189+
tcx: TyCtxt<'tcx>,
190+
ct: AbstractConst<'tcx>,
191+
param_env: ty::ParamEnv<'tcx>,
192+
) -> Result<bool, NotConstEvaluatable> {
193+
for pred in param_env.caller_bounds() {
194+
match pred.kind().skip_binder() {
195+
ty::PredicateKind::ConstEvaluatable(uv) => {
196+
if let Some(b_ct) = AbstractConst::new(tcx, uv)? {
197+
// Try to unify with each subtree in the AbstractConst to allow for
198+
// `N + 1` being const evaluatable even if theres only a `ConstEvaluatable`
199+
// predicate for `(N + 1) * 2`
200+
let result =
201+
walk_abstract_const(tcx, b_ct, |b_ct| match try_unify(tcx, ct, b_ct) {
202+
true => ControlFlow::BREAK,
203+
false => ControlFlow::CONTINUE,
204+
});
205+
206+
if let ControlFlow::Break(()) = result {
207+
debug!("is_const_evaluatable: abstract_const ~~> ok");
208+
return Ok(true);
209+
}
210+
}
211+
}
212+
_ => {} // don't care
213+
}
214+
}
215+
216+
Ok(false)
217+
}
218+
181219
/// A tree representing an anonymous constant.
182220
///
183221
/// This is only able to represent a subset of `MIR`,

library/alloc/src/boxed.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1170,8 +1170,7 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
11701170
}
11711171

11721172
#[stable(feature = "rust1", since = "1.0.0")]
1173-
#[rustc_const_unstable(feature = "const_box", issue = "92521")]
1174-
unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> const Drop for Box<T, A> {
1173+
unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Box<T, A> {
11751174
fn drop(&mut self) {
11761175
// FIXME: Do nothing, drop is currently performed by compiler.
11771176
}

library/alloc/tests/boxed.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ fn const_box() {
160160
*boxed = 42;
161161
assert!(*boxed == 42);
162162

163-
*boxed
163+
*Box::leak(boxed)
164164
};
165165

166166
assert!(VALUE == 42);

library/core/src/iter/traits/collect.rs

+16-3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
/// created from an iterator. This is common for types which describe a
55
/// collection of some kind.
66
///
7-
/// [`FromIterator::from_iter()`] is rarely called explicitly, and is instead
8-
/// used through [`Iterator::collect()`] method. See [`Iterator::collect()`]'s
9-
/// documentation for more examples.
7+
/// If you want to create a collection from the contents of an iterator, the
8+
/// [`Iterator::collect()`] method is preferred. However, when you need to
9+
/// specify the container type, [`FromIterator::from_iter()`] can be more
10+
/// readable than using a turbofish (e.g. `::<Vec<_>>()`). See the
11+
/// [`Iterator::collect()`] documentation for more examples of its use.
1012
///
1113
/// See also: [`IntoIterator`].
1214
///
@@ -32,6 +34,17 @@
3234
/// assert_eq!(v, vec![5, 5, 5, 5, 5]);
3335
/// ```
3436
///
37+
/// Using [`FromIterator::from_iter()`] as a more readable alternative to
38+
/// [`Iterator::collect()`]:
39+
///
40+
/// ```
41+
/// use std::collections::VecDeque;
42+
/// let first = (0..10).collect::<VecDeque<i32>>();
43+
/// let second = VecDeque::from_iter(0..10);
44+
///
45+
/// assert_eq!(first, second);
46+
/// ```
47+
///
3548
/// Implementing `FromIterator` for your type:
3649
///
3750
/// ```

library/std/src/lib.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,11 @@ extern crate std as realstd;
364364
#[macro_use]
365365
mod macros;
366366

367+
// The runtime entry point and a few unstable public functions used by the
368+
// compiler
369+
#[macro_use]
370+
pub mod rt;
371+
367372
// The Rust prelude
368373
pub mod prelude;
369374

@@ -548,11 +553,6 @@ pub mod arch {
548553
#[stable(feature = "simd_x86", since = "1.27.0")]
549554
pub use std_detect::is_x86_feature_detected;
550555

551-
// The runtime entry point and a few unstable public functions used by the
552-
// compiler
553-
#[macro_use]
554-
pub mod rt;
555-
556556
// Platform-abstraction modules
557557
mod sys;
558558
mod sys_common;

library/std/src/thread/mod.rs

+23-4
Original file line numberDiff line numberDiff line change
@@ -1287,12 +1287,31 @@ unsafe impl<'scope, T: Sync> Sync for Packet<'scope, T> {}
12871287

12881288
impl<'scope, T> Drop for Packet<'scope, T> {
12891289
fn drop(&mut self) {
1290+
// If this packet was for a thread that ran in a scope, the thread
1291+
// panicked, and nobody consumed the panic payload, we make sure
1292+
// the scope function will panic.
1293+
let unhandled_panic = matches!(self.result.get_mut(), Some(Err(_)));
1294+
// Drop the result without causing unwinding.
1295+
// This is only relevant for threads that aren't join()ed, as
1296+
// join() will take the `result` and set it to None, such that
1297+
// there is nothing left to drop here.
1298+
// If this panics, we should handle that, because we're outside the
1299+
// outermost `catch_unwind` of our thread.
1300+
// We just abort in that case, since there's nothing else we can do.
1301+
// (And even if we tried to handle it somehow, we'd also need to handle
1302+
// the case where the panic payload we get out of it also panics on
1303+
// drop, and so on. See issue #86027.)
1304+
if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| {
1305+
*self.result.get_mut() = None;
1306+
})) {
1307+
rtabort!("thread result panicked on drop");
1308+
}
12901309
// Book-keeping so the scope knows when it's done.
12911310
if let Some(scope) = self.scope {
1292-
// If this packet was for a thread that ran in a scope, the thread
1293-
// panicked, and nobody consumed the panic payload, we make sure
1294-
// the scope function will panic.
1295-
let unhandled_panic = matches!(self.result.get_mut(), Some(Err(_)));
1311+
// Now that there will be no more user code running on this thread
1312+
// that can use 'scope, mark the thread as 'finished'.
1313+
// It's important we only do this after the `result` has been dropped,
1314+
// since dropping it might still use things it borrowed from 'scope.
12961315
scope.decrement_num_running_threads(unhandled_panic);
12971316
}
12981317
}

library/std/src/thread/tests.rs

+24-3
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ use crate::mem;
44
use crate::panic::panic_any;
55
use crate::result;
66
use crate::sync::{
7+
atomic::{AtomicBool, Ordering},
78
mpsc::{channel, Sender},
89
Arc, Barrier,
910
};
10-
use crate::thread::{self, ThreadId};
11+
use crate::thread::{self, Scope, ThreadId};
1112
use crate::time::Duration;
1213
use crate::time::Instant;
1314

@@ -293,5 +294,25 @@ fn test_thread_id_not_equal() {
293294
assert!(thread::current().id() != spawned_id);
294295
}
295296

296-
// NOTE: the corresponding test for stderr is in ui/thread-stderr, due
297-
// to the test harness apparently interfering with stderr configuration.
297+
#[test]
298+
fn test_scoped_threads_drop_result_before_join() {
299+
let actually_finished = &AtomicBool::new(false);
300+
struct X<'scope, 'env>(&'scope Scope<'scope, 'env>, &'env AtomicBool);
301+
impl Drop for X<'_, '_> {
302+
fn drop(&mut self) {
303+
thread::sleep(Duration::from_millis(20));
304+
let actually_finished = self.1;
305+
self.0.spawn(move || {
306+
thread::sleep(Duration::from_millis(20));
307+
actually_finished.store(true, Ordering::Relaxed);
308+
});
309+
}
310+
}
311+
thread::scope(|s| {
312+
s.spawn(move || {
313+
thread::sleep(Duration::from_millis(20));
314+
X(s, actually_finished)
315+
});
316+
});
317+
assert!(actually_finished.load(Ordering::Relaxed));
318+
}

src/doc/rustdoc/book.toml

+4
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,7 @@ title = "The rustdoc book"
44

55
[output.html]
66
git-repository-url = "https://github.com/rust-lang/rust/tree/master/src/doc/rustdoc"
7+
8+
[output.html.redirect]
9+
"/the-doc-attribute.html" = "write-documentation/the-doc-attribute.html"
10+
"/documentation-tests.html" = "write-documentation/documentation-tests.html"

src/doc/rustdoc/src/SUMMARY.md

+7-8
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
# The Rustdoc Book
22

33
- [What is rustdoc?](what-is-rustdoc.md)
4+
- [Command-line arguments](command-line-arguments.md)
45
- [How to read rustdoc output](how-to-read-rustdoc.md)
56
- [How to write documentation](how-to-write-documentation.md)
6-
- [What to include (and exclude)](what-to-include.md)
7-
- [Command-line arguments](command-line-arguments.md)
8-
- [The `#[doc]` attribute](the-doc-attribute.md)
9-
- [Documentation tests](documentation-tests.md)
10-
- [Linking to items by name](linking-to-items-by-name.md)
11-
- [Lints](lints.md)
7+
- [What to include (and exclude)](write-documentation/what-to-include.md)
8+
- [The `#[doc]` attribute](write-documentation/the-doc-attribute.md)
9+
- [Linking to items by name](write-documentation/linking-to-items-by-name.md)
10+
- [Documentation tests](write-documentation/documentation-tests.md)
11+
- [Rustdoc-specific lints](lints.md)
1212
- [Advanced features](advanced-features.md)
1313
- [Unstable features](unstable-features.md)
14-
- [Website features](website-features.md)
15-
- [Passes](passes.md)
14+
- [Deprecated features](deprecated-features.md)
1615
- [References](references.md)

src/doc/rustdoc/src/advanced-features.md

+22
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,25 @@ You can add multiple aliases at the same time by using a list:
8888
#[doc(alias("x", "big"))]
8989
pub struct BigX;
9090
```
91+
92+
## Custom search engines
93+
94+
If you find yourself often referencing online Rust docs you might enjoy using a custom search
95+
engine. This allows you to use the navigation bar directly to search a `rustdoc` website.
96+
Most browsers support this feature by letting you define a URL template containing `%s`
97+
which will be substituted for the search term. As an example, for the standard library you could use
98+
this template:
99+
100+
```text
101+
https://doc.rust-lang.org/stable/std/?search=%s
102+
```
103+
104+
Note that this will take you to a results page listing all matches. If you want to navigate to the first
105+
result right away (which is often the best match) use the following instead:
106+
107+
```text
108+
https://doc.rust-lang.org/stable/std/?search=%s&go_to_first=true
109+
```
110+
111+
This URL adds the `go_to_first=true` query parameter which can be appended to any `rustdoc` search URL
112+
to automatically go to the first result.

0 commit comments

Comments
 (0)