Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
23e99d3
Implement `Duration::div_duration_{floor,ceil}`
max-heller Dec 3, 2025
ac7e6c6
Optimized implementation for uN::{gather,scatter}_bits
quaternic Dec 3, 2025
79d792f
use more descriptive variable names
quaternic Dec 8, 2025
242e58e
Add more `unbounded_sh[lr]` examples
scottmcm Dec 15, 2025
60bba9b
std: sys: fs: uefi: Implement readdir
Ayush1325 Dec 2, 2025
053597f
add several older crashtests
cyrgani Dec 25, 2025
a9442b4
Fix ICE by rejecting const blocks in patterns during AST lowering
Shinonn23 Dec 5, 2025
ca64688
parser/lexer: bump to Unicode 17, use faster unicode-ident
Marcondiro Oct 30, 2025
f7cb82e
lexer/parser: ensure deps use the same unicode version
Marcondiro Dec 13, 2025
b29cc98
refactor destructure_const
Kivooeo Dec 25, 2025
30618bb
Rollup merge of #148321 - Marcondiro:master, r=Mark-Simulacrum
JonathanBrouwer Dec 28, 2025
b512fa7
Rollup merge of #149540 - Ayush1325:uefi-fs-readdir, r=Mark-Simulacrum
JonathanBrouwer Dec 28, 2025
7b105b2
Rollup merge of #149582 - max-heller:duration-integer-division, r=Mar…
JonathanBrouwer Dec 28, 2025
8bd4d04
Rollup merge of #149663 - quaternic:gather-scatter-bits-opt, r=Mark-S…
JonathanBrouwer Dec 28, 2025
ef835a8
Rollup merge of #149667 - Shinonn23:fix-ice-constblock-148138, r=dianne
JonathanBrouwer Dec 28, 2025
32e8481
Rollup merge of #149947 - cyrgani:crashtests, r=Mark-Simulacrum
JonathanBrouwer Dec 28, 2025
13633c5
Rollup merge of #150011 - scottmcm:more-unbounded-shift-docs, r=Mark-…
JonathanBrouwer Dec 28, 2025
1117bd9
Rollup merge of #150411 - Kivooeo:somefunnystuff, r=BoxyUwU
JonathanBrouwer Dec 28, 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
14 changes: 7 additions & 7 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4144,8 +4144,8 @@ version = "0.0.0"
dependencies = [
"expect-test",
"memchr",
"unicode-ident",
"unicode-properties",
"unicode-xid",
]

[[package]]
Expand Down Expand Up @@ -5981,24 +5981,24 @@ checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"

[[package]]
name = "unicode-ident"
version = "1.0.18"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"

[[package]]
name = "unicode-normalization"
version = "0.1.24"
version = "0.1.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956"
checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8"
dependencies = [
"tinyvec",
]

[[package]]
name = "unicode-properties"
version = "0.1.3"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0"
checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d"

[[package]]
name = "unicode-script"
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_ast_lowering/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ ast_lowering_abi_specified_multiple_times =
ast_lowering_arbitrary_expression_in_pattern =
arbitrary expressions aren't allowed in patterns
.pattern_from_macro_note = the `expr` fragment specifier forces the metavariable's content to be an expression
.const_block_in_pattern_help = use a named `const`-item or an `if`-guard (`x if x == const {"{ ... }"}`) instead

ast_lowering_argument = argument

Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_ast_lowering/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,8 @@ pub(crate) struct ArbitraryExpressionInPattern {
pub span: Span,
#[note(ast_lowering_pattern_from_macro_note)]
pub pattern_from_macro_note: bool,
#[help(ast_lowering_const_block_in_pattern_help)]
pub const_block_in_pattern_help: bool,
}

