Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
34 changes: 22 additions & 12 deletions compiler/rustc_codegen_ssa/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ use std::process::ExitStatus;

use rustc_errors::codes::*;
use rustc_errors::{
Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, Level, msg,
Diag, DiagArgValue, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee, IntoDiagArg,
Level, msg,
};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_middle::ty::layout::LayoutError;
Expand Down Expand Up @@ -1249,20 +1250,29 @@ pub(crate) struct FeatureNotValid<'a> {
#[label("`{$feature}` is not valid for this target")]
pub span: Span,
#[subdiagnostic]
pub plus_hint: Option<RemovePlusFromFeatureName<'a>>,
pub hint: FeatureNotValidHint<'a>,
}

#[derive(Subdiagnostic)]
#[suggestion(
"consider removing the leading `+` in the feature name",
code = "enable = \"{stripped}\"",
applicability = "maybe-incorrect",
style = "verbose"
)]
pub struct RemovePlusFromFeatureName<'a> {
#[primary_span]
pub span: Span,
pub stripped: &'a str,
pub(crate) enum FeatureNotValidHint<'a> {
#[suggestion(
"consider removing the leading `+` in the feature name",
code = "enable = \"{stripped}\"",
applicability = "maybe-incorrect",
style = "verbose"
)]
RemovePlusFromFeatureName {
#[primary_span]
span: Span,
stripped: &'a str,
},
#[help(
"valid names are: {$possibilities}{$and_more ->
[0] {\"\"}
*[other] {\" \"}and {$and_more} more
}"
)]
ValidFeatureNames { possibilities: DiagSymbolList<&'a str>, and_more: usize },
}

#[derive(Diagnostic)]
Expand Down
32 changes: 21 additions & 11 deletions compiler/rustc_codegen_ssa/src/target_features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_session::lint::builtin::AARCH64_SOFTFLOAT_NEON;
use rustc_session::parse::feature_err;
use rustc_span::{Span, Symbol, sym};
use rustc_span::{Span, Symbol, edit_distance, sym};
use rustc_target::spec::Arch;
use rustc_target::target_features::{RUSTC_SPECIFIC_FEATURES, Stability};
use smallvec::SmallVec;

use crate::errors::{FeatureNotValid, RemovePlusFromFeatureName};
use crate::errors::{FeatureNotValid, FeatureNotValidHint};
use crate::{errors, target_features};

