Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
ef95c63
disable core dumps for panic-uninitialized-zeroed
Sep 8, 2025
eba0934
report duplicate symbol added by the driver
folkertdev Sep 8, 2025
4c84f0a
Update the LoongArch target documentation
heiher Sep 9, 2025
23edc4d
Fix compare_against_sw_vers test when a version part is 0
madsmtm Sep 9, 2025
b1c4e19
Unify and deduplicate bits conv float tests
rperier Sep 9, 2025
d50a80e
core::ptr: deduplicate docs for as_ref, addr, and as_uninit_ref
lolbinarycat Jun 10, 2025
3b21783
s390x: mark soft-float target feature as incompatible
RalfJung Sep 10, 2025
1558e65
Restore the test intention of several MBE trait bound modifier tests
fmease Sep 10, 2025
f5dad62
Less greedily parse `[const]` bounds
fmease Sep 10, 2025
5f2b046
Improve `core::ops` coverage
pvdrz Sep 10, 2025
789c840
Update library/coretests/tests/ops.rs
pvdrz Sep 10, 2025
a7528e7
Improve `core::array` coverage
pvdrz Sep 10, 2025
fc58d8f
Add regression test for assert desugaring change
jieyouxu Sep 11, 2025
b38a86f
Revert "Rollup merge of #122661 - estebank:assert-macro-span, r=petro…
jieyouxu Sep 11, 2025
602841d
Rollup merge of #142315 - lolbinarycat:core-dedup-ptr-docs-139190-pt3…
Zalathar Sep 11, 2025
cc51a7e
Rollup merge of #146335 - arielb1:dont-dump-core, r=nnethercote
Zalathar Sep 11, 2025
f38c788
Rollup merge of #146347 - folkertdev:duplicate-symbol-panic, r=fee1-dead
Zalathar Sep 11, 2025
88b5130
Rollup merge of #146370 - heiher:update-loong-linux-docs, r=jieyouxu
Zalathar Sep 11, 2025
c79c990
Rollup merge of #146379 - madsmtm:fix-platform_version-test, r=tgross35
Zalathar Sep 11, 2025
c69a792
Rollup merge of #146380 - rperier:unify_and_dedup_bits_conv_float_tes…
Zalathar Sep 11, 2025
77ec478
Rollup merge of #146415 - RalfJung:s390x-softfloat, r=workingjubilee
Zalathar Sep 11, 2025
d037d10
Rollup merge of #146422 - fmease:less-greedy-maybe-const-bounds, r=es…
Zalathar Sep 11, 2025
8184027
Rollup merge of #146424 - ferrocene:pvdrz/improve-ops-coverage, r=wor…
Zalathar Sep 11, 2025
5258dfc
Rollup merge of #146425 - ferrocene:pvdrz/improve-array-coverage, r=w…
Zalathar Sep 11, 2025
613a3b6
Rollup merge of #146428 - jieyouxu:revert-assert-desugaring, r=esteba…
Zalathar Sep 11, 2025
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
35 changes: 14 additions & 21 deletions compiler/rustc_builtin_macros/src/assert.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
mod context;

use rustc_ast::token::{self, Delimiter};
use rustc_ast::token::Delimiter;
use rustc_ast::tokenstream::{DelimSpan, TokenStream};
use rustc_ast::{DelimArgs, Expr, ExprKind, MacCall, Path, PathSegment};
use rustc_ast::{DelimArgs, Expr, ExprKind, MacCall, Path, PathSegment, UnOp, token};
use rustc_ast_pretty::pprust;
use rustc_errors::PResult;
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
Expand All @@ -29,7 +29,7 @@ pub(crate) fn expand_assert<'cx>(

// `core::panic` and `std::panic` are different macros, so we use call-site
// context to pick up whichever is currently in scope.
let call_site_span = cx.with_call_site_ctxt(cond_expr.span);
let call_site_span = cx.with_call_site_ctxt(span);

let panic_path = || {
if use_panic_2021(span) {
Expand Down Expand Up @@ -63,7 +63,7 @@ pub(crate) fn expand_assert<'cx>(
}),
})),
);
assert_cond_check(cx, call_site_span, cond_expr, then)
expr_if_not(cx, call_site_span, cond_expr, then, None)
}
// If `generic_assert` is enabled, generates rich captured outputs
//
Expand All @@ -88,33 +88,26 @@ pub(crate) fn expand_assert<'cx>(
)),
)],
);
assert_cond_check(cx, call_site_span, cond_expr, then)
expr_if_not(cx, call_site_span, cond_expr, then, None)
};

ExpandResult::Ready(MacEager::expr(expr))
}

/// `assert!($cond_expr, $custom_message)`
struct Assert {
cond_expr: Box<Expr>,
custom_message: Option<TokenStream>,
}