#[derive(Diagnostic)]
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_ast_lowering/src/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
ExprKind::Lit(lit) => {
hir::PatExprKind::Lit { lit: self.lower_lit(lit, span), negated: false }
}
ExprKind::ConstBlock(c) => hir::PatExprKind::ConstBlock(self.lower_const_block(c)),
ExprKind::IncludedBytes(byte_sym) => hir::PatExprKind::Lit {
lit: respan(span, LitKind::ByteStr(*byte_sym, StrStyle::Cooked)),
negated: false,
Expand All @@ -419,10 +418,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
hir::PatExprKind::Lit { lit: self.lower_lit(lit, span), negated: true }
}
_ => {
let is_const_block = matches!(expr.kind, ExprKind::ConstBlock(_));
let pattern_from_macro = expr.is_approximately_pattern();
let guar = self.dcx().emit_err(ArbitraryExpressionInPattern {
span,
pattern_from_macro_note: pattern_from_macro,
const_block_in_pattern_help: is_const_block,
});
err(guar)
}
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1944,7 +1944,6 @@ pub enum PatExprKind<'hir> {
// once instead of matching on unop neg expressions everywhere.
negated: bool,
},
ConstBlock(ConstBlock),
/// A path pattern for a unit struct/variant or a (maybe-associated) constant.
Path(QPath<'hir>),
}
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -792,7 +792,6 @@ pub fn walk_pat_expr<'v, V: Visitor<'v>>(visitor: &mut V, expr: &'v PatExpr<'v>)
try_visit!(visitor.visit_id(*hir_id));
match kind {
PatExprKind::Lit { lit, negated } => visitor.visit_lit(*hir_id, *lit, *negated),
PatExprKind::ConstBlock(c) => visitor.visit_inline_const(c),
PatExprKind::Path(qpath) => visitor.visit_qpath(qpath, *hir_id, *span),
}
}
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_hir_pretty/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1880,7 +1880,6 @@ impl<'a> State<'a> {
}
self.print_literal(lit);
}
hir::PatExprKind::ConstBlock(c) => self.print_inline_const(c),
hir::PatExprKind::Path(qpath) => self.print_qpath(qpath, true),
}
}
Expand Down
3 changes: 0 additions & 3 deletions compiler/rustc_hir_typeck/src/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -925,9 +925,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
ty
}
rustc_hir::PatExprKind::ConstBlock(c) => {
self.check_expr_const_block(c, Expectation::NoExpectation)
}
rustc_hir::PatExprKind::Path(qpath) => {
let (res, opt_ty, segments) =
self.resolve_ty_and_res_fully_qualified_call(qpath, lt.hir_id, lt.span);
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_lexer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ Rust lexer used by rustc. No stability guarantees are provided.
# Note that this crate purposefully does not depend on other rustc crates
[dependencies]
memchr = "2.7.6"
unicode-properties = { version = "0.1.0", default-features = false, features = ["emoji"] }
unicode-xid = "0.2.0"
unicode-properties = { version = "0.1.4", default-features = false, features = ["emoji"] }
unicode-ident = "1.0.22"

[dev-dependencies]
expect-test = "1.4.0"
23 changes: 20 additions & 3 deletions compiler/rustc_lexer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,25 @@ use LiteralKind::*;
use TokenKind::*;
use cursor::EOF_CHAR;
pub use cursor::{Cursor, FrontmatterAllowed};
pub use unicode_ident::UNICODE_VERSION;
use unicode_properties::UnicodeEmoji;
pub use unicode_xid::UNICODE_VERSION as UNICODE_XID_VERSION;

// Make sure that the Unicode version of the dependencies is the same.
const _: () = {
let properties = unicode_properties::UNICODE_VERSION;
let ident = unicode_ident::UNICODE_VERSION;

if properties.0 != ident.0 as u64
|| properties.1 != ident.1 as u64
|| properties.2 != ident.2 as u64
{
panic!(
"unicode-properties and unicode-ident must use the same Unicode version, \
`unicode_properties::UNICODE_VERSION` and `unicode_ident::UNICODE_VERSION` are \
different."
);
}
};

/// Parsed token.
/// It doesn't contain information about data that has been parsed,
Expand Down Expand Up @@ -370,14 +387,14 @@ pub fn is_horizontal_whitespace(c: char) -> bool {
/// a formal definition of valid identifier name.
pub fn is_id_start(c: char) -> bool {
// This is XID_Start OR '_' (which formally is not a XID_Start).
c == '_' || unicode_xid::UnicodeXID::is_xid_start(c)
c == '_' || unicode_ident::is_xid_start(c)
}

/// True if `c` is valid as a non-first character of an identifier.
/// See [Rust language reference](https://doc.rust-lang.org/reference/identifiers.html) for
/// a formal definition of valid identifier name.
pub fn is_id_continue(c: char) -> bool {
unicode_xid::UnicodeXID::is_xid_continue(c)
unicode_ident::is_xid_continue(c)
}

/// The passed string is lexically an identifier.
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_middle/src/mir/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1896,7 +1896,8 @@ fn pretty_print_const_value_tcx<'tcx>(
// Aggregates, printed as array/tuple/struct/variant construction syntax.
//
// NB: the `has_non_region_param` check ensures that we can use
// the `destructure_const` query with an empty `ty::ParamEnv` without
// the `try_destructure_mir_constant_for_user_output ` query with
// an empty `TypingEnv::fully_monomorphized` without
// introducing ICEs (e.g. via `layout_of`) from missing bounds.
// E.g. `transmute([0usize; 2]): (u8, *mut T)` needs to know `T: Sized`
// to be able to destructure the tuple into `(0u8, *mut T)`
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/query/erase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ tcx_lifetime! {
rustc_middle::ty::ClauseKind,
rustc_middle::ty::ClosureTypeInfo,
rustc_middle::ty::Const,
rustc_middle::ty::DestructuredConst,
rustc_middle::ty::DestructuredAdtConst,
rustc_middle::ty::ExistentialTraitRef,
rustc_middle::ty::FnSig,
rustc_middle::ty::GenericArg,
Expand Down
6 changes: 0 additions & 6 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1408,12 +1408,6 @@ rustc_queries! {
desc { "converting type-level constant value to MIR constant value"}
}

/// Destructures array, ADT or tuple constants into the constants
/// of their fields.
query destructure_const(key: ty::Const<'tcx>) -> ty::DestructuredConst<'tcx> {
desc { "destructuring type level constant"}
}

// FIXME get rid of this with valtrees
query lit_to_const(
key: LitToConstInput<'tcx>
Expand Down
21 changes: 21 additions & 0 deletions compiler/rustc_middle/src/ty/consts/valtree.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::fmt;
use std::ops::Deref;

use rustc_abi::{FIRST_VARIANT, VariantIdx};
use rustc_data_structures::intern::Interned;
use rustc_hir::def::Namespace;
use rustc_macros::{
Expand Down Expand Up @@ -189,6 +190,26 @@ impl<'tcx> Value<'tcx> {
ValTreeKind::Leaf(_) => None,
}
}

/// Destructures array, ADT or tuple constants into the constants
/// of their fields.
pub fn destructure_adt_const(&self) -> ty::DestructuredAdtConst<'tcx> {
let fields = self.to_branch();

let (variant, fields) = match self.ty.kind() {
ty::Adt(def, _) if def.variants().is_empty() => {
bug!("unreachable")
}
ty::Adt(def, _) if def.is_enum() => {
let (head, rest) = fields.split_first().unwrap();
(VariantIdx::from_u32(head.to_leaf().to_u32()), rest)
}
ty::Adt(_, _) => (FIRST_VARIANT, fields),
_ => bug!("destructure_adt_const called on non-ADT type: {:?}", self.ty),
};

ty::DestructuredAdtConst { variant, fields }
}
}

impl<'tcx> rustc_type_ir::inherent::ValueConst<TyCtxt<'tcx>> for Value<'tcx> {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2331,8 +2331,8 @@ impl<'tcx> fmt::Debug for SymbolName<'tcx> {

/// The constituent parts of a type level constant of kind ADT or array.
#[derive(Copy, Clone, Debug, HashStable)]
pub struct DestructuredConst<'tcx> {
pub variant: Option<VariantIdx>,
pub struct DestructuredAdtConst<'tcx> {
pub variant: VariantIdx,
pub fields: &'tcx [ty::Const<'tcx>],
}

Expand Down
89 changes: 44 additions & 45 deletions compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1919,66 +1919,65 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
self.pretty_print_byte_str(bytes)?;
return Ok(());
}
// Aggregates, printed as array/tuple/struct/variant construction syntax.
(ty::ValTreeKind::Branch(_), ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) => {
let contents = self.tcx().destructure_const(ty::Const::new_value(
self.tcx(),
cv.valtree,
cv.ty,
));
let fields = contents.fields.iter().copied();
(ty::ValTreeKind::Branch(fields), ty::Array(..) | ty::Tuple(..)) => {
let fields_iter = fields.iter().copied();

match *cv.ty.kind() {
ty::Array(..) => {
write!(self, "[")?;
self.comma_sep(fields)?;
self.comma_sep(fields_iter)?;
write!(self, "]")?;
}
ty::Tuple(..) => {
write!(self, "(")?;
self.comma_sep(fields)?;
if contents.fields.len() == 1 {
self.comma_sep(fields_iter)?;
if fields.len() == 1 {
write!(self, ",")?;
}
write!(self, ")")?;
}
ty::Adt(def, _) if def.variants().is_empty() => {
self.typed_value(
|this| {
write!(this, "unreachable()")?;
Ok(())
},
|this| this.print_type(cv.ty),
": ",
)?;
}
ty::Adt(def, args) => {
let variant_idx =
contents.variant.expect("destructed const of adt without variant idx");
let variant_def = &def.variant(variant_idx);
self.pretty_print_value_path(variant_def.def_id, args)?;
match variant_def.ctor_kind() {
Some(CtorKind::Const) => {}
Some(CtorKind::Fn) => {
write!(self, "(")?;
self.comma_sep(fields)?;
write!(self, ")")?;
}
None => {
write!(self, " {{ ")?;
let mut first = true;
for (field_def, field) in iter::zip(&variant_def.fields, fields) {
if !first {
write!(self, ", ")?;
}
write!(self, "{}: ", field_def.name)?;
field.print(self)?;
first = false;
_ => unreachable!(),
}
return Ok(());
}
(ty::ValTreeKind::Branch(_), ty::Adt(def, args)) => {
let contents = cv.destructure_adt_const();
let fields = contents.fields.iter().copied();

if def.variants().is_empty() {
self.typed_value(
|this| {
write!(this, "unreachable()")?;
Ok(())
},
|this| this.print_type(cv.ty),
": ",
)?;
} else {
let variant_idx = contents.variant;
let variant_def = &def.variant(variant_idx);
self.pretty_print_value_path(variant_def.def_id, args)?;
match variant_def.ctor_kind() {
Some(CtorKind::Const) => {}
Some(CtorKind::Fn) => {
write!(self, "(")?;
self.comma_sep(fields)?;
write!(self, ")")?;
}
None => {
write!(self, " {{ ")?;
let mut first = true;
for (field_def, field) in iter::zip(&variant_def.fields, fields) {
if !first {
write!(self, ", ")?;
}
write!(self, " }}")?;
write!(self, "{}: ", field_def.name)?;
field.print(self)?;
first = false;
}
write!(self, " }}")?;
}
}
_ => unreachable!(),
}
return Ok(());
}
Expand Down
Loading
Loading