Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 7 pull requests #94801

Closed
wants to merge 22 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
c956fe5
Document new recommended use of method
Mar 4, 2022
5f34c04
Make use statement visible
Mar 4, 2022
b363f13
Add suggested changes to the docs
Mar 4, 2022
b328688
Statically compile libstdc++ everywhere if asked
Mar 8, 2022
a5216cf
Unify inherent impl blocks by wrapping them into a div
GuillaumeGomez Mar 8, 2022
fbd9c28
Update GUI tests for impl blocks path changes
GuillaumeGomez Mar 8, 2022
4e067e8
Improve rustdoc book
Urgau Mar 8, 2022
5226395
Fix soundness issue in scoped threads.
m-ou-se Mar 5, 2022
7a481ff
Properly abort when thread result panics on drop.
m-ou-se Mar 5, 2022
1c06eb7
Remove outdated comment.
m-ou-se Mar 9, 2022
b97d875
Add soundness test for dropping scoped thread results before joining.
m-ou-se Mar 9, 2022
e346920
Also take in account mdbook redirect in linkchecker
Urgau Mar 9, 2022
109cdc7
suggest enabling generic_const_exprs feature if const is unevaluatable
compiler-errors Mar 4, 2022
9d857d9
Make llvm-libunwind a per-target option
tmandry Feb 2, 2022
42624ba
Use in-tree libunwind by default on Fuchsia
tmandry Mar 10, 2022
321e159
Rollup merge of #93604 - tmandry:libunwind-fuchsia-default, r=Mark-Si…
m-ou-se Mar 10, 2022
20bae16
Rollup merge of #94440 - compiler-errors:issue-94282, r=lcnr
m-ou-se Mar 10, 2022
3a712c3
Rollup merge of #94587 - JKAnderson409:issue-90107-fix, r=scottmcm
m-ou-se Mar 10, 2022
ca36078
Rollup merge of #94644 - m-ou-se:scoped-threads-drop-soundness, r=jos…
m-ou-se Mar 10, 2022
62e9d9a
Rollup merge of #94719 - jonhoo:enable-static-lld, r=Mark-Simulacrum
m-ou-se Mar 10, 2022
06e4633
Rollup merge of #94740 - GuillaumeGomez:unify-impl-blocks, r=notriddle
m-ou-se Mar 10, 2022
8a2cf58
Rollup merge of #94753 - Urgau:rustdoc-book-improvements, r=Guillaume…
m-ou-se Mar 10, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 63 additions & 25 deletions compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,34 +35,14 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
span: Span,
) -> Result<(), NotConstEvaluatable> {
debug!("is_const_evaluatable({:?})", uv);
if infcx.tcx.features().generic_const_exprs {
let tcx = infcx.tcx;
let tcx = infcx.tcx;

if tcx.features().generic_const_exprs {
match AbstractConst::new(tcx, uv)? {
// We are looking at a generic abstract constant.
Some(ct) => {
for pred in param_env.caller_bounds() {
match pred.kind().skip_binder() {
ty::PredicateKind::ConstEvaluatable(uv) => {
if let Some(b_ct) = AbstractConst::new(tcx, uv)? {
// Try to unify with each subtree in the AbstractConst to allow for
// `N + 1` being const evaluatable even if theres only a `ConstEvaluatable`
// predicate for `(N + 1) * 2`
let result =
walk_abstract_const(tcx, b_ct, |b_ct| {
match try_unify(tcx, ct, b_ct) {
true => ControlFlow::BREAK,
false => ControlFlow::CONTINUE,
}
});

if let ControlFlow::Break(()) = result {
debug!("is_const_evaluatable: abstract_const ~~> ok");
return Ok(());
}
}
}
_ => {} // don't care
}
if satisfied_from_param_env(tcx, ct, param_env)? {
return Ok(());
}

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

// If we're evaluating a foreign constant, under a nightly compiler without generic
// const exprs, AND it would've passed if that expression had been evaluated with
// generic const exprs, then suggest using generic const exprs.
if concrete.is_err()
&& tcx.sess.is_nightly_build()
&& !uv.def.did.is_local()
&& !tcx.features().generic_const_exprs
&& let Ok(Some(ct)) = AbstractConst::new(tcx, uv)
&& satisfied_from_param_env(tcx, ct, param_env) == Ok(true)
{
tcx.sess
.struct_span_fatal(
// Slightly better span than just using `span` alone
if span == rustc_span::DUMMY_SP { tcx.def_span(uv.def.did) } else { span },
"failed to evaluate generic const expression",
)
.note("the crate this constant originates from uses `#![feature(generic_const_exprs)]`")
.span_suggestion_verbose(
rustc_span::DUMMY_SP,
"consider enabling this feature",
"#![feature(generic_const_exprs)]\n".to_string(),
rustc_errors::Applicability::MaybeIncorrect,
)
.emit();
rustc_errors::FatalError.raise();
}

debug!(?concrete, "is_const_evaluatable");
match concrete {
Err(ErrorHandled::TooGeneric) => Err(match uv.has_infer_types_or_consts() {
Expand All @@ -178,6 +185,37 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
}
}

fn satisfied_from_param_env<'tcx>(
tcx: TyCtxt<'tcx>,
ct: AbstractConst<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> Result<bool, NotConstEvaluatable> {
for pred in param_env.caller_bounds() {
match pred.kind().skip_binder() {
ty::PredicateKind::ConstEvaluatable(uv) => {
if let Some(b_ct) = AbstractConst::new(tcx, uv)? {
// Try to unify with each subtree in the AbstractConst to allow for
// `N + 1` being const evaluatable even if theres only a `ConstEvaluatable`
// predicate for `(N + 1) * 2`
let result =
walk_abstract_const(tcx, b_ct, |b_ct| match try_unify(tcx, ct, b_ct) {
true => ControlFlow::BREAK,
false => ControlFlow::CONTINUE,
});

if let ControlFlow::Break(()) = result {
debug!("is_const_evaluatable: abstract_const ~~> ok");
return Ok(true);
}
}
}
_ => {} // don't care
}
}

Ok(false)
}

/// A tree representing an anonymous constant.
///
/// This is only able to represent a subset of `MIR`,
Expand Down
25 changes: 15 additions & 10 deletions config.toml.example
Original file line number Diff line number Diff line change
Expand Up @@ -599,16 +599,9 @@ changelog-seen = 2
# development of NLL
#test-compare-mode = false

# Use LLVM libunwind as the implementation for Rust's unwinder.
# Accepted values are 'in-tree' (formerly true), 'system' or 'no' (formerly false).
# This option only applies for Linux and Fuchsia targets.
# On Linux target, if crt-static is not enabled, 'no' means dynamic link to
# `libgcc_s.so`, 'in-tree' means static link to the in-tree build of llvm libunwind
# and 'system' means dynamic link to `libunwind.so`. If crt-static is enabled,
# the behavior is depend on the libc. On musl target, 'no' and 'in-tree' both
# means static link to the in-tree build of llvm libunwind, and 'system' means
# static link to `libunwind.a` provided by system. Due to the limitation of glibc,
# it must link to `libgcc_eh.a` to get a working output, and this option have no effect.
# Global default for llvm-libunwind for all targets. See the target-specific
# documentation for llvm-libunwind below. Note that the target-specific
# option will override this if set.
#llvm-libunwind = 'no'

# Enable Windows Control Flow Guard checks in the standard library.
Expand Down Expand Up @@ -665,6 +658,18 @@ changelog-seen = 2
# not, you can specify an explicit file name for it.
#llvm-filecheck = "/path/to/llvm-version/bin/FileCheck"

# Use LLVM libunwind as the implementation for Rust's unwinder.
# Accepted values are 'in-tree' (formerly true), 'system' or 'no' (formerly false).
# This option only applies for Linux and Fuchsia targets.
# On Linux target, if crt-static is not enabled, 'no' means dynamic link to
# `libgcc_s.so`, 'in-tree' means static link to the in-tree build of llvm libunwind
# and 'system' means dynamic link to `libunwind.so`. If crt-static is enabled,
# the behavior is depend on the libc. On musl target, 'no' and 'in-tree' both
# means static link to the in-tree build of llvm libunwind, and 'system' means
# static link to `libunwind.a` provided by system. Due to the limitation of glibc,
# it must link to `libgcc_eh.a` to get a working output, and this option have no effect.
#llvm-libunwind = 'no' if Linux, 'in-tree' if Fuchsia

# If this target is for Android, this option will be required to specify where
# the NDK for the target lives. This is used to find the C compiler to link and
# build native code.
Expand Down
19 changes: 16 additions & 3 deletions library/core/src/iter/traits/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
/// created from an iterator. This is common for types which describe a
/// collection of some kind.
///
/// [`FromIterator::from_iter()`] is rarely called explicitly, and is instead
/// used through [`Iterator::collect()`] method. See [`Iterator::collect()`]'s
/// documentation for more examples.
/// If you want to create a collection from the contents of an iterator, the
/// [`Iterator::collect()`] method is preferred. However, when you need to
/// specify the container type, [`FromIterator::from_iter()`] can be more
/// readable than using a turbofish (e.g. `::<Vec<_>>()`). See the
/// [`Iterator::collect()`] documentation for more examples of its use.
///
/// See also: [`IntoIterator`].
///
Expand All @@ -32,6 +34,17 @@
/// assert_eq!(v, vec![5, 5, 5, 5, 5]);
/// ```
///
/// Using [`FromIterator::from_iter()`] as a more readable alternative to
/// [`Iterator::collect()`]:
///
/// ```
/// use std::collections::VecDeque;
/// let first = (0..10).collect::<VecDeque<i32>>();
/// let second = VecDeque::from_iter(0..10);
///
/// assert_eq!(first, second);
/// ```
///
/// Implementing `FromIterator` for your type:
///
/// ```
Expand Down
10 changes: 5 additions & 5 deletions library/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,11 @@ extern crate std as realstd;
#[macro_use]
mod macros;

// The runtime entry point and a few unstable public functions used by the
// compiler
#[macro_use]
pub mod rt;

// The Rust prelude
pub mod prelude;

Expand Down Expand Up @@ -547,11 +552,6 @@ pub mod arch {
#[stable(feature = "simd_x86", since = "1.27.0")]
pub use std_detect::is_x86_feature_detected;

// The runtime entry point and a few unstable public functions used by the
// compiler
#[macro_use]
pub mod rt;

// Platform-abstraction modules
mod sys;
mod sys_common;
Expand Down
27 changes: 23 additions & 4 deletions library/std/src/thread/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1287,12 +1287,31 @@ unsafe impl<'scope, T: Sync> Sync for Packet<'scope, T> {}

impl<'scope, T> Drop for Packet<'scope, T> {
fn drop(&mut self) {
// If this packet was for a thread that ran in a scope, the thread
// panicked, and nobody consumed the panic payload, we make sure
// the scope function will panic.
let unhandled_panic = matches!(self.result.get_mut(), Some(Err(_)));
// Drop the result without causing unwinding.
// This is only relevant for threads that aren't join()ed, as
// join() will take the `result` and set it to None, such that
// there is nothing left to drop here.
// If this panics, we should handle that, because we're outside the
// outermost `catch_unwind` of our thread.
// We just abort in that case, since there's nothing else we can do.
// (And even if we tried to handle it somehow, we'd also need to handle
// the case where the panic payload we get out of it also panics on
// drop, and so on. See issue #86027.)
if let Err(_) = panic::catch_unwind(panic::AssertUnwindSafe(|| {
*self.result.get_mut() = None;
})) {
rtabort!("thread result panicked on drop");
}
// Book-keeping so the scope knows when it's done.
if let Some(scope) = self.scope {
// If this packet was for a thread that ran in a scope, the thread
// panicked, and nobody consumed the panic payload, we make sure
// the scope function will panic.
let unhandled_panic = matches!(self.result.get_mut(), Some(Err(_)));
// Now that there will be no more user code running on this thread
// that can use 'scope, mark the thread as 'finished'.
// It's important we only do this after the `result` has been dropped,
// since dropping it might still use things it borrowed from 'scope.
scope.decrement_num_running_threads(unhandled_panic);
}
}
Expand Down
27 changes: 24 additions & 3 deletions library/std/src/thread/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ use crate::mem;
use crate::panic::panic_any;
use crate::result;
use crate::sync::{
atomic::{AtomicBool, Ordering},
mpsc::{channel, Sender},
Arc, Barrier,
};
use crate::thread::{self, ThreadId};
use crate::thread::{self, Scope, ThreadId};
use crate::time::Duration;
use crate::time::Instant;

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

// NOTE: the corresponding test for stderr is in ui/thread-stderr, due
// to the test harness apparently interfering with stderr configuration.
#[test]
fn test_scoped_threads_drop_result_before_join() {
let actually_finished = &AtomicBool::new(false);
struct X<'scope, 'env>(&'scope Scope<'scope, 'env>, &'env AtomicBool);
impl Drop for X<'_, '_> {
fn drop(&mut self) {
thread::sleep(Duration::from_millis(20));
let actually_finished = self.1;
self.0.spawn(move || {
thread::sleep(Duration::from_millis(20));
actually_finished.store(true, Ordering::Relaxed);
});
}
}
thread::scope(|s| {
s.spawn(move || {
thread::sleep(Duration::from_millis(20));
X(s, actually_finished)
});
});
assert!(actually_finished.load(Ordering::Relaxed));
}
2 changes: 1 addition & 1 deletion src/bootstrap/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ fn copy_third_party_objects(
}

if target == "x86_64-fortanix-unknown-sgx"
|| builder.config.llvm_libunwind == LlvmLibunwind::InTree
|| builder.config.llvm_libunwind(target) == LlvmLibunwind::InTree
&& (target.contains("linux") || target.contains("fuchsia"))
{
let libunwind_path =
Expand Down
27 changes: 22 additions & 5 deletions src/bootstrap/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ pub struct Config {
pub rustc_error_format: Option<String>,
pub json_output: bool,
pub test_compare_mode: bool,
pub llvm_libunwind: LlvmLibunwind,
pub color: Color,

pub on_fail: Option<String>,
Expand Down Expand Up @@ -145,6 +144,7 @@ pub struct Config {
pub rust_profile_generate: Option<String>,
pub llvm_profile_use: Option<String>,
pub llvm_profile_generate: bool,
pub llvm_libunwind_default: Option<LlvmLibunwind>,

pub build: TargetSelection,
pub hosts: Vec<TargetSelection>,
Expand Down Expand Up @@ -289,6 +289,7 @@ pub struct Target {
pub llvm_config: Option<PathBuf>,
/// Some(path to FileCheck) if one was specified.
pub llvm_filecheck: Option<PathBuf>,
pub llvm_libunwind: Option<LlvmLibunwind>,
pub cc: Option<PathBuf>,
pub cxx: Option<PathBuf>,
pub ar: Option<PathBuf>,
Expand Down Expand Up @@ -573,6 +574,7 @@ derive_merge! {
linker: Option<String>,
llvm_config: Option<String>,
llvm_filecheck: Option<String>,
llvm_libunwind: Option<String>,
android_ndk: Option<String>,
sanitizers: Option<bool>,
profiler: Option<bool>,
Expand Down Expand Up @@ -925,10 +927,6 @@ impl Config {
set(&mut config.rust_rpath, rust.rpath);
set(&mut config.jemalloc, rust.jemalloc);
set(&mut config.test_compare_mode, rust.test_compare_mode);
config.llvm_libunwind = rust
.llvm_libunwind
.map(|v| v.parse().expect("failed to parse rust.llvm-libunwind"))
.unwrap_or_default();
set(&mut config.backtrace, rust.backtrace);
set(&mut config.channel, rust.channel);
config.description = rust.description;
Expand All @@ -951,6 +949,9 @@ impl Config {
config.rust_thin_lto_import_instr_limit = rust.thin_lto_import_instr_limit;
set(&mut config.rust_remap_debuginfo, rust.remap_debuginfo);
set(&mut config.control_flow_guard, rust.control_flow_guard);
config.llvm_libunwind_default = rust
.llvm_libunwind
.map(|v| v.parse().expect("failed to parse rust.llvm-libunwind"));

if let Some(ref backends) = rust.codegen_backends {
config.rust_codegen_backends =
Expand All @@ -977,6 +978,10 @@ impl Config {
if let Some(ref s) = cfg.llvm_filecheck {
target.llvm_filecheck = Some(config.src.join(s));
}
target.llvm_libunwind = cfg
.llvm_libunwind
.as_ref()
.map(|v| v.parse().expect("failed to parse rust.llvm-libunwind"));
if let Some(ref s) = cfg.android_ndk {
target.ndk = Some(config.src.join(s));
}
Expand Down Expand Up @@ -1174,6 +1179,18 @@ impl Config {
self.rust_codegen_backends.contains(&INTERNER.intern_str("llvm"))
}

pub fn llvm_libunwind(&self, target: TargetSelection) -> LlvmLibunwind {
self.target_config
.get(&target)
.and_then(|t| t.llvm_libunwind)
.or(self.llvm_libunwind_default)
.unwrap_or(if target.contains("fuchsia") {
LlvmLibunwind::InTree
} else {
LlvmLibunwind::No
})
}

pub fn submodules(&self, rust_info: &GitInfo) -> bool {
self.submodules.unwrap_or(rust_info.is_git())
}
Expand Down
2 changes: 1 addition & 1 deletion src/bootstrap/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,7 @@ impl Build {
fn std_features(&self, target: TargetSelection) -> String {
let mut features = "panic-unwind".to_string();

match self.config.llvm_libunwind {
match self.config.llvm_libunwind(target) {
LlvmLibunwind::InTree => features.push_str(" llvm-libunwind"),
LlvmLibunwind::System => features.push_str(" system-llvm-libunwind"),
LlvmLibunwind::No => {}
Expand Down
Loading