/// `match <cond> { true => {} _ => <then> }`
fn assert_cond_check(cx: &ExtCtxt<'_>, span: Span, cond: Box<Expr>, then: Box<Expr>) -> Box<Expr> {
// Instead of expanding to `if !<cond> { <then> }`, we expand to
// `match <cond> { true => {} _ => <then> }`.
// This allows us to always complain about mismatched types instead of "cannot apply unary
// operator `!` to type `X`" when passing an invalid `<cond>`, while also allowing `<cond>` to
// be `&true`.
let els = cx.expr_block(cx.block(span, thin_vec![]));
let mut arms = thin_vec![];
arms.push(cx.arm(span, cx.pat_lit(span, cx.expr_bool(span, true)), els));
arms.push(cx.arm(span, cx.pat_wild(span), then));

// We wrap the `match` in a statement to limit the length of any borrows introduced in the
// condition.
cx.expr_block(cx.block(span, [cx.stmt_expr(cx.expr_match(span, cond, arms))].into()))
// if !{ ... } { ... } else { ... }
fn expr_if_not(
cx: &ExtCtxt<'_>,
span: Span,
cond: Box<Expr>,
then: Box<Expr>,
els: Option<Box<Expr>>,
) -> Box<Expr> {
cx.expr_if(span, cx.expr(span, ExprKind::Unary(UnOp::Not, cond)), then, els)
}

fn parse_assert<'a>(cx: &ExtCtxt<'a>, sp: Span, stream: TokenStream) -> PResult<'a, Assert> {
Expand Down
19 changes: 11 additions & 8 deletions compiler/rustc_parse/src/parser/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,10 @@ fn can_continue_type_after_non_fn_ident(t: &Token) -> bool {
}

