diff --git a/README.md b/README.md index 78edac9d12c13..26613314a15bc 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ by running it with the `--help` flag or reading the [rustc dev guide][rustcguide If you plan to use `x.py install` to create an installation, it is recommended that you set the `prefix` value in the `[install]` section to a directory. - Create install directory if you are not installing in default directory + Create install directory if you are not installing in default directory. 4. Build and install: diff --git a/RELEASES.md b/RELEASES.md index 0e118fb939ff0..3d88891ad215c 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,128 @@ +Version 1.62.0 (2022-06-30) +========================== + +Language +-------- + +- [Stabilize `#[derive(Default)]` on enums with a `#[default]` variant][94457] +- [Stop validating some checks in dead code after functions with uninhabited return types][93313] +- [Fix constants not getting dropped if part of a diverging expression][94775] +- [Support unit struct/enum variant in destructuring assignment][95380] +- [Remove mutable_borrow_reservation_conflict lint and allow the code pattern][96268] + +Compiler +-------- + +- [linker: Stop using whole-archive on dependencies of dylibs][96436] +- [Make `unaligned_references` lint deny-by-default][95372] + This lint is also a future compatibility lint, and is expected to eventually + become a hard error. +- [Only add codegen backend to dep info if -Zbinary-dep-depinfo is used][93969] +- [Reject `#[thread_local]` attribute on non-static items][95006] +- [Add tier 3 `aarch64-pc-windows-gnullvm` and `x86_64-pc-windows-gnullvm` targets\*][94872] +- [Implement a lint to warn about unused macro rules][96150] +- [Promote `x86_64-unknown-none` target to Tier 2\*][95705] + +\* Refer to Rust's [platform support page][platform-support-doc] for more + information on Rust's tiered platform support. + +Libraries +--------- + +- [Move `CStr` to libcore, and `CString` to liballoc][94079] +- [Windows: Use a pipe relay for chaining pipes][95841] +- [Replace Linux Mutex and Condvar with futex based ones.][95035] +- [Replace RwLock by a futex based one on Linux][95801] +- [std: directly use pthread in UNIX parker implementation][96393] + +Stabilized APIs +--------------- + +- [`bool::then_some`] +- [`f32::total_cmp`] +- [`f64::total_cmp`] +- [`Stdin::lines`] +- [`windows::CommandExt::raw_arg`] +- [`impl Default for AssertUnwindSafe`] +- [`From> for Rc<[u8]>`][rc-u8-from-str] +- [`From> for Arc<[u8]>`][arc-u8-from-str] +- [`FusedIterator for EncodeWide`] +- [RDM intrinsics on aarch64][stdarch/1285] + +Clippy +------ + +- [Create clippy lint against unexpectedly late drop for temporaries in match scrutinee expressions][94206] + +Cargo +----- + +- Added the `cargo add` command for adding dependencies to `Cargo.toml` from + the command-line. + [docs](https://doc.rust-lang.org/nightly/cargo/commands/cargo-add.html) +- Package ID specs now support `name@version` syntax in addition to the + previous `name:version` to align with the behavior in `cargo add` and other + tools. `cargo install` and `cargo yank` also now support this syntax so the + version does not need to passed as a separate flag. +- The `git` and `registry` directories in Cargo's home directory (usually + `~/.cargo`) are now marked as cache directories so that they are not + included in backups or content indexing (on Windows). +- Added automatic `@` argfile support, which will use "response files" if the + command-line to `rustc` exceeds the operating system's limit. + +Compatibility Notes +------------------- + +- `cargo test` now passes `--target` to `rustdoc` if the specified target is + the same as the host target. + [#10594](https://github.com/rust-lang/cargo/pull/10594) +- [rustdoc: Remove .woff font files][96279] +- [Enforce Copy bounds for repeat elements while considering lifetimes][95819] + +Internal Changes +---------------- + +- [Unify ReentrantMutex implementations across all platforms][96042] + +These changes provide no direct user facing benefits, but represent significant +improvements to the internals and overall performance of rustc +and related tools. + +[93313]: https://github.com/rust-lang/rust/pull/93313/ +[93969]: https://github.com/rust-lang/rust/pull/93969/ +[94079]: https://github.com/rust-lang/rust/pull/94079/ +[94206]: https://github.com/rust-lang/rust/pull/94206/ +[94457]: https://github.com/rust-lang/rust/pull/94457/ +[94775]: https://github.com/rust-lang/rust/pull/94775/ +[94872]: https://github.com/rust-lang/rust/pull/94872/ +[95006]: https://github.com/rust-lang/rust/pull/95006/ +[95035]: https://github.com/rust-lang/rust/pull/95035/ +[95372]: https://github.com/rust-lang/rust/pull/95372/ +[95380]: https://github.com/rust-lang/rust/pull/95380/ +[95431]: https://github.com/rust-lang/rust/pull/95431/ +[95705]: https://github.com/rust-lang/rust/pull/95705/ +[95801]: https://github.com/rust-lang/rust/pull/95801/ +[95819]: https://github.com/rust-lang/rust/pull/95819/ +[95841]: https://github.com/rust-lang/rust/pull/95841/ +[96042]: https://github.com/rust-lang/rust/pull/96042/ +[96150]: https://github.com/rust-lang/rust/pull/96150/ +[96268]: https://github.com/rust-lang/rust/pull/96268/ +[96279]: https://github.com/rust-lang/rust/pull/96279/ +[96393]: https://github.com/rust-lang/rust/pull/96393/ +[96436]: https://github.com/rust-lang/rust/pull/96436/ +[96557]: https://github.com/rust-lang/rust/pull/96557/ + +[`bool::then_some`]: https://doc.rust-lang.org/stable/std/primitive.bool.html#method.then_some +[`f32::total_cmp`]: https://doc.rust-lang.org/stable/std/primitive.f32.html#method.total_cmp +[`f64::total_cmp`]: https://doc.rust-lang.org/stable/std/primitive.f64.html#method.total_cmp +[`Stdin::lines`]: https://doc.rust-lang.org/stable/std/io/struct.Stdin.html#method.lines +[`impl Default for AssertUnwindSafe`]: https://doc.rust-lang.org/stable/std/panic/struct.AssertUnwindSafe.html#impl-Default +[rc-u8-from-str]: https://doc.rust-lang.org/stable/std/rc/struct.Rc.html#impl-From%3CRc%3Cstr%3E%3E +[arc-u8-from-str]: https://doc.rust-lang.org/stable/std/sync/struct.Arc.html#impl-From%3CArc%3Cstr%3E%3E +[stdarch/1285]: https://github.com/rust-lang/stdarch/pull/1285 +[`windows::CommandExt::raw_arg`]: https://doc.rust-lang.org/stable/std/os/windows/process/trait.CommandExt.html#tymethod.raw_arg +[`FusedIterator for EncodeWide`]: https://doc.rust-lang.org/stable/std/os/windows/ffi/struct.EncodeWide.html#impl-FusedIterator + Version 1.61.0 (2022-05-19) ========================== diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 0d072046d58ff..390a44d3f337d 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -11,7 +11,6 @@ #![feature(associated_type_bounds)] #![feature(auto_traits)] #![feature(control_flow_enum)] -#![feature(core_intrinsics)] #![feature(extend_one)] #![feature(let_else)] #![feature(hash_raw_entry)] @@ -44,26 +43,6 @@ pub fn cold_path R, R>(f: F) -> R { f() } -#[macro_export] -macro_rules! likely { - ($e:expr) => { - match $e { - #[allow(unused_unsafe)] - e => unsafe { std::intrinsics::likely(e) }, - } - }; -} - -#[macro_export] -macro_rules! unlikely { - ($e:expr) => { - match $e { - #[allow(unused_unsafe)] - e => unsafe { std::intrinsics::unlikely(e) }, - } - }; -} - pub mod base_n; pub mod binary_search_util; pub mod captures; diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs index a1f42d8d3c059..88ff33b4d09a1 100644 --- a/compiler/rustc_data_structures/src/profiling.rs +++ b/compiler/rustc_data_structures/src/profiling.rs @@ -195,6 +195,7 @@ impl SelfProfilerRef { F: for<'a> FnOnce(&'a SelfProfiler) -> TimingGuard<'a>, { #[inline(never)] + #[cold] fn cold_call(profiler_ref: &SelfProfilerRef, f: F) -> TimingGuard<'_> where F: for<'a> FnOnce(&'a SelfProfiler) -> TimingGuard<'a>, @@ -203,7 +204,7 @@ impl SelfProfilerRef { f(&**profiler) } - if unlikely!(self.event_filter_mask.contains(event_filter)) { + if self.event_filter_mask.contains(event_filter) { cold_call(self, f) } else { TimingGuard::none() diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 80f6abbab3447..7684d861f3c93 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -5,7 +5,7 @@ use hir::{HirId, OpaqueTyOrigin}; use rustc_data_structures::sync::Lrc; use rustc_data_structures::vec_map::VecMap; use rustc_hir as hir; -use rustc_middle::traits::ObligationCause; +use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::subst::{GenericArgKind, Subst}; use rustc_middle::ty::{ @@ -46,6 +46,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { value: T, body_id: HirId, span: Span, + code: ObligationCauseCode<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> InferOk<'tcx, T> { if !value.has_opaque_types() { @@ -68,10 +69,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ) => { let span = if span.is_dummy() { self.tcx.def_span(def_id) } else { span }; - let cause = ObligationCause::misc(span, body_id); + let cause = ObligationCause::new(span, body_id, code.clone()); + // FIXME(compiler-errors): We probably should add a new TypeVariableOriginKind + // for opaque types, and then use that kind to fix the spans for type errors + // that we see later on. let ty_var = self.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, - span: cause.span, + span, }); obligations.extend( self.handle_opaque_type(ty, ty_var, true, &cause, param_env) diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 912b09eeca861..5258d37a14c91 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -387,6 +387,9 @@ pub enum ObligationCauseCode<'tcx> { /// Return type of this function ReturnType, + /// Opaque return type of this function + OpaqueReturnType(Option<(Ty<'tcx>, Span)>), + /// Block implicit return BlockTailExpression(hir::HirId), diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 9c1972e81e19e..00403ff044c40 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -804,7 +804,7 @@ pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>; impl<'tcx> TraitPredicate<'tcx> { pub fn remap_constness(&mut self, tcx: TyCtxt<'tcx>, param_env: &mut ParamEnv<'tcx>) { - if unlikely!(Some(self.trait_ref.def_id) == tcx.lang_items().drop_trait()) { + if std::intrinsics::unlikely(Some(self.trait_ref.def_id) == tcx.lang_items().drop_trait()) { // remap without changing constness of this predicate. // this is because `T: ~const Drop` has a different meaning to `T: Drop` // FIXME(fee1-dead): remove this logic after beta bump diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 5a32d7075db06..341cf8f827bc9 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -750,7 +750,7 @@ impl DepGraph { dep_node ); - if unlikely!(!side_effects.is_empty()) { + if !side_effects.is_empty() { self.emit_side_effects(tcx, data, dep_node_index, side_effects); } diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 3498df95196e5..3e4c7ad9f8f41 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -316,7 +316,7 @@ where OnHit: FnOnce(&C::Stored) -> R, { cache.lookup(&key, |value, index| { - if unlikely!(tcx.profiler().enabled()) { + if std::intrinsics::unlikely(tcx.profiler().enabled()) { tcx.profiler().query_cache_hit(index.into()); } tcx.dep_graph().read_index(index); @@ -354,7 +354,7 @@ where .lookup(&key, |value, index| (value.clone(), index)) .unwrap_or_else(|_| panic!("value must be in cache after waiting")); - if unlikely!(tcx.dep_context().profiler().enabled()) { + if std::intrinsics::unlikely(tcx.dep_context().profiler().enabled()) { tcx.dep_context().profiler().query_cache_hit(index.into()); } query_blocked_prof_timer.finish_with_query_invocation_id(index.into()); @@ -422,7 +422,7 @@ where let diagnostics = diagnostics.into_inner(); let side_effects = QuerySideEffects { diagnostics }; - if unlikely!(!side_effects.is_empty()) { + if std::intrinsics::unlikely(!side_effects.is_empty()) { if query.anon { tcx.store_side_effects_for_anon_node(dep_node_index, side_effects); } else { @@ -466,7 +466,9 @@ where prof_timer.finish_with_query_invocation_id(dep_node_index.into()); if let Some(result) = result { - if unlikely!(tcx.dep_context().sess().opts.debugging_opts.query_dep_graph) { + if std::intrinsics::unlikely( + tcx.dep_context().sess().opts.debugging_opts.query_dep_graph, + ) { dep_graph.mark_debug_loaded_from_disk(*dep_node) } @@ -483,8 +485,8 @@ where // currently afford to verify every hash. This subset should still // give us some coverage of potential bugs though. let try_verify = prev_fingerprint.as_value().1 % 32 == 0; - if unlikely!( - try_verify || tcx.dep_context().sess().opts.debugging_opts.incremental_verify_ich + if std::intrinsics::unlikely( + try_verify || tcx.dep_context().sess().opts.debugging_opts.incremental_verify_ich, ) { incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query); } @@ -723,7 +725,7 @@ where // Ensure that only one of them runs the query. let cache = Q::query_cache(tcx); let cached = cache.lookup(&key, |_, index| { - if unlikely!(tcx.dep_context().profiler().enabled()) { + if std::intrinsics::unlikely(tcx.dep_context().profiler().enabled()) { tcx.dep_context().profiler().query_cache_hit(index.into()); } }); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index d8003efba872d..0485cac9e9f74 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2661,6 +2661,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { err.help("add `#![feature(trivial_bounds)]` to the crate attributes to enable"); } } + ObligationCauseCode::OpaqueReturnType(expr_info) => { + if let Some((expr_ty, expr_span)) = expr_info { + let expr_ty = self.resolve_vars_if_possible(expr_ty); + err.span_label( + expr_span, + format!("return type was inferred to be `{expr_ty}` here"), + ); + } + } } } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index a72f90746edfa..82c54291a5d5e 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -28,6 +28,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_infer::infer::resolve::OpportunisticRegionResolver; +use rustc_infer::traits::ObligationCauseCode; use rustc_middle::traits::select::OverflowError; use rustc_middle::ty::fold::{MaxUniverse, TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::subst::Subst; @@ -261,6 +262,7 @@ fn project_and_unify_type<'cx, 'tcx>( actual, obligation.cause.body_id, obligation.cause.span, + ObligationCauseCode::MiscObligation, obligation.param_env, ); obligations.extend(new); diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 0425e7b074fcf..45c011b78e388 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -101,8 +101,13 @@ pub(super) fn check_fn<'a, 'tcx>( declared_ret_ty, body.value.hir_id, DUMMY_SP, + traits::ObligationCauseCode::OpaqueReturnType(None), param_env, )); + // If we replaced declared_ret_ty with infer vars, then we must be infering + // an opaque type, so set a flag so we can improve diagnostics. + fcx.return_type_has_opaque = ret_ty != declared_ret_ty; + fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(ret_ty))); fcx.ret_type_span = Some(decl.output.span()); diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs index 05b22e174b845..cce1130511944 100644 --- a/compiler/rustc_typeck/src/check/closure.rs +++ b/compiler/rustc_typeck/src/check/closure.rs @@ -10,6 +10,7 @@ use rustc_hir::lang_items::LangItem; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_infer::infer::{InferOk, InferResult}; +use rustc_infer::traits::ObligationCauseCode; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::{self, Ty}; @@ -645,8 +646,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } fn hide_parent_opaque_types(&self, ty: Ty<'tcx>, span: Span, body_id: hir::HirId) -> Ty<'tcx> { - let InferOk { value, obligations } = - self.replace_opaque_types_with_inference_vars(ty, body_id, span, self.param_env); + let InferOk { value, obligations } = self.replace_opaque_types_with_inference_vars( + ty, + body_id, + span, + ObligationCauseCode::MiscObligation, + self.param_env, + ); self.register_predicates(obligations); value } diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 37d12b4ed5da4..77d6495f38c2f 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -39,6 +39,7 @@ use rustc_hir::{ExprKind, HirId, QPath}; use rustc_infer::infer; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::InferOk; +use rustc_infer::traits::ObligationCause; use rustc_middle::middle::stability; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase}; use rustc_middle::ty::error::TypeError::FieldMisMatch; @@ -839,6 +840,37 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return_expr, return_expr_ty, ); + + if self.return_type_has_opaque { + // Point any obligations that were registered due to opaque type + // inference at the return expression. + self.select_obligations_where_possible(false, |errors| { + self.point_at_return_for_opaque_ty_error(errors, span, return_expr_ty); + }); + } + } + + fn point_at_return_for_opaque_ty_error( + &self, + errors: &mut Vec>, + span: Span, + return_expr_ty: Ty<'tcx>, + ) { + // Don't point at the whole block if it's empty + if span == self.tcx.hir().span(self.body_id) { + return; + } + for err in errors { + let cause = &mut err.obligation.cause; + if let ObligationCauseCode::OpaqueReturnType(None) = cause.code() { + let new_cause = ObligationCause::new( + cause.span, + cause.body_id, + ObligationCauseCode::OpaqueReturnType(Some((return_expr_ty, span))), + ); + *cause = new_cause; + } + } } pub(crate) fn check_lhs_assignable( diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs index fa2416d56de14..8b680a3d042da 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs @@ -115,6 +115,9 @@ pub struct FnCtxt<'a, 'tcx> { /// either given explicitly or inferred from, say, an `Fn*` trait /// bound. Used for diagnostic purposes only. pub(super) return_type_pre_known: bool, + + /// True if the return type has an Opaque type + pub(super) return_type_has_opaque: bool, } impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -141,6 +144,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }), inh, return_type_pre_known: true, + return_type_has_opaque: false, } } diff --git a/library/alloc/src/collections/btree/node/tests.rs b/library/alloc/src/collections/btree/node/tests.rs index c8634e6c06fe3..aadb0dc9c40d9 100644 --- a/library/alloc/src/collections/btree/node/tests.rs +++ b/library/alloc/src/collections/btree/node/tests.rs @@ -68,10 +68,10 @@ fn test_splitpoint() { #[test] fn test_partial_eq() { - let mut root1 = NodeRef::new_leaf(&Global); + let mut root1 = NodeRef::new_leaf(Global); root1.borrow_mut().push(1, ()); - let mut root1 = NodeRef::new_internal(root1.forget_type(), &Global).forget_type(); - let root2 = Root::new(&Global); + let mut root1 = NodeRef::new_internal(root1.forget_type(), Global).forget_type(); + let root2 = Root::new(Global); root1.reborrow().assert_back_pointers(); root2.reborrow().assert_back_pointers(); @@ -87,9 +87,9 @@ fn test_partial_eq() { assert!(top_edge_1 == top_edge_1); assert!(top_edge_1 != top_edge_2); - root1.pop_internal_level(&Global); - unsafe { root1.into_dying().deallocate_and_ascend(&Global) }; - unsafe { root2.into_dying().deallocate_and_ascend(&Global) }; + root1.pop_internal_level(Global); + unsafe { root1.into_dying().deallocate_and_ascend(Global) }; + unsafe { root2.into_dying().deallocate_and_ascend(Global) }; } #[test] diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index cedeb27d6d95a..a66ecc35bbdb1 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -4,6 +4,12 @@ //! threads, and are the building blocks of other concurrent //! types. //! +//! Rust atomics currently follow the same rules as [C++20 atomics][cpp], specifically `atomic_ref`. +//! Basically, creating a *shared reference* to one of the Rust atomic types corresponds to creating +//! an `atomic_ref` in C++; the `atomic_ref` is destroyed when the lifetime of the shared reference +//! ends. (A Rust atomic type that is exclusively owned or behind a mutable reference does *not* +//! correspond to an "atomic object" in C++, since it can be accessed via non-atomic operations.) +//! //! This module defines atomic versions of a select number of primitive //! types, including [`AtomicBool`], [`AtomicIsize`], [`AtomicUsize`], //! [`AtomicI8`], [`AtomicU16`], etc. @@ -14,6 +20,7 @@ //! the memory barrier for that operation. These orderings are the //! same as the [C++20 atomic orderings][1]. For more information see the [nomicon][2]. //! +//! [cpp]: https://en.cppreference.com/w/cpp/atomic //! [1]: https://en.cppreference.com/w/cpp/atomic/memory_order //! [2]: ../../../nomicon/atomics.html //! diff --git a/library/std/src/sys/unix/futex.rs b/library/std/src/sys/unix/futex.rs index 8d05cb44b9479..ab516a7f76dd0 100644 --- a/library/std/src/sys/unix/futex.rs +++ b/library/std/src/sys/unix/futex.rs @@ -5,6 +5,7 @@ target_os = "freebsd", target_os = "openbsd", target_os = "dragonfly", + target_os = "fuchsia", ))] use crate::sync::atomic::AtomicU32; @@ -237,3 +238,52 @@ pub fn futex_wake(futex: &AtomicU32) -> bool { pub fn futex_wake_all(futex: &AtomicU32) { unsafe { emscripten_futex_wake(futex, i32::MAX) }; } + +#[cfg(target_os = "fuchsia")] +mod zircon { + type zx_time_t = i64; + type zx_futex_t = crate::sync::atomic::AtomicU32; + type zx_handle_t = u32; + type zx_status_t = i32; + + pub const ZX_HANDLE_INVALID: zx_handle_t = 0; + pub const ZX_ERR_TIMED_OUT: zx_status_t = -21; + pub const ZX_TIME_INFINITE: zx_time_t = zx_time_t::MAX; + + extern "C" { + pub fn zx_futex_wait( + value_ptr: *const zx_futex_t, + current_value: zx_futex_t, + new_futex_owner: zx_handle_t, + deadline: zx_time_t, + ) -> zx_status_t; + pub fn zx_futex_wake(value_ptr: *const zx_futex_t, wake_count: u32) -> zx_status_t; + pub fn zx_clock_get_monotonic() -> zx_time_t; + } +} + +#[cfg(target_os = "fuchsia")] +pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option) -> bool { + use crate::convert::TryFrom; + + // Sleep forever if the timeout is longer than fits in a i64. + let deadline = timeout + .and_then(|d| { + i64::try_from(d.as_nanos()) + .ok()? + .checked_add(unsafe { zircon::zx_clock_get_monotonic() }) + }) + .unwrap_or(zircon::ZX_TIME_INFINITE); + + unsafe { + zircon::zx_futex_wait(futex, AtomicU32::new(expected), zircon::ZX_HANDLE_INVALID, deadline) + != zircon::ZX_ERR_TIMED_OUT + } +} + +// Fuchsia doesn't tell us how many threads are woken up, so this always returns false. +#[cfg(target_os = "fuchsia")] +pub fn futex_wake(futex: &AtomicU32) -> bool { + unsafe { zircon::zx_futex_wake(futex, 1) }; + false +} diff --git a/library/std/src/sys/unix/thread_parker.rs b/library/std/src/sys/unix/thread_parker.rs index 76278ae30f1af..9f4d4f7e736e8 100644 --- a/library/std/src/sys/unix/thread_parker.rs +++ b/library/std/src/sys/unix/thread_parker.rs @@ -7,6 +7,7 @@ target_os = "freebsd", target_os = "openbsd", target_os = "dragonfly", + target_os = "fuchsia", )))] use crate::cell::UnsafeCell; diff --git a/library/std/src/sys_common/thread_parker/mod.rs b/library/std/src/sys_common/thread_parker/mod.rs index c789a388e05ad..7e8bfb2565e45 100644 --- a/library/std/src/sys_common/thread_parker/mod.rs +++ b/library/std/src/sys_common/thread_parker/mod.rs @@ -6,6 +6,7 @@ cfg_if::cfg_if! { target_os = "freebsd", target_os = "openbsd", target_os = "dragonfly", + target_os = "fuchsia", ))] { mod futex; pub use futex::Parker; diff --git a/src/doc/unstable-book/src/compiler-flags/extern-options.md b/src/doc/unstable-book/src/compiler-flags/extern-options.md new file mode 100644 index 0000000000000..858eee5d2c283 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/extern-options.md @@ -0,0 +1,22 @@ +# `--extern` Options + +The behavior of the `--extern` flag can be modified with `noprelude`, `priv` or `nounused` options. + +This is unstable feature, so you have to provide `-Zunstable-options` to enable it. + +## Examples + +Use your own build of the `core` crate. + +`rustc main.rs -Z unstable-options --extern noprelude:core=libcore.rlib` + +To use multiple options, separate them with a comma: + +`rustc main.rs -Z unstable-options --extern noprelude,priv,nounused:mydep=mydep.rlib` + +## Options + +* `noprelude`: Do not add the crate to the external prelude. If used, it will need to be imported using `extern crate`. + This is used by the [build-std project](https://github.com/rust-lang/wg-cargo-std-aware/) to simulate compatibility with sysroot-only crates. +* `priv`: Mark the crate as a private dependency for the [`exported_private_dependencies`](../../rustc/lints/listing/warn-by-default.html#exported-private-dependencies) lint. +* `nounused`: Suppress [`unused-crate-dependencies`](../../rustc/lints/listing/allowed-by-default.html#unused-crate-dependencies) warnings for the crate. diff --git a/src/etc/cpu-usage-over-time-plot.sh b/src/etc/cpu-usage-over-time-plot.sh index 0905789079a3e..1c34255919434 100755 --- a/src/etc/cpu-usage-over-time-plot.sh +++ b/src/etc/cpu-usage-over-time-plot.sh @@ -7,13 +7,21 @@ # commit SHA of the build you're interested in, and the second is the name of # the builder. For example: # -# ./src/etc/cpu-usage-over-time-plot.sh e699ea096fcc2fc9ce8e8bcf884e11496a31cc9f i686-mingw-1 +# ./src/etc/cpu-usage-over-time-plot.sh 7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c x86_64-gnu # # That will generate `$builder.png` in the current directory which you can open # up to see a hopefully pretty graph. # # Improvements to this script are greatly appreciated! +if [[ $# != 2 ]]; then + echo "expected 2 arguments, recieved $#" + echo "example usage: './src/etc/cpu-usage-over-time-plot.sh \ +7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c \ +x86_64-gnu'" + exit 1 +fi + set -ex bucket=rust-lang-ci2 @@ -30,7 +38,7 @@ set ylabel "CPU Usage %" set xlabel "Time" set datafile sep ',' set term png size 3000,1000 -set output "$builder.png" +set output "$builder-$commit-cpu-usage-plot.png" set grid f(x) = mean_y @@ -43,7 +51,9 @@ set ytics 10 set boxwidth 0.5 plot \\ - mean_y with lines linetype 1 linecolor rgb "#ff0000" title "average", \\ - "cpu-$builder.csv" using 1:(100-\$2) with points pointtype 7 pointsize 0.4 title "$builder", \\ - "" using 1:(100-\$2) smooth bezier linewidth 3 title "bezier" + mean_y with lines linetype 1 linecolor rgb "#ff0000" title "average", "cpu-$builder.csv" \\ + using 1:(100-\$2) with points pointtype 7 pointsize 0.4 title "$builder", "" \\ + using 1:(100-\$2) smooth bezier linewidth 3 title "bezier" EOF + +rm "cpu-$builder.csv" diff --git a/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr b/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr index bd8c8a4414c4d..fbd76a64c1e92 100644 --- a/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr +++ b/src/test/ui/associated-types/impl-trait-return-missing-constraint.stderr @@ -6,6 +6,9 @@ LL | fn bar() -> impl Bar { ... LL | fn baz() -> impl Bar { | ^^^^^^^^^^^^^^^^^^^^ expected associated type, found `i32` +LL | +LL | bar() + | ----- return type was inferred to be `impl Bar` here | = note: expected associated type `::Item` found type `i32` diff --git a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr index cbe4a4ac0d659..cbc7b93f3a925 100644 --- a/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr +++ b/src/test/ui/const-generics/defaults/rp_impl_trait_fail.stderr @@ -3,6 +3,9 @@ error[E0277]: the trait bound `Uwu<10_u32, 12_u32>: Trait` is not satisfied | LL | fn rawr() -> impl Trait { | ^^^^^^^^^^ the trait `Trait` is not implemented for `Uwu<10_u32, 12_u32>` +LL | +LL | Uwu::<10, 12> + | ------------- return type was inferred to be `Uwu<10_u32, 12_u32>` here | = help: the trait `Trait` is implemented for `Uwu` @@ -11,6 +14,9 @@ error[E0277]: the trait bound `u32: Traitor` is not satisfied | LL | fn uwu() -> impl Traitor { | ^^^^^^^^^^^^^^^ the trait `Traitor` is not implemented for `u32` +LL | +LL | 1_u32 + | ----- return type was inferred to be `u32` here | = help: the following other types implement trait `Traitor`: > @@ -21,6 +27,9 @@ error[E0277]: the trait bound `u64: Traitor` is not satisfied | LL | fn owo() -> impl Traitor { | ^^^^^^^^^^^^ the trait `Traitor` is not implemented for `u64` +LL | +LL | 1_u64 + | ----- return type was inferred to be `u64` here | = help: the following other types implement trait `Traitor`: > diff --git a/src/test/ui/impl-trait/bound-normalization-fail.stderr b/src/test/ui/impl-trait/bound-normalization-fail.stderr index eac7e6b315ec4..bd8d3d3d24ece 100644 --- a/src/test/ui/impl-trait/bound-normalization-fail.stderr +++ b/src/test/ui/impl-trait/bound-normalization-fail.stderr @@ -3,6 +3,9 @@ error[E0271]: type mismatch resolving ` as FooLike>::Output == () -> impl FooLike { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving ` as FooLike>::Output == ::Assoc` +LL | +LL | Foo(()) + | ------- return type was inferred to be `Foo<()>` here | note: expected this to be `()` --> $DIR/bound-normalization-fail.rs:14:19 @@ -27,6 +30,9 @@ error[E0271]: type mismatch resolving ` as FooLike>::Output == >() -> impl FooLike { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving ` as FooLike>::Output == >::Assoc` +... +LL | Foo(()) + | ------- return type was inferred to be `Foo<()>` here | note: expected this to be `()` --> $DIR/bound-normalization-fail.rs:14:19 diff --git a/src/test/ui/issues-71798.stderr b/src/test/ui/issues-71798.stderr index ab72c3e41af97..829d0a02ec90b 100644 --- a/src/test/ui/issues-71798.stderr +++ b/src/test/ui/issues-71798.stderr @@ -9,6 +9,9 @@ error[E0277]: `u32` is not a future | LL | fn test_ref(x: &u32) -> impl std::future::Future + '_ { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `u32` is not a future +LL | +LL | *x + | -- return type was inferred to be `u32` here | = help: the trait `Future` is not implemented for `u32` = note: u32 must be a future or must implement `IntoFuture` to be awaited diff --git a/src/test/ui/trait-bounds/issue-93008.rs b/src/test/ui/trait-bounds/issue-93008.rs index 1b010566cbc6e..f4d21a160b695 100644 --- a/src/test/ui/trait-bounds/issue-93008.rs +++ b/src/test/ui/trait-bounds/issue-93008.rs @@ -1,10 +1,15 @@ -// compile-flags: -Zmir-opt-level=4 +// build-pass +// compile-flags: -Zmir-opt-level=3 --crate-type=lib -pub fn bar(s: &'static mut ()) +#![feature(trivial_bounds)] +#![allow(trivial_bounds)] + +trait Foo { + fn test(self); +} +fn baz() where - &'static mut (): Clone, //~ ERROR the trait bound + &'static str: Foo, { - <&'static mut () as Clone>::clone(&s); + "Foo".test() } - -fn main() {} diff --git a/src/test/ui/trait-bounds/issue-93008.stderr b/src/test/ui/trait-bounds/issue-93008.stderr deleted file mode 100644 index 10f80f8de0c9b..0000000000000 --- a/src/test/ui/trait-bounds/issue-93008.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0277]: the trait bound `&'static mut (): Clone` is not satisfied - --> $DIR/issue-93008.rs:5:5 - | -LL | &'static mut (): Clone, - | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `&'static mut ()` - | - = help: see issue #48214 - = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/trait-bounds/issue-94680.rs b/src/test/ui/trait-bounds/issue-94680.rs new file mode 100644 index 0000000000000..58e892079e65f --- /dev/null +++ b/src/test/ui/trait-bounds/issue-94680.rs @@ -0,0 +1,14 @@ +// check-pass + +fn main() { + println!("{:?}", { + type T = (); + + pub fn cloneit(it: &'_ mut T) -> (&'_ mut T, &'_ mut T) + where + for<'any> &'any mut T: Clone, + { + (it.clone(), it) + } + }); +} diff --git a/src/test/ui/trait-bounds/issue-94999.rs b/src/test/ui/trait-bounds/issue-94999.rs new file mode 100644 index 0000000000000..e131902346f1b --- /dev/null +++ b/src/test/ui/trait-bounds/issue-94999.rs @@ -0,0 +1,34 @@ +// check-pass + +trait Identity { + type T; +} + +impl Identity for T { + type T = T; +} + +trait Holds { + type Q; +} + +struct S; +struct X(S); + +struct XHelper; + +impl Holds for X { + type Q = XHelper; +} + +impl Clone for X +where + >::T: Clone, + X: Holds, +{ + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} + +fn main() {} diff --git a/src/test/ui/trait-bounds/issue-95640.rs b/src/test/ui/trait-bounds/issue-95640.rs new file mode 100644 index 0000000000000..e4e998b5d0bb8 --- /dev/null +++ b/src/test/ui/trait-bounds/issue-95640.rs @@ -0,0 +1,31 @@ +// build-pass +// compile-flags:-Zmir-opt-level=3 + +struct D; + +trait Tr { + type It; + fn foo(self) -> Option; +} + +impl<'a> Tr for &'a D { + type It = (); + fn foo(self) -> Option<()> { + None + } +} + +fn run(f: F) +where + for<'a> &'a D: Tr, + F: Fn(<&D as Tr>::It), +{ + let d = &D; + while let Some(i) = d.foo() { + f(i); + } +} + +fn main() { + run(|_| {}); +} diff --git a/src/test/ui/trait-bounds/select-param-env-instead-of-blanket.rs b/src/test/ui/trait-bounds/select-param-env-instead-of-blanket.rs new file mode 100644 index 0000000000000..288b2098b4c02 --- /dev/null +++ b/src/test/ui/trait-bounds/select-param-env-instead-of-blanket.rs @@ -0,0 +1,43 @@ +// known-bug +// build-fail +// failure-status: 101 +// compile-flags:--crate-type=lib -Zmir-opt-level=3 +// rustc-env:RUST_BACKTRACE=0 + +// normalize-stderr-test "thread 'rustc' panicked.*" -> "thread 'rustc' panicked" +// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" +// normalize-stderr-test "error: internal compiler error.*" -> "error: internal compiler error" +// normalize-stderr-test "encountered.*with incompatible types:" "encountered ... with incompatible types:" +// normalize-stderr-test "note:.*unexpectedly panicked.*\n\n" -> "" +// normalize-stderr-test "note: we would appreciate a bug report.*\n\n" -> "" +// normalize-stderr-test "note: compiler flags.*\n\n" -> "" +// normalize-stderr-test "note: rustc.*running on.*\n\n" -> "" +// normalize-stderr-test "query stack during panic:\n" -> "" +// normalize-stderr-test "we're just showing a limited slice of the query stack\n" -> "" +// normalize-stderr-test "end of query stack\n" -> "" +// normalize-stderr-test "#.*\n" -> "" + +// This is a known bug that @compiler-errors tried to fix in #94238, +// but the solution was probably not correct. + +pub trait Factory { + type Item; +} + +pub struct IntFactory; + +impl Factory for IntFactory { + type Item = usize; +} + +pub fn foo() +where + IntFactory: Factory, +{ + let mut x: >::Item = bar::(); +} + +#[inline] +pub fn bar() -> >::Item { + 0usize +} diff --git a/src/test/ui/trait-bounds/select-param-env-instead-of-blanket.stderr b/src/test/ui/trait-bounds/select-param-env-instead-of-blanket.stderr new file mode 100644 index 0000000000000..56cc5c93c96f2 --- /dev/null +++ b/src/test/ui/trait-bounds/select-param-env-instead-of-blanket.stderr @@ -0,0 +1,18 @@ +error: internal compiler error + +error: internal compiler error + encountered ... with incompatible types: + left-hand side has type: >::Item + right-hand side has type: usize + --> $DIR/select-param-env-instead-of-blanket.rs:42:5 + | +LL | let mut x: >::Item = bar::(); + | ---------- in this inlined function call +... +LL | 0usize + | ^^^^^^ + | + = note: delayed at compiler/rustc_const_eval/src/transform/validate.rs:128:36 + +thread 'rustc' panicked + diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr index f98da9f7f920a..62db019ed6a91 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference.stderr @@ -3,6 +3,9 @@ error[E0277]: the trait bound `(): Foo` is not satisfied | LL | fn foo() -> impl Foo { | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` +... +LL | () + | -- return type was inferred to be `()` here | = help: the trait `Foo<()>` is implemented for `()` diff --git a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr index 54f571ad3e37e..f4d96038d9109 100644 --- a/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr +++ b/src/test/ui/type-alias-impl-trait/nested-tait-inference2.stderr @@ -3,6 +3,9 @@ error[E0277]: the trait bound `(): Foo` is not satisfied | LL | fn foo() -> impl Foo { | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` +LL | +LL | () + | -- return type was inferred to be `()` here | = help: the following other types implement trait `Foo`: <() as Foo<()>>