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
7a96d86
Fix typos in `intrinsics::size_of_type_id` panic message and doc comment
SpriteOvO May 7, 2026
d1ad629
Add `TypeId::variants` method to get number of variants for `type_info`
SpriteOvO May 7, 2026
b50aae6
Add `TypeId::fields` method to get number of fields for `type_info`
SpriteOvO May 7, 2026
8fec623
Inside attributes, suggest adding quotation marks to identifier when …
ariagivens May 21, 2026
28733aa
Add `TypeId::field` method to get a field representing type for `type…
SpriteOvO May 10, 2026
76de222
add relnotes
BoxyUwU May 25, 2026
a7cdee1
Apply suggestion from @BoxyUwU
BoxyUwU May 25, 2026
b665316
Allow building the source tarballs while offline
bjorn3 May 27, 2026
2043790
`#[expect]` is an attribute valid for outer style
samueltardieu May 27, 2026
6a51d20
Show crate root path in misplaced crate-level attribute diagnostic
Dnreikronos May 27, 2026
1e62f5a
Suppress crate-root help when attribute is in same file
Dnreikronos May 27, 2026
bb92226
Remove trailing whitespace left by deleted annotations
Dnreikronos May 27, 2026
1fa9548
Support quotation mark suggestion for attributes in apple tests
ariagivens May 27, 2026
59debaf
Mark submod.rs as auxiliary so compiletest skips it
Dnreikronos May 27, 2026
b513e53
`FieldId` wraps FRT `TypeId` instead of the actual field `TypeId`
SpriteOvO May 27, 2026
8db956b
Move multi-file test to use auxiliary/ directory layout
Dnreikronos May 27, 2026
fd3b569
Apply suggestions from code review
cuviper May 28, 2026
dd6f520
clean up spaces and add a rustdoc anchor
cuviper May 28, 2026
63d96cb
Fix `assert_matches!` link
cuviper May 28, 2026
54352a0
Rollup merge of #156932 - BoxyUwU:relnotes_1_96_0, r=cuviper
matthiaskrgr May 28, 2026
ac7ba99
Rollup merge of #156403 - SpriteOvO:type-info-refactor-variant, r=oli…
matthiaskrgr May 28, 2026
c67006e
Rollup merge of #156797 - ariagivens:suggest-quotes, r=JonathanBrouwer
matthiaskrgr May 28, 2026
0578fb7
Rollup merge of #157014 - bjorn3:source_tarball_offline, r=jieyouxu
matthiaskrgr May 28, 2026
7277731
Rollup merge of #157023 - samueltardieu:push-mwykwuslpolq, r=nnethercote
matthiaskrgr May 28, 2026
89777ad
Rollup merge of #157025 - Dnreikronos:fix/crate-root-path-help-in-att…
matthiaskrgr May 28, 2026
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
93 changes: 93 additions & 0 deletions RELEASES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,96 @@
Version 1.96.0 (2026-05-28)
==========================

<a id="1.96.0-Language"></a>