fn can_begin_dyn_bound_in_edition_2015(t: &Token) -> bool {
// `Not`, `Tilde` & `Const` are deliberately not part of this list to
// `!`, `const`, `[`, `async` are deliberately not part of this list to
// contain the number of potential regressions esp. in MBE code.
// `Const` would regress `rfc-2632-const-trait-impl/mbe-dyn-const-2015.rs`.
// `Not` would regress `dyn!(...)` macro calls in Rust 2015.
// `const` and `[` would regress UI test `macro-dyn-const-2015.rs`.
// `!` would regress `dyn!(...)` macro calls in Rust 2015.
t.is_path_start()
|| t.is_lifetime()
|| t == &TokenKind::Question
Expand Down Expand Up @@ -1015,12 +1015,18 @@ impl<'a> Parser<'a> {
|| self.check(exp!(Tilde))
|| self.check_keyword(exp!(For))
|| self.check(exp!(OpenParen))
|| self.check(exp!(OpenBracket))
|| self.can_begin_maybe_const_bound()
|| self.check_keyword(exp!(Const))
|| self.check_keyword(exp!(Async))
|| self.check_keyword(exp!(Use))
}

fn can_begin_maybe_const_bound(&mut self) -> bool {
self.check(exp!(OpenBracket))
&& self.look_ahead(1, |t| t.is_keyword(kw::Const))
&& self.look_ahead(2, |t| *t == token::CloseBracket)
}

/// Parse a bound.
///
/// ```ebnf
Expand Down Expand Up @@ -1199,10 +1205,7 @@ impl<'a> Parser<'a> {
let span = tilde.to(self.prev_token.span);
self.psess.gated_spans.gate(sym::const_trait_impl, span);
BoundConstness::Maybe(span)
} else if self.check(exp!(OpenBracket))
&& self.look_ahead(1, |t| t.is_keyword(kw::Const))
&& self.look_ahead(2, |t| *t == token::CloseBracket)
{
} else if self.can_begin_maybe_const_bound() {
let start = self.token.span;
self.bump();
self.expect_keyword(exp!(Const)).unwrap();
Expand Down
21 changes: 15 additions & 6 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::ops::Deref;
use std::{fmt, str};

use rustc_arena::DroplessArena;
use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
use rustc_data_structures::stable_hasher::{
HashStable, StableCompare, StableHasher, ToStableHashKey,
};
Expand Down Expand Up @@ -2871,11 +2871,20 @@ impl Interner {
let byte_strs = FxIndexSet::from_iter(
init.iter().copied().chain(extra.iter().copied()).map(|str| str.as_bytes()),
);
assert_eq!(
byte_strs.len(),
init.len() + extra.len(),
"duplicate symbols in the rustc symbol list and the extra symbols added by the driver",
);

// The order in which duplicates are reported is irrelevant.
#[expect(rustc::potential_query_instability)]
if byte_strs.len() != init.len() + extra.len() {
panic!(
"duplicate symbols in the rustc symbol list and the extra symbols added by the driver: {:?}",
FxHashSet::intersection(
&init.iter().copied().collect(),
&extra.iter().copied().collect(),
)
.collect::<Vec<_>>()
)
}

Interner(Lock::new(InternerInner { arena: Default::default(), byte_strs }))
}

Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_target/src/target_features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,7 @@ const IBMZ_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
("miscellaneous-extensions-3", Unstable(sym::s390x_target_feature), &[]),
("miscellaneous-extensions-4", Unstable(sym::s390x_target_feature), &[]),
("nnp-assist", Unstable(sym::s390x_target_feature), &["vector"]),
("soft-float", Forbidden { reason: "currently unsupported ABI-configuration feature" }, &[]),
("transactional-execution", Unstable(sym::s390x_target_feature), &[]),
("vector", Unstable(sym::s390x_target_feature), &[]),
("vector-enhancements-1", Unstable(sym::s390x_target_feature), &["vector"]),
Expand Down Expand Up @@ -1177,6 +1178,13 @@ impl Target {
_ => unreachable!(),
}
}
"s390x" => {
// We don't currently support a softfloat target on this architecture.
// As usual, we have to reject swapping the `soft-float` target feature.
// The "vector" target feature does not affect the ABI for floats
// because the vector and float registers overlap.
FeatureConstraints { required: &[], incompatible: &["soft-float"] }
}
_ => NOTHING,
}
}
Expand Down
40 changes: 4 additions & 36 deletions compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1618,18 +1618,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
{
let e = self.tcx.erase_and_anonymize_regions(e);
let f = self.tcx.erase_and_anonymize_regions(f);
let mut expected = with_forced_trimmed_paths!(e.sort_string(self.tcx));
let mut found = with_forced_trimmed_paths!(f.sort_string(self.tcx));
if let ObligationCauseCode::Pattern { span, .. } = cause.code()
&& let Some(span) = span
&& !span.from_expansion()
&& cause.span.from_expansion()
{
// When the type error comes from a macro like `assert!()`, and we are pointing at
// code the user wrote the cause and effect are reversed as the expected value is
// what the macro expanded to.
(found, expected) = (expected, found);
}
let expected = with_forced_trimmed_paths!(e.sort_string(self.tcx));
let found = with_forced_trimmed_paths!(f.sort_string(self.tcx));
if expected == found {
label_or_note(span, terr.to_string(self.tcx));
} else {
Expand Down Expand Up @@ -2152,9 +2142,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
) -> Option<(DiagStyledString, DiagStyledString)> {
match values {
ValuePairs::Regions(exp_found) => self.expected_found_str(exp_found),
ValuePairs::Terms(exp_found) => {
self.expected_found_str_term(cause, exp_found, long_ty_path)
}
ValuePairs::Terms(exp_found) => self.expected_found_str_term(exp_found, long_ty_path),
ValuePairs::Aliases(exp_found) => self.expected_found_str(exp_found),
ValuePairs::ExistentialTraitRef(exp_found) => self.expected_found_str(exp_found),
ValuePairs::ExistentialProjection(exp_found) => self.expected_found_str(exp_found),
Expand Down Expand Up @@ -2193,35 +2181,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {

fn expected_found_str_term(
&self,
cause: &ObligationCause<'tcx>,
exp_found: ty::error::ExpectedFound<ty::Term<'tcx>>,
long_ty_path: &mut Option<PathBuf>,
) -> Option<(DiagStyledString, DiagStyledString)> {
let exp_found = self.resolve_vars_if_possible(exp_found);
if exp_found.references_error() {
return None;
}
let (mut expected, mut found) = (exp_found.expected, exp_found.found);

if let ObligationCauseCode::Pattern { span, .. } = cause.code()
&& let Some(span) = span
&& !span.from_expansion()
&& cause.span.from_expansion()
{
// When the type error comes from a macro like `assert!()`, and we are pointing at
// code the user wrote, the cause and effect are reversed as the expected value is
// what the macro expanded to. So if the user provided a `Type` when the macro is
// written in such a way that a `bool` was expected, we want to print:
// = note: expected `bool`
// found `Type`"
// but as far as the compiler is concerned, after expansion what was expected was `Type`
// = note: expected `Type`
// found `bool`"
// so we reverse them here to match user expectation.
(expected, found) = (found, expected);
}

Some(match (expected.kind(), found.kind()) {
Some(match (exp_found.expected.kind(), exp_found.found.kind()) {
(ty::TermKind::Ty(expected), ty::TermKind::Ty(found)) => {
let (mut exp, mut fnd) = self.cmp(expected, found);
// Use the terminal width as the basis to determine when to compress the printed
Expand Down
78 changes: 13 additions & 65 deletions library/core/src/ptr/const_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,28 +146,7 @@ impl<T: PointeeSized> *const T {
self as _
}

/// Gets the "address" portion of the pointer.
///
/// This is similar to `self as usize`, except that the [provenance][crate::ptr#provenance] of
/// the pointer is discarded and not [exposed][crate::ptr#exposed-provenance]. This means that
/// casting the returned address back to a pointer yields a [pointer without
/// provenance][without_provenance], which is undefined behavior to dereference. To properly
/// restore the lost information and obtain a dereferenceable pointer, use
/// [`with_addr`][pointer::with_addr] or [`map_addr`][pointer::map_addr].
///
/// If using those APIs is not possible because there is no way to preserve a pointer with the
/// required provenance, then Strict Provenance might not be for you. Use pointer-integer casts
/// or [`expose_provenance`][pointer::expose_provenance] and [`with_exposed_provenance`][with_exposed_provenance]
/// instead. However, note that this makes your code less portable and less amenable to tools
/// that check for compliance with the Rust memory model.
///
/// On most platforms this will produce a value with the same bytes as the original
/// pointer, because all the bytes are dedicated to describing the address.
/// Platforms which need to store additional information in the pointer may
/// perform a change of representation to produce a value containing only the address
/// portion of the pointer. What that means is up to the platform to define.
///
/// This is a [Strict Provenance][crate::ptr#strict-provenance] API.
#[doc = include_str!("./docs/addr.md")]
#[must_use]
#[inline(always)]
#[stable(feature = "strict_provenance", since = "1.84.0")]
Expand Down Expand Up @@ -254,23 +233,16 @@ impl<T: PointeeSized> *const T {
(self.cast(), metadata(self))
}

/// Returns `None` if the pointer is null, or else returns a shared reference to
/// the value wrapped in `Some`. If the value may be uninitialized, [`as_uninit_ref`]
/// must be used instead.
///
/// [`as_uninit_ref`]: #method.as_uninit_ref
///
/// # Safety
///
/// When calling this method, you have to ensure that *either* the pointer is null *or*
/// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion).
#[doc = include_str!("./docs/as_ref.md")]
///
/// # Panics during const evaluation
///
/// This method will panic during const evaluation if the pointer cannot be
/// determined to be null or not. See [`is_null`] for more information.
/// ```
/// let ptr: *const u8 = &10u8 as *const u8;
///
/// [`is_null`]: #method.is_null
/// unsafe {
/// let val_back = &*ptr;
/// assert_eq!(val_back, &10);
/// }
/// ```
///
/// # Examples
///
Expand All @@ -284,20 +256,9 @@ impl<T: PointeeSized> *const T {
/// }
/// ```
///
/// # Null-unchecked version
///
/// If you are sure the pointer can never be null and are looking for some kind of
/// `as_ref_unchecked` that returns the `&T` instead of `Option<&T>`, know that you can
/// dereference the pointer directly.
///
/// ```
/// let ptr: *const u8 = &10u8 as *const u8;
///
/// unsafe {
/// let val_back = &*ptr;
/// assert_eq!(val_back, &10);
/// }
/// ```
/// [`is_null`]: #method.is_null
/// [`as_uninit_ref`]: #method.as_uninit_ref
#[stable(feature = "ptr_as_ref", since = "1.9.0")]
#[rustc_const_stable(feature = "const_ptr_is_null", since = "1.84.0")]
#[inline]
Expand Down Expand Up @@ -338,23 +299,10 @@ impl<T: PointeeSized> *const T {
unsafe { &*self }
}

/// Returns `None` if the pointer is null, or else returns a shared reference to
/// the value wrapped in `Some`. In contrast to [`as_ref`], this does not require
/// that the value has to be initialized.
///
/// [`as_ref`]: #method.as_ref
///
/// # Safety
///
/// When calling this method, you have to ensure that *either* the pointer is null *or*
/// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion).
///
/// # Panics during const evaluation
///
/// This method will panic during const evaluation if the pointer cannot be
/// determined to be null or not. See [`is_null`] for more information.
#[doc = include_str!("./docs/as_uninit_ref.md")]
///
/// [`is_null`]: #method.is_null
/// [`as_ref`]: #method.as_ref
///
/// # Examples
///
Expand Down
21 changes: 21 additions & 0 deletions library/core/src/ptr/docs/INFO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
This directory holds method documentation that otherwise
would be duplicated across mutable and immutable pointers.

Note that most of the docs here are not the complete docs
for their corresponding method. This is for a few reasons:

1. Examples need to be different for mutable/immutable
pointers, in order to actually call the correct method.
2. Link reference definitions are frequently different
between mutable/immutable pointers, in order to link to
the correct method.
For example, `<*const T>::as_ref` links to
`<*const T>::is_null`, while `<*mut T>::as_ref` links to
`<*mut T>::is_null`.
3. Many methods on mutable pointers link to an alternate
version that returns a mutable reference instead of
a shared reference.

Always review the rendered docs manually when making
changes to these files to make sure you're not accidentally
splitting up a section.
Loading
Loading