/// Compute the enabled target features from the `#[target_feature]` function attribute.
Expand All @@ -32,15 +32,25 @@ pub(crate) fn from_target_feature_attr(
for &(feature, feature_span) in features {
let feature_str = feature.as_str();
let Some(stability) = rust_target_features.get(feature_str) else {
let plus_hint = feature_str
.strip_prefix('+')
.filter(|stripped| rust_target_features.contains_key(*stripped))
.map(|stripped| RemovePlusFromFeatureName { span: feature_span, stripped });
tcx.dcx().emit_err(FeatureNotValid {
feature: feature_str,
span: feature_span,
plus_hint,
});
let hint = if let Some(stripped) = feature_str.strip_prefix('+')
&& rust_target_features.contains_key(stripped)
{
FeatureNotValidHint::RemovePlusFromFeatureName { span: feature_span, stripped }
} else {
// Show the 5 feature names that are most similar to the input.
let mut valid_names: Vec<_> =
rust_target_features.keys().map(|name| name.as_str()).into_sorted_stable_ord();
valid_names.sort_by_key(|name| {
edit_distance::edit_distance(name, feature.as_str(), 5).unwrap_or(usize::MAX)
});
valid_names.truncate(5);

FeatureNotValidHint::ValidFeatureNames {
possibilities: valid_names.into(),
and_more: rust_target_features.len().saturating_sub(5),
}
};
tcx.dcx().emit_err(FeatureNotValid { feature: feature_str, span: feature_span, hint });
continue;
};

Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
ordered_associated_items.extend(
tcx.associated_items(pred.trait_ref.def_id)
.in_definition_order()
// Only associated types & consts can possibly be constrained via a binding.
.filter(|item| item.is_type() || item.is_const())
// Only associated types & type consts can possibly be
// constrained in a trait object type via a binding.
.filter(|item| item.is_type() || item.is_type_const())
// Traits with RPITITs are simply not dyn compatible (for now).
.filter(|item| !item.is_impl_trait_in_trait())
.map(|item| (item.def_id, trait_ref)),
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/ty/assoc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,8 @@ impl AssocItem {
self.kind.as_def_kind()
}

pub fn is_const(&self) -> bool {
matches!(self.kind, ty::AssocKind::Const { .. })
pub fn is_type_const(&self) -> bool {
matches!(self.kind, ty::AssocKind::Const { is_type_const: true, .. })
}

pub fn is_fn(&self) -> bool {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -753,7 +753,7 @@ impl<'tcx> Ty<'tcx> {
.map(|principal| {
tcx.associated_items(principal.def_id())
.in_definition_order()
.filter(|item| item.is_type() || item.is_const())
.filter(|item| item.is_type() || item.is_type_const())
.filter(|item| !item.is_impl_trait_in_trait())
.filter(|item| !tcx.generics_require_sized_self(item.def_id))
.count()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ fn trait_object_ty<'tcx>(tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tc
.flat_map(|super_poly_trait_ref| {
tcx.associated_items(super_poly_trait_ref.def_id())
.in_definition_order()
.filter(|item| item.is_type() || item.is_const())
.filter(|item| item.is_type() || item.is_type_const())
.filter(|item| !tcx.generics_require_sized_self(item.def_id))
.map(move |assoc_item| {
super_poly_trait_ref.map_bound(|super_trait_ref| {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,13 @@ impl<T> Trait<T> for X {
cause.code(),
);
}
// Don't suggest constraining a projection to something
// containing itself, e.g. `Item = &<I as Iterator>::Item`.
(_, ty::Alias(ty::Projection | ty::Inherent, proj_ty))
if !tcx.is_impl_trait_in_trait(proj_ty.def_id) =>
if !tcx.is_impl_trait_in_trait(proj_ty.def_id)
&& !tcx
.erase_and_anonymize_regions(values.expected)
.contains(tcx.erase_and_anonymize_regions(values.found)) =>
{
let msg = || {
format!(
Expand Down
9 changes: 9 additions & 0 deletions library/alloc/src/boxed/thin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -430,3 +430,12 @@ impl<T: ?Sized + Error> Error for ThinBox<T> {
self.deref().source()
}
}

#[cfg(not(no_global_oom_handling))]
#[unstable(feature = "thin_box", issue = "92791")]
impl<T> From<T> for ThinBox<T> {
#[inline(always)]
fn from(value: T) -> Self {
Self::new(value)
}
}
9 changes: 9 additions & 0 deletions library/alloc/src/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3980,6 +3980,15 @@ impl<T: ?Sized, A: Allocator> AsMut<T> for UniqueRc<T, A> {
#[unstable(feature = "unique_rc_arc", issue = "112566")]
impl<T: ?Sized, A: Allocator> Unpin for UniqueRc<T, A> {}

#[cfg(not(no_global_oom_handling))]
#[unstable(feature = "unique_rc_arc", issue = "112566")]
impl<T> From<T> for UniqueRc<T> {
#[inline(always)]
fn from(value: T) -> Self {
Self::new(value)
}
}

#[unstable(feature = "unique_rc_arc", issue = "112566")]
impl<T: ?Sized + PartialEq, A: Allocator> PartialEq for UniqueRc<T, A> {
/// Equality for two `UniqueRc`s.
Expand Down
9 changes: 9 additions & 0 deletions library/alloc/src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4424,6 +4424,15 @@ impl<T: ?Sized, A: Allocator> AsMut<T> for UniqueArc<T, A> {
}
}

#[cfg(not(no_global_oom_handling))]
#[unstable(feature = "unique_rc_arc", issue = "112566")]
impl<T> From<T> for UniqueArc<T> {
#[inline(always)]
fn from(value: T) -> Self {
Self::new(value)
}
}

#[unstable(feature = "unique_rc_arc", issue = "112566")]
impl<T: ?Sized, A: Allocator> Unpin for UniqueArc<T, A> {}

Expand Down
10 changes: 10 additions & 0 deletions library/core/src/cell/lazy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,16 @@ impl<T: fmt::Debug, F> fmt::Debug for LazyCell<T, F> {
}
}

#[stable(feature = "from_wrapper_impls", since = "CURRENT_RUSTC_VERSION")]
impl<T, F> From<T> for LazyCell<T, F> {
/// Constructs a `LazyCell` that starts already initialized
/// with the provided value.
#[inline]
fn from(value: T) -> Self {
Self { state: UnsafeCell::new(State::Init(value)) }
}
}

#[cold]
#[inline(never)]
const fn panic_poisoned() -> ! {
Expand Down
13 changes: 13 additions & 0 deletions library/core/src/panic/unwind_safe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,3 +313,16 @@ impl<S: AsyncIterator> AsyncIterator for AssertUnwindSafe<S> {
self.0.size_hint()
}
}

/// If a value's type is already `UnwindSafe`,
/// wrapping it in `AssertUnwindSafe` is never incorrect.
#[stable(feature = "from_wrapper_impls", since = "CURRENT_RUSTC_VERSION")]
impl<T> From<T> for AssertUnwindSafe<T>
where
T: UnwindSafe,
{
#[inline(always)]
fn from(value: T) -> Self {
Self(value)
}
}
14 changes: 6 additions & 8 deletions library/std/src/backtrace/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,9 @@ fn generate_fake_frames() -> Vec<BacktraceFrame> {
#[test]
fn test_debug() {
let backtrace = Backtrace {
inner: Inner::Captured(LazyLock::preinit(Capture {
actual_start: 1,
frames: generate_fake_frames(),
})),
inner: Inner::Captured(
(Capture { actual_start: 1, frames: generate_fake_frames() }).into(),
),
};

#[rustfmt::skip]
Expand All @@ -66,10 +65,9 @@ fn test_debug() {
#[test]
fn test_frames() {
let backtrace = Backtrace {
inner: Inner::Captured(LazyLock::preinit(Capture {
actual_start: 1,
frames: generate_fake_frames(),
})),
inner: Inner::Captured(
(Capture { actual_start: 1, frames: generate_fake_frames() }).into(),
),
};

let frames = backtrace.frames();
Expand Down
22 changes: 13 additions & 9 deletions library/std/src/sync/lazy_lock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,15 +105,6 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
LazyLock { once: Once::new(), data: UnsafeCell::new(Data { f: ManuallyDrop::new(f) }) }
}

/// Creates a new lazy value that is already initialized.
#[inline]
#[cfg(test)]
pub(crate) fn preinit(value: T) -> LazyLock<T, F> {
let once = Once::new();
once.call_once(|| {});
LazyLock { once, data: UnsafeCell::new(Data { value: ManuallyDrop::new(value) }) }
}

/// Consumes this `LazyLock` returning the stored value.
///
/// Returns `Ok(value)` if `Lazy` is initialized and `Err(f)` otherwise.
Expand Down Expand Up @@ -404,6 +395,19 @@ impl<T: fmt::Debug, F> fmt::Debug for LazyLock<T, F> {
}
}

#[stable(feature = "from_wrapper_impls", since = "CURRENT_RUSTC_VERSION")]
impl<T, F> From<T> for LazyLock<T, F> {
/// Constructs a `LazyLock` that starts already initialized
/// with the provided value.
#[inline]
fn from(value: T) -> Self {
LazyLock {
once: Once::new_complete(),
data: UnsafeCell::new(Data { value: ManuallyDrop::new(value) }),
}
}
}

#[cold]
#[inline(never)]
fn panic_poisoned() -> ! {
Expand Down
7 changes: 7 additions & 0 deletions library/std/src/sync/once.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,13 @@ impl Once {
Once { inner: sys::Once::new() }
}

/// Creates a new `Once` value that starts already completed.
#[inline]
#[must_use]
pub(crate) const fn new_complete() -> Once {
Once { inner: sys::Once::new_complete() }
}

/// Performs an initialization routine once and only once. The given closure
/// will be executed if this is the first time `call_once` has been called,
/// and otherwise the routine will *not* be invoked.
Expand Down
5 changes: 5 additions & 0 deletions library/std/src/sys/sync/once/futex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ impl Once {
Once { state_and_queued: Futex::new(INCOMPLETE) }
}

#[inline]
pub const fn new_complete() -> Once {
Once { state_and_queued: Futex::new(COMPLETE) }
}

#[inline]
pub fn is_completed(&self) -> bool {
// Use acquire ordering to make all initialization changes visible to the
Expand Down
5 changes: 5 additions & 0 deletions library/std/src/sys/sync/once/no_threads.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ impl Once {
Once { state: Cell::new(State::Incomplete) }
}

#[inline]
pub const fn new_complete() -> Once {
Once { state: Cell::new(State::Complete) }
}

#[inline]
pub fn is_completed(&self) -> bool {
self.state.get() == State::Complete
Expand Down
5 changes: 5 additions & 0 deletions library/std/src/sys/sync/once/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ impl Once {
Once { state_and_queue: AtomicPtr::new(ptr::without_provenance_mut(INCOMPLETE)) }
}

#[inline]
pub const fn new_complete() -> Once {
Once { state_and_queue: AtomicPtr::new(ptr::without_provenance_mut(COMPLETE)) }
}

#[inline]
pub fn is_completed(&self) -> bool {
// An `Acquire` load is enough because that makes all the initialization
Expand Down
4 changes: 2 additions & 2 deletions src/ci/docker/host-x86_64/x86_64-gnu-aux/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,5 @@ RUN sh /scripts/sccache.sh
ENV NO_DEBUG_ASSERTIONS=1
ENV NO_OVERFLOW_CHECKS=1

ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu
ENV RUST_CHECK_TARGET check-aux
ENV RUST_CONFIGURE_ARGS="--build=x86_64-unknown-linux-gnu"
ENV RUST_CHECK_TARGET="check-aux"
14 changes: 6 additions & 8 deletions src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,19 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh

ENV RUSTBUILD_FORCE_CLANG_BASED_TESTS 1
ENV RUSTBUILD_FORCE_CLANG_BASED_TESTS="1"

# llvm.use-linker conflicts with downloading CI LLVM
ENV NO_DOWNLOAD_CI_LLVM 1
ENV NO_DOWNLOAD_CI_LLVM="1"

ENV RUST_CONFIGURE_ARGS \
--build=x86_64-unknown-linux-gnu \
ENV RUST_CONFIGURE_ARGS="--build=x86_64-unknown-linux-gnu \
--enable-debug \
--enable-lld \
--set rust.debuginfo-level-tests=2 \
--set llvm.use-linker=lld \
--set target.x86_64-unknown-linux-gnu.linker=clang \
--set target.x86_64-unknown-linux-gnu.cc=clang \
--set target.x86_64-unknown-linux-gnu.cxx=clang++
--set target.x86_64-unknown-linux-gnu.cxx=clang++"

# This job checks:
# - That ui tests can be built with `-Cdebuginfo=1`
Expand All @@ -53,7 +52,6 @@ ENV RUST_CONFIGURE_ARGS \
# - That the tests with `//@ needs-force-clang-based-tests` pass, since they
# don't run by default unless RUSTBUILD_FORCE_CLANG_BASED_TESTS is set.

ENV SCRIPT \
python3 ../x.py --stage 2 build && \
ENV SCRIPT="python3 ../x.py --stage 2 build && \
python3 ../x.py --stage 2 test tests/ui && \
python3 ../x.py --stage 2 test tests/run-make tests/run-make-cargo
python3 ../x.py --stage 2 test tests/run-make tests/run-make-cargo"
Loading
Loading