Language
--------
- [Allow passing `expr` metavariable to `cfg`](https://github.com/rust-lang/rust/pull/146961)
- [Always coerce never types in tuple expressions](https://github.com/rust-lang/rust/pull/147834)
- [Avoid incorrect inference guidance of function arguments in rare cases](https://github.com/rust-lang/rust/pull/150316)
- [Support s390x vector registers in inline assembly](https://github.com/rust-lang/rust/pull/154184)
- [Allow using constants of type `ManuallyDrop` as patterns (fixing a regression introduced in 1.94.0)](https://github.com/rust-lang/rust/pull/154891)

<a id="1.96.0-Compiler"></a>

Compiler
--------
- [Enable link relaxation feature for LoongArch Linux targets](https://github.com/rust-lang/rust/pull/153427)
- [Update `riscv64gc-unknown-fuchsia` baseline to RVA22 + vector](https://github.com/rust-lang/rust/pull/155072)

<a id="1.96.0-Libraries"></a>

Libraries
---------
- [Support iterating over ranges of `NonZero` integers](https://github.com/rust-lang/rust/pull/127534)
- [refactor 'valid for read/write' definition: exclude null; add that as an exception on individual methods instead](https://github.com/rust-lang/rust/pull/152615)
- [Fix SGX delayed host lookup via ToSocketAddr](https://github.com/rust-lang/rust/pull/152851)

<a id="1.96.0-Stabilized-APIs"></a>

Stabilized APIs
---------------

- [`assert_matches!`](https://doc.rust-lang.org/stable/std/macro.assert_matches.html)
- [`debug_assert_matches!`](https://doc.rust-lang.org/stable/std/macro.debug_assert_matches.html)
- [`From<T> for AssertUnwindSafe<T>`](https://doc.rust-lang.org/stable/std/panic/struct.AssertUnwindSafe.html#impl-From%3CT%3E-for-AssertUnwindSafe%3CT%3E)
- [`From<T> for LazyCell<T, F>`](https://doc.rust-lang.org/stable/std/cell/struct.LazyCell.html#impl-From%3CT%3E-for-LazyCell%3CT,+F%3E)
- [`From<T> for LazyLock<T, F>`](https://doc.rust-lang.org/stable/std/sync/struct.LazyLock.html#impl-From%3CT%3E-for-LazyLock%3CT,+F%3E)
- [`core::range::RangeToInclusive`](https://doc.rust-lang.org/stable/core/range/struct.RangeToInclusive.html)
- [`core::range::RangeToInclusiveIter`](https://doc.rust-lang.org/stable/core/range/struct.RangeToInclusiveIter.html)
- [`core::range::RangeFrom`](https://doc.rust-lang.org/stable/core/ops/struct.RangeFrom.html)
- [`core::range::RangeFromIter`](https://doc.rust-lang.org/stable/core/ops/struct.RangeFromIter.html)
- [`core::range::Range`](https://doc.rust-lang.org/stable/std/range/struct.Range.html)
- [`core::range::RangeIter`](https://doc.rust-lang.org/stable/std/range/struct.RangeIter.html)

<a id="1.96.0-Cargo"></a>

Cargo
-----
- [Allow a dependency to specify both a git repository and an alternate registry.](https://github.com/rust-lang/cargo/pull/16810/) Just like with crates.io, the git repository will be used locally, but the registry version will be used when published.
- [Added `target.'cfg(..)'.rustdocflags` support in configuration.](https://github.com/rust-lang/cargo/pull/16846)
- Fixed [CVE-2026-5222](https://blog.rust-lang.org/2026/05/25/cve-2026-5222/) and [CVE-2026-5223](https://blog.rust-lang.org/2026/05/25/cve-2026-5223/).

<a id="1.96-Rustdoc"></a>

Rustdoc
-----
- [Deprecation notes are now rendered like any other documentation](https://github.com/rust-lang/rust/pull/149931). Previously they used the css `white-space: pre-wrap;` property and stripped any `<p>` elements from the rendered html, however this caused issues and unintuitive behavior. The new behavior should be more predictable, however some multi-line deprecation notes will now be rendered as as single lines. If this is undesirable, you can use the standard markdown method of forcing a linebreak, which is two spaces followed by a newline (`"\n"`).
- [Don't emit rustdoc `missing_doc_code_examples` lint on impl items](https://github.com/rust-lang/rust/pull/154048)
- [Seperate methods and associated functions in sidebar](https://github.com/rust-lang/rust/pull/154644)

<a id="1.96.0-Compatibility-Notes"></a>

Compatibility Notes
-------------------
- [Fix layout of `#[repr(Int)]` enums in some edge cases involving fields of uninhabited zero-sized types](https://github.com/rust-lang/rust/pull/146989)
- [Prevent unsize-coercing into `Pin<Foo>` where `Foo` doesn't implement `Deref`. Some such coercions were previously allowed, but produce a type with no useful public API.](https://github.com/rust-lang/rust/pull/149218)
- [rustc: Stop passing `--allow-undefined` on wasm targets](https://github.com/rust-lang/rust/pull/149868)
- [Gate the accidentally stabilized `#![reexport_test_harness_main]` attribute](https://github.com/rust-lang/rust/pull/152210)
- [Error on return-position-impl-trait-in-traits whose types are too private](https://github.com/rust-lang/rust/pull/152543)
- [Report the `uninhabited_static` lint in dependencies and make it deny-by-default](https://github.com/rust-lang/rust/pull/152853)
- [Distributed builds now contain non-split debuginfo for windows-gnu](https://github.com/rust-lang/rust/pull/152870)
This appears to improve the quality of backtraces. This change has no effect on the defaults for the output of rustc/cargo on these targets.
- [Check const generic arguments are correctly typed in more positions](https://github.com/rust-lang/rust/pull/152931)
- [Remove `-Csoft-float`](https://github.com/rust-lang/rust/pull/152973)
- [Importing structs with `::{self [as name]}`, e.g., `struct S {}; use S::{self as Other};`, is now no longer permitted because `{self}` imports require a module parent.](https://github.com/rust-lang/rust/pull/152996)
- [For `export_name`, `link_name`, and `link_section` attributes, if multiple of the same attribute is present, the first one now takes precedence.](https://github.com/rust-lang/rust/pull/153041)
- [Update the minimum external LLVM to 21](https://github.com/rust-lang/rust/pull/153684)
- On `avr` targets, C's `double` type is 32-bit by default, so [change `c_double` to `f32` on `avr` targets to match](https://github.com/rust-lang/rust/pull/154647). This is a breaking change, but necessary to make `c_double` match C's double.

<a id="1.96.0-Internal-Changes"></a>

Internal Changes
----------------

These changes do not affect any public interfaces of Rust, but they represent
significant improvements to the performance or internals of rustc and related
tools.

- [JSON targets: `aarch64` softfloat targets now have to have `rustc_abi` set to `"softfloat"`](https://github.com/rust-lang/rust/pull/152941)
- [target specs: stricter checks for LLVM ABI values, and correlate that with `cfg(target_abi)`](https://github.com/rust-lang/rust/pull/153769)


Version 1.95.0 (2026-04-16)
===========================

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3497,6 +3497,7 @@ impl AttrItem {
|| self.path == sym::warn
|| self.path == sym::allow
|| self.path == sym::deny
|| self.path == sym::expect
}
}

Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_attr_parsing/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,9 @@ pub(crate) struct InvalidAttrStyle {
#[note("this attribute does not have an `!`, which means it is applied to this {$target}")]
pub target_span: Option<Span>,
pub target: &'static str,
pub crate_root_path: String,
#[help("the crate root is at `{$crate_root_path}`")]
pub show_crate_root_help: bool,
}

#[derive(Diagnostic)]
Expand Down
17 changes: 15 additions & 2 deletions compiler/rustc_attr_parsing/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use rustc_ast::{
AttrArgs, Expr, ExprKind, LitKind, MetaItemLit, Path, PathSegment, StmtKind, UnOp,
};
use rustc_ast_pretty::pprust;
use rustc_errors::{Diag, PResult};
use rustc_errors::{Applicability, Diag, PResult};
use rustc_hir::{self as hir, AttrPath};
use rustc_parse::exp;
use rustc_parse::parser::{ForceCollect, Parser, PathStyle, Recovery, token_descr};
Expand Down Expand Up @@ -410,7 +410,20 @@ fn expr_to_lit<'sess>(
// - `#[foo = include_str!("nonexistent-file.rs")]`:
// results in `ast::ExprKind::Err`.
let msg = "attribute value must be a literal";
let err = psess.dcx().struct_span_err(span, msg);
let mut err = psess.dcx().struct_span_err(span, msg);

// Suggest adding quotation marks to turn an identifier into a string literal
if let ExprKind::Path(None, ref path) = expr.kind
&& let [segment] = path.segments.as_slice()
{
err.span_suggestion(
expr.span,
"try adding quotation marks",
&format!("\"{}\"", segment.ident),
Applicability::MaybeIncorrect,
);
}

Err(err)
}
}
Expand Down
18 changes: 17 additions & 1 deletion compiler/rustc_attr_parsing/src/target_checking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use rustc_errors::{DiagArgValue, Diagnostic, MultiSpan, StashKey};
use rustc_feature::Features;
use rustc_hir::attrs::AttributeKind;
use rustc_hir::{AttrItem, Attribute, MethodKind, Target};
use rustc_span::{BytePos, Span, Symbol, sym};
use rustc_span::{BytePos, FileName, RemapPathScopeComponents, Span, Symbol, sym};

use crate::AttributeParser;
use crate::context::AcceptContext;
Expand Down Expand Up @@ -186,13 +186,29 @@ impl<'sess> AttributeParser<'sess> {
let target_span = cx.target_span;
let attr_span = cx.attr_span;

let (show_crate_root_help, crate_root_path) = is_used_as_inner
.then(|| cx.cx.sess.local_crate_source_file())
.flatten()
.filter(|src| {
!matches!(
cx.cx.sess.source_map().span_to_filename(attr_span),
FileName::Real(ref name) if name == src
)
})
.map(|src| {
(true, src.path(RemapPathScopeComponents::DIAGNOSTICS).display().to_string())
})
.unwrap_or_default();

cx.emit_lint(
rustc_session::lint::builtin::UNUSED_ATTRIBUTES,
crate::errors::InvalidAttrStyle {
name,
is_used_as_inner,
target_span: (!is_used_as_inner).then_some(target_span),
target: target.name(),
crate_root_path,
show_crate_root_help,
},
attr_span,
);
Expand Down
85 changes: 84 additions & 1 deletion compiler/rustc_const_eval/src/const_eval/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::borrow::{Borrow, Cow};
use std::hash::Hash;
use std::{fmt, mem};

use rustc_abi::{Align, FIRST_VARIANT, FieldIdx, Size};
use rustc_abi::{Align, FIRST_VARIANT, FieldIdx, Size, VariantIdx};
use rustc_ast::Mutability;
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, IndexEntry};
use rustc_hir::def_id::{DefId, LocalDefId};
Expand Down Expand Up @@ -622,6 +622,75 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
ecx.write_discriminant(variant_index, dest)?;
}

sym::type_id_fields => {
let ty = ecx.read_type_id(&args[0])?;
let variant_idx = ecx.read_target_usize(&args[1])? as usize;

let variants_num =
ty.ty_adt_def().map(|adt_def| adt_def.variants().len()).unwrap_or(1);
if variant_idx >= variants_num {
throw_ub!(BoundsCheckFailed {
len: variants_num as u64,
index: variant_idx as u64
});
}

let fields_num = match ty.kind() {
ty::Adt(adt_def, _) => {
let variant_def = &adt_def.variants()[VariantIdx::from_usize(variant_idx)];
variant_def.fields.len()
}
ty::Tuple(fields) => fields.len(),
_ => 0, // Other types have no fields
};

ecx.write_scalar(Scalar::from_target_usize(fields_num as u64, ecx), dest)?;
}

sym::type_id_field_representing_type => {
let ty = ecx.read_type_id(&args[0])?;
let variant_idx = ecx.read_target_usize(&args[1])? as usize;
let field_idx = ecx.read_target_usize(&args[2])? as usize;

let variants_num =
ty.ty_adt_def().map(|adt_def| adt_def.variants().len()).unwrap_or(1);
if variant_idx >= variants_num {
throw_ub!(BoundsCheckFailed {
len: variants_num as u64,
index: variant_idx as u64
});
}

let fields_num = match ty.kind() {
ty::Adt(adt_def, _) => {
let variant_def = &adt_def.variants()[VariantIdx::from_usize(variant_idx)];
variant_def.fields.len()
}
ty::Tuple(fields) => fields.len(),
_ => 0, // Other types have no fields
};
if field_idx >= fields_num {
throw_ub!(BoundsCheckFailed {
len: fields_num as u64,
index: field_idx as u64
});
}

let frt = Ty::new_field_representing_type(
*ecx.tcx,
ty,
VariantIdx::from_usize(variant_idx),
FieldIdx::from_usize(field_idx),
);
ecx.write_type_id(frt, dest)?;
}

sym::type_id_variants => {
let ty = ecx.read_type_id(&args[0])?;
let variants_num = ty.ty_adt_def().map(|def| def.variants().len()).unwrap_or(1);
ecx.write_scalar(Scalar::from_target_usize(variants_num as u64, ecx), dest)?;
}

sym::field_offset => {
let frt_ty = instance.args.type_at(0);
ensure_monomorphic_enough(ecx.tcx.tcx, frt_ty)?;
Expand All @@ -643,6 +712,20 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
ecx.write_scalar(Scalar::from_target_usize(offset, ecx), dest)?;
}

sym::field_representing_type_actual_type_id => {
let frt_ty = ecx.read_type_id(&args[0])?;

let field_ty = if let ty::Adt(def, args) = frt_ty.kind()
&& let Some(FieldInfo { ty, .. }) =
def.field_representing_type_info(ecx.tcx.tcx, args)
{
ecx.tcx.erase_and_anonymize_regions(ty)
} else {
span_bug!(ecx.cur_span(), "expected field representing type, got {frt_ty}")
};
ecx.write_type_id(field_ty, dest)?;
}

_ => {
// We haven't handled the intrinsic, let's see if we can use a fallback body.
if ecx.tcx.intrinsic(instance.def_id()).unwrap().must_be_overridden {
Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_hir_analysis/src/check/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi
| sym::fadd_algebraic
| sym::fdiv_algebraic
| sym::field_offset
| sym::field_representing_type_actual_type_id
| sym::floorf16
| sym::floorf32
| sym::floorf64
Expand Down Expand Up @@ -213,6 +214,9 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi
| sym::truncf128
| sym::type_id
| sym::type_id_eq
| sym::type_id_field_representing_type
| sym::type_id_fields
| sym::type_id_variants
| sym::type_id_vtable
| sym::type_name
| sym::type_of
Expand Down Expand Up @@ -319,6 +323,11 @@ pub(crate) fn check_intrinsic_type(
sym::type_name => (1, 0, vec![], Ty::new_static_str(tcx)),
sym::type_id => (1, 0, vec![], type_id_ty()),
sym::type_id_eq => (0, 0, vec![type_id_ty(), type_id_ty()], tcx.types.bool),
sym::type_id_field_representing_type => {
(0, 0, vec![type_id_ty(), tcx.types.usize, tcx.types.usize], type_id_ty())
}
sym::type_id_fields => (0, 0, vec![type_id_ty(), tcx.types.usize], tcx.types.usize),
sym::type_id_variants => (0, 0, vec![type_id_ty()], tcx.types.usize),
sym::type_id_vtable => {
let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, span);
let dyn_metadata_adt_ref = tcx.adt_def(dyn_metadata);
Expand All @@ -339,6 +348,7 @@ pub(crate) fn check_intrinsic_type(
vec![type_id_ty()],
tcx.type_of(tcx.lang_items().type_struct().unwrap()).no_bound_vars().unwrap(),
),
sym::field_representing_type_actual_type_id => (0, 0, vec![type_id_ty()], type_id_ty()),
sym::offload => (
3,
0,
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,7 @@ symbols! {
field_offset,
field_projections,
field_representing_type,
field_representing_type_actual_type_id,
field_representing_type_raw,
field_type,
fields,
Expand Down Expand Up @@ -2098,6 +2099,9 @@ symbols! {
type_changing_struct_update,
type_id,
type_id_eq,
type_id_field_representing_type,
type_id_fields,
type_id_variants,
type_id_vtable,
type_info,
type_ir,
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -829,7 +829,7 @@ impl TypeId {
}
}

fn as_u128(self) -> u128 {
pub(crate) fn as_u128(self) -> u128 {
let mut bytes = [0; 16];

// This is a provenance-stripping memcpy.
Expand Down
Loading
Loading