From 603b80f0873a8e8c3cf4a9ae247813b0b9b69346 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 10 Apr 2026 12:17:13 -0400 Subject: [PATCH 01/59] Ensure Send/Sync is not implemented for std::env::Vars{,Os} On some platforms, it looks like these are not currently Send/Sync. We have a negative impl in env/common.rs. This is a breaking change on a bunch of targets, but it makes it less likely that someone unintentionally/accidentally depends on this. This is a potentially partial list but should be fairly complete: aarch64-unknown-none, aarch64-unknown-none-softfloat, armv7a-none-eabi, armv7a-none-eabihf, armv7r-none-eabi, armv7r-none-eabihf, armv8r-none-eabihf, loongarch64-unknown-none, loongarch64-unknown-none-softfloat, nvptx64-nvidia-cuda, riscv32i-unknown-none-elf, riscv32im-unknown-none-elf, riscv32imac-unknown-none-elf, riscv32imafc-unknown-none-elf, riscv32imc-unknown-none-elf, riscv64gc-unknown-none-elf, riscv64imac-unknown-none-elf, s390x-unknown-none-softfloat, thumbv6m-none-eabi, thumbv7a-none-eabi, thumbv7a-none-eabihf, thumbv7em-none-eabi, thumbv7em-none-eabihf, thumbv7m-none-eabi, thumbv7r-none-eabi, thumbv7r-none-eabihf, thumbv8m.base-none-eabi, thumbv8m.main-none-eabi, thumbv8m.main-none-eabihf, thumbv8r-none-eabihf, wasm32-unknown-unknown, wasm32v1-none, x86_64-unknown-none --- library/std/src/env.rs | 6 ++++++ library/std/src/sys/env/common.rs | 3 --- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/library/std/src/env.rs b/library/std/src/env.rs index d3e4417656e9a..697e0b4b68f13 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -101,6 +101,12 @@ pub struct VarsOs { inner: env_imp::Env, } +#[stable(feature = "env_vars_unimpl_send_sync", since = "CURRENT_RUSTC_VERSION")] +impl !Send for VarsOs {} + +#[stable(feature = "env_vars_unimpl_send_sync", since = "CURRENT_RUSTC_VERSION")] +impl !Sync for VarsOs {} + /// Returns an iterator of (variable, value) pairs of strings, for all the /// environment variables of the current process. /// diff --git a/library/std/src/sys/env/common.rs b/library/std/src/sys/env/common.rs index 87e86e2947fad..d620c8b4acdd9 100644 --- a/library/std/src/sys/env/common.rs +++ b/library/std/src/sys/env/common.rs @@ -17,9 +17,6 @@ impl fmt::Debug for Env { } } -impl !Send for Env {} -impl !Sync for Env {} - impl Iterator for Env { type Item = (OsString, OsString); fn next(&mut self) -> Option<(OsString, OsString)> { From d780821bd3391e599bbd1189f0698d25ce42410d Mon Sep 17 00:00:00 2001 From: Shina <53410646+s7tya@users.noreply.github.com> Date: Wed, 27 May 2026 18:18:39 +0900 Subject: [PATCH 02/59] Ensure inferred let pattern types are well-formed --- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 10 +++ tests/ui/wf/let-pat-inferred-non-wf.rs | 58 +++++++++++++++++ tests/ui/wf/let-pat-inferred-non-wf.stderr | 62 +++++++++++++++++++ 3 files changed, 130 insertions(+) create mode 100644 tests/ui/wf/let-pat-inferred-non-wf.rs create mode 100644 tests/ui/wf/let-pat-inferred-non-wf.stderr diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index d62ba9cf804eb..d6f6b0843018f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -902,6 +902,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Type check the pattern. Override if necessary to avoid knock-on errors. self.check_pat_top(decl.pat, decl_ty, ty_span, origin_expr, Some(decl.origin)); + if decl.ty.is_none() + && decl.init.is_none() + && !matches!(decl.pat.kind, hir::PatKind::Binding(.., None) | hir::PatKind::Wild) + { + self.register_wf_obligation( + decl_ty.into(), + decl.pat.span, + ObligationCauseCode::WellFormed(None), + ); + } let pat_ty = self.node_ty(decl.pat.hir_id); self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, pat_ty); diff --git a/tests/ui/wf/let-pat-inferred-non-wf.rs b/tests/ui/wf/let-pat-inferred-non-wf.rs new file mode 100644 index 0000000000000..ab032161ebb51 --- /dev/null +++ b/tests/ui/wf/let-pat-inferred-non-wf.rs @@ -0,0 +1,58 @@ +// Regression test for https://github.com/rust-lang/rust/issues/150040 +// When a `let PAT;` has no explicit type, later assignments can infer a non-well-formed +// pattern type such as `[str; 2]` or `(str, i32)`. We must reject those array and tuple +// patterns instead of accepting the invalid type or causing ICE. + +#![allow(unused)] + +struct S(T); + +fn should_fail_1() { + let ref y @ [ref x, _]; //~ ERROR E0277 + x = ""; +} + +fn should_fail_2() { + let [ref x]; //~ ERROR E0277 + x = ""; +} + +fn should_fail_3() { + let [[ref x], [_, y @ ..]]; //~ ERROR E0277 + x = ""; + y = []; +} + +fn should_fail_4() { + let [(ref a, b), x]; //~ ERROR E0277 + a = ""; + b = 5; +} + +fn should_fail_5() { + let (ref a, b); //~ ERROR E0277 + a = ""; + b = 5; +} + +fn should_fail_6() { + let [S(ref x)]; //~ ERROR E0277 + x = ""; +} + +fn should_pass_1() { + let ref x; + x = ""; +} + +fn should_pass_2() { + let ref y @ (ref x,); + x = ""; +} + +fn should_pass_3() { + let S(ref x); + x = ""; +} + +fn main() {} diff --git a/tests/ui/wf/let-pat-inferred-non-wf.stderr b/tests/ui/wf/let-pat-inferred-non-wf.stderr new file mode 100644 index 0000000000000..1c524a22b432b --- /dev/null +++ b/tests/ui/wf/let-pat-inferred-non-wf.stderr @@ -0,0 +1,62 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/let-pat-inferred-non-wf.rs:11:9 + | +LL | let ref y @ [ref x, _]; + | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: slice and array elements must have `Sized` type + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/let-pat-inferred-non-wf.rs:16:9 + | +LL | let [ref x]; + | ^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: slice and array elements must have `Sized` type + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/let-pat-inferred-non-wf.rs:21:9 + | +LL | let [[ref x], [_, y @ ..]]; + | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: slice and array elements must have `Sized` type + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/let-pat-inferred-non-wf.rs:27:9 + | +LL | let [(ref a, b), x]; + | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: only the last element of a tuple may have a dynamically sized type + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/let-pat-inferred-non-wf.rs:33:9 + | +LL | let (ref a, b); + | ^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: only the last element of a tuple may have a dynamically sized type + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/let-pat-inferred-non-wf.rs:39:9 + | +LL | let [S(ref x)]; + | ^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `S`, the trait `Sized` is not implemented for `str` +note: required because it appears within the type `S` + --> $DIR/let-pat-inferred-non-wf.rs:8:8 + | +LL | struct S(T); + | ^ + = note: slice and array elements must have `Sized` type + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`. From 7859a29ba5c106764d063664450b9deddeb28689 Mon Sep 17 00:00:00 2001 From: Haoran Wang Date: Sun, 31 May 2026 21:25:25 +0800 Subject: [PATCH 03/59] Only suggest reborrowing a moved value where the reborrow is valid When a `&mut`-typed value is moved out of a closure via a `for` loop's implicit `into_iter`, borrowck suggests "consider creating a fresh reborrow" (`&mut *place`) with `Applicability::MachineApplicable`. For a value captured by an `Fn` closure -- which holds its captures through `&self` -- that place cannot be borrowed mutably (E0596), so applying the machine-applicable suggestion produces code that does not compile. Gate the suggestion on borrowck's own `is_mutable` check for the reborrowed place, so it is only offered where `&mut *place` is valid: suppressed for `Fn`-closure captures, still offered for `FnMut` closures and ordinary `&mut` locals. --- .../rustc_borrowck/src/diagnostics/mod.rs | 11 +++- ...n-closure-move-capture-no-reborrow-sugg.rs | 46 ++++++++++++++++ ...osure-move-capture-no-reborrow-sugg.stderr | 53 +++++++++++++++++++ 3 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 tests/ui/borrowck/fn-closure-move-capture-no-reborrow-sugg.rs create mode 100644 tests/ui/borrowck/fn-closure-move-capture-no-reborrow-sugg.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 248396ba9849b..8547f7593232e 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -34,6 +34,7 @@ use tracing::debug; use super::MirBorrowckCtxt; use super::borrow_set::BorrowData; +use crate::LocalMutationIsAllowed; use crate::constraints::OutlivesConstraint; use crate::nll::ConstraintDescription; use crate::session_diagnostics::{ @@ -1426,11 +1427,19 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if let ty::Ref(_, _, hir::Mutability::Mut) = moved_place.ty(self.body, self.infcx.tcx).ty.kind() { + // The `&mut *place` reborrow suggestion is `MachineApplicable`, so + // only offer it where `*place` can be borrowed mutably: a value + // captured by an `Fn` closure (held via `&self`) cannot, and the + // suggestion would otherwise fail to compile with E0596. + let reborrow_place = self.infcx.tcx.mk_place_deref(moved_place); + let reborrow_is_valid = self + .is_mutable(reborrow_place.as_ref(), LocalMutationIsAllowed::No) + .is_ok(); // Suggest `reborrow` in other place for following situations: // 1. If we are in a loop this will be suggested later. // 2. If the moved value is a mut reference, it is used in a // generic function and the corresponding arg's type is generic param. - if !is_loop_move && !has_suggest_reborrow { + if !is_loop_move && !has_suggest_reborrow && reborrow_is_valid { self.suggest_reborrow( err, move_span.shrink_to_lo(), diff --git a/tests/ui/borrowck/fn-closure-move-capture-no-reborrow-sugg.rs b/tests/ui/borrowck/fn-closure-move-capture-no-reborrow-sugg.rs new file mode 100644 index 0000000000000..4f0c65dd5bd2a --- /dev/null +++ b/tests/ui/borrowck/fn-closure-move-capture-no-reborrow-sugg.rs @@ -0,0 +1,46 @@ +//@ edition: 2021 +//@ compile-flags: --crate-type=lib + +// Regression test for https://github.com/rust-lang/rust/issues/150175. +// +// Moving a `&mut`-typed captured variable out of a closure (here through the +// implicit `into_iter` of a `for` loop) is an E0507. The "consider creating a +// fresh reborrow" suggestion rewrites the move site to `&mut *foos`, but that +// only compiles when the capture can be borrowed mutably there: +// +// * an `Fn` closure holds its captures through `&self`, so `&mut *foos` +// cannot be borrowed (E0596). The suggestion is `MachineApplicable`, so +// offering it here produces code that does not compile -- it must be +// suppressed (this is the bug). +// * an `FnMut` closure holds its captures through `&mut self`, so the +// reborrow is valid and the suggestion must still be offered. + +pub struct Foo; + +pub fn in_fn Result<(), ()>>(f: F) -> Result<(), ()> { + f() +} + +pub fn in_fn_mut Result<(), ()>>(mut f: F) -> Result<(), ()> { + f() +} + +// `Fn` closure: a mutable reborrow is impossible, so no suggestion is offered. +pub fn fn_closure(foos: &mut [&mut Foo]) -> Result<(), ()> { + in_fn(|| { + for _ in foos { + //~^ ERROR cannot move out of `foos`, a captured variable in an `Fn` closure + } + Ok(()) + }) +} + +// `FnMut` closure: a mutable reborrow is valid, so the suggestion is offered. +pub fn fn_mut_closure(foos: &mut [&mut Foo]) -> Result<(), ()> { + in_fn_mut(|| { + for _ in foos { + //~^ ERROR cannot move out of `foos`, a captured variable in an `FnMut` closure + } + Ok(()) + }) +} diff --git a/tests/ui/borrowck/fn-closure-move-capture-no-reborrow-sugg.stderr b/tests/ui/borrowck/fn-closure-move-capture-no-reborrow-sugg.stderr new file mode 100644 index 0000000000000..e31bae3a4ddf6 --- /dev/null +++ b/tests/ui/borrowck/fn-closure-move-capture-no-reborrow-sugg.stderr @@ -0,0 +1,53 @@ +error[E0507]: cannot move out of `foos`, a captured variable in an `Fn` closure + --> $DIR/fn-closure-move-capture-no-reborrow-sugg.rs:31:18 + | +LL | pub fn fn_closure(foos: &mut [&mut Foo]) -> Result<(), ()> { + | ---- --------------- move occurs because `foos` has type `&mut [&mut Foo]`, which does not implement the `Copy` trait + | | + | captured outer variable +LL | in_fn(|| { + | -- captured by this `Fn` closure +LL | for _ in foos { + | ^^^^ + | | + | `foos` moved due to this implicit call to `.into_iter()` + | `foos` is moved here + | +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once + --> $DIR/fn-closure-move-capture-no-reborrow-sugg.rs:20:17 + | +LL | pub fn in_fn Result<(), ()>>(f: F) -> Result<(), ()> { + | ^^^^^^^^^^^^^^^^^^^^^^ +note: `into_iter` takes ownership of the receiver `self`, which moves `foos` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + +error[E0507]: cannot move out of `foos`, a captured variable in an `FnMut` closure + --> $DIR/fn-closure-move-capture-no-reborrow-sugg.rs:41:18 + | +LL | pub fn fn_mut_closure(foos: &mut [&mut Foo]) -> Result<(), ()> { + | ---- --------------- move occurs because `foos` has type `&mut [&mut Foo]`, which does not implement the `Copy` trait + | | + | captured outer variable +LL | in_fn_mut(|| { + | -- captured by this `FnMut` closure +LL | for _ in foos { + | ^^^^ + | | + | `foos` moved due to this implicit call to `.into_iter()` + | `foos` is moved here + | +help: `Fn` and `FnMut` closures require captured values to be able to be consumed multiple times, but `FnOnce` closures may consume them only once + --> $DIR/fn-closure-move-capture-no-reborrow-sugg.rs:24:21 + | +LL | pub fn in_fn_mut Result<(), ()>>(mut f: F) -> Result<(), ()> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: `into_iter` takes ownership of the receiver `self`, which moves `foos` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL +help: consider creating a fresh reborrow of `foos` here + | +LL | for _ in &mut *foos { + | ++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0507`. From 9633071bf1122e873941e4c8ec49b9af9b5b6e84 Mon Sep 17 00:00:00 2001 From: lokirithm Date: Sun, 31 May 2026 19:47:00 +0530 Subject: [PATCH 04/59] Don't suggest wrong unwrap expect --- .../src/fn_ctxt/suggestions.rs | 13 +++++++++ .../dont-suggest-wrong-expect-suggestion.rs | 19 +++++++++++++ ...ont-suggest-wrong-expect-suggestion.stderr | 27 +++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 tests/ui/destructuring-assignment/dont-suggest-wrong-expect-suggestion.rs create mode 100644 tests/ui/destructuring-assignment/dont-suggest-wrong-expect-suggestion.stderr diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index afd5356d5a1e7..ea66889ec731b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -2218,6 +2218,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Ty<'tcx>, found: Ty<'tcx>, ) -> bool { + // don't suggest missing `.expect()` or `?` in destructuring assignments LHS. + // If the immediate parent is an Assign Expr, and the LHS and the RHS of that Expr + // overlap with each other, it's guaranteed that the expression came from desugaring + // a destructuring assignment. + let parent_node = self.tcx.parent_hir_node(expr.hir_id); + if let hir::Node::Expr(e) = parent_node + && let hir::ExprKind::Assign(lhs, rhs, _) = e.kind + && rhs.hir_id == expr.hir_id + && lhs.span.overlaps(rhs.span) + { + return false; + } + let ty::Adt(adt, args) = found.kind() else { return false; }; diff --git a/tests/ui/destructuring-assignment/dont-suggest-wrong-expect-suggestion.rs b/tests/ui/destructuring-assignment/dont-suggest-wrong-expect-suggestion.rs new file mode 100644 index 0000000000000..5b345606ec7cd --- /dev/null +++ b/tests/ui/destructuring-assignment/dont-suggest-wrong-expect-suggestion.rs @@ -0,0 +1,19 @@ +//! regression test for + +struct NamedStruct { + opt_field: Option, + res_field: Result, +} + +fn main() { + let a: usize; + let b: usize; + + NamedStruct { + opt_field: a, //~ ERROR mismatched types + res_field: b, //~ ERROR mismatched types + } = NamedStruct { + opt_field: Some(0), + res_field: Ok(42_usize), + }; +} diff --git a/tests/ui/destructuring-assignment/dont-suggest-wrong-expect-suggestion.stderr b/tests/ui/destructuring-assignment/dont-suggest-wrong-expect-suggestion.stderr new file mode 100644 index 0000000000000..699d0b37ff4e7 --- /dev/null +++ b/tests/ui/destructuring-assignment/dont-suggest-wrong-expect-suggestion.stderr @@ -0,0 +1,27 @@ +error[E0308]: mismatched types + --> $DIR/dont-suggest-wrong-expect-suggestion.rs:13:20 + | +LL | let a: usize; + | ----- expected due to this type +... +LL | opt_field: a, + | ^ expected `usize`, found `Option` + | + = note: expected type `usize` + found enum `Option` + +error[E0308]: mismatched types + --> $DIR/dont-suggest-wrong-expect-suggestion.rs:14:20 + | +LL | let b: usize; + | ----- expected due to this type +... +LL | res_field: b, + | ^ expected `usize`, found `Result` + | + = note: expected type `usize` + found enum `Result` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. From 23144573a871726bca6e271ff80168cf5acba640 Mon Sep 17 00:00:00 2001 From: steamproof <93405617+pbkx@users.noreply.github.com> Date: Sun, 31 May 2026 20:10:17 -0700 Subject: [PATCH 05/59] borrowck: avoid ICE describing fields on generic params --- .../rustc_borrowck/src/diagnostics/mod.rs | 1 + ...-describe-field-generic-param-owned-box.rs | 56 +++++++++++++++++++ ...cribe-field-generic-param-owned-box.stderr | 9 +++ 3 files changed, 66 insertions(+) create mode 100644 tests/ui/borrowck/borrowck-describe-field-generic-param-owned-box.rs create mode 100644 tests/ui/borrowck/borrowck-describe-field-generic-param-owned-box.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 248396ba9849b..0b21ab419886b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -525,6 +525,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ty::Array(ty, _) | ty::Slice(ty) => { self.describe_field_from_ty(ty, field, variant_index, including_tuple_field) } + ty::Param(_) => Some(field.index().to_string()), ty::Closure(def_id, _) | ty::Coroutine(def_id, _) => { // We won't be borrowck'ing here if the closure came from another crate, // so it's safe to call `expect_local`. diff --git a/tests/ui/borrowck/borrowck-describe-field-generic-param-owned-box.rs b/tests/ui/borrowck/borrowck-describe-field-generic-param-owned-box.rs new file mode 100644 index 0000000000000..95a34f173fbd3 --- /dev/null +++ b/tests/ui/borrowck/borrowck-describe-field-generic-param-owned-box.rs @@ -0,0 +1,56 @@ +// Regression test for #155344. +// Borrowck diagnostics should not ICE when describing a field access on a generic parameter. + +//@ edition: 2024 + +#![crate_type = "lib"] +#![feature(no_core, lang_items)] +#![no_core] + +#[lang = "pointee_sized"] +pub trait PointeeSized {} + +#[lang = "meta_sized"] +pub trait MetaSized: PointeeSized {} + +#[lang = "sized"] +pub trait Sized: MetaSized {} + +#[lang = "legacy_receiver"] +pub trait LegacyReceiver {} + +impl LegacyReceiver for &T {} +impl LegacyReceiver for &mut T {} + +#[lang = "copy"] +pub trait Copy {} + +impl Copy for *mut () {} + +#[lang = "drop"] +pub trait Drop { + fn drop(&mut self); +} + +unsafe extern "C" { + fn free(_: *mut ()); +} + +unsafe fn transmute(_: T) -> U { + loop {} +} + +#[repr(transparent)] +pub struct NonNull(pub *const T); + +#[lang = "owned_box"] +pub struct Box(NonNull, A); + +impl Drop for Box { + fn drop(&mut self) { + unsafe { + free(transmute::, *mut _>(self.0)); + //~^ ERROR cannot move out of `self.0` which is behind a mutable reference + } + } +} diff --git a/tests/ui/borrowck/borrowck-describe-field-generic-param-owned-box.stderr b/tests/ui/borrowck/borrowck-describe-field-generic-param-owned-box.stderr new file mode 100644 index 0000000000000..00fc198bac231 --- /dev/null +++ b/tests/ui/borrowck/borrowck-describe-field-generic-param-owned-box.stderr @@ -0,0 +1,9 @@ +error[E0507]: cannot move out of `self.0` which is behind a mutable reference + --> $DIR/borrowck-describe-field-generic-param-owned-box.rs:52:50 + | +LL | free(transmute::, *mut _>(self.0)); + | ^^^^^^ move occurs because `self.0` has type `NonNull`, which does not implement the `Copy` trait + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0507`. From b5738418aad4ff971ff6005d91e4bd810ac94838 Mon Sep 17 00:00:00 2001 From: Dnreikronos Date: Mon, 1 Jun 2026 23:23:45 -0300 Subject: [PATCH 06/59] Use a placeholder self type for escaping dyn principals in WF WF-checking walks through higher-ranked binders without instantiating them, so a `dyn Trait` nested inside a `for<'a>` bound reaches the `ty::Dynamic` arm of `WfPredicates::visit_ty` while still carrying escaping bound vars. Feeding that type into `ExistentialTraitRef::with_self_ty` violated its no-escaping-self precondition and tripped the assertion that guards it. The trait ref built there is only used to read off `ConstArgHasType` clauses, which constrain the trait's own const arguments and never mention the `Self` type. Substitute a fresh placeholder self type when the real one escapes: the assertion holds and the const-argument check is still performed. Re-enable the `with_self_ty` debug assertion now that its precondition is upheld. --- compiler/rustc_trait_selection/src/traits/wf.rs | 17 ++++++++++++++++- compiler/rustc_type_ir/src/predicate.rs | 6 +----- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index a2143a7462a84..e226c553e6f98 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -974,7 +974,22 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { // go through an anon const still have their types checked. // // See also: https://rustc-dev-guide.rust-lang.org/const-generics.html - let args = principal.skip_binder().with_self_ty(self.tcx(), t).args; + // + // We only use this trait ref to read off its `ConstArgHasType` clauses, + // which constrain the trait's own const arguments and never mention the + // `Self` type. The `with_self_ty` assertion forbids an escaping self type + // (those vars would be captured by the trait-ref binder), and `t` can carry + // escaping bound vars here because WF-checking walks through higher-ranked + // binders without instantiating them (e.g. a `dyn Trait` nested in a + // `for<'a>` bound). Since the self type is irrelevant to the clauses we + // keep, fall back to the dummy self type in that case rather than skipping + // the check entirely. + let self_ty = if t.has_escaping_bound_vars() { + tcx.types.trait_object_dummy_self + } else { + t + }; + let args = principal.skip_binder().with_self_ty(tcx, self_ty).args; let obligations = self.nominal_obligations(principal_def_id, args).into_iter().filter(|o| { let kind = o.predicate.kind().skip_binder(); diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index 59c5f69463b38..30264943459f7 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -443,12 +443,8 @@ impl ExistentialTraitRef { /// Therefore, you must specify *some* self type to perform the conversion. /// A common choice is the trait object type itself or some kind of dummy type. pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> TraitRef { - // FIXME(#157122): This assertion was accidentally commented out in refactoring PR #53816 - // back in 2018 but nowadays it can actually trigger. Either remove this - // comment entirely if the assertion is incorrect or uncomment it and fix - // the fallout! // otherwise the escaping vars would be captured by the binder - //debug_assert!(!self_ty.has_escaping_bound_vars()); + debug_assert!(!self_ty.has_escaping_bound_vars()); TraitRef::new(interner, self.def_id, [self_ty.into()].into_iter().chain(self.args.iter())) } From 0676d4ab7816f6892b34e092bbf7fbbf1cb3185b Mon Sep 17 00:00:00 2001 From: Dnreikronos Date: Mon, 1 Jun 2026 23:24:02 -0300 Subject: [PATCH 07/59] Add regression tests for WF-checking dyn in HRTB bounds One test covers the original ICE (a `dyn Trait` nested in a `for<'a>` bound, distilled from itertools). The other locks in that a const argument on such a nested `dyn` is still type-checked, so the placeholder-self-type fix cannot silently regress into dropping the `ConstArgHasType` check. --- .../wf/wf-dyn-in-hrtb-bound-const-mismatch.rs | 19 +++++++++++++ ...wf-dyn-in-hrtb-bound-const-mismatch.stderr | 14 ++++++++++ .../wf/wf-dyn-in-hrtb-bound-issue-157122.rs | 28 +++++++++++++++++++ 3 files changed, 61 insertions(+) create mode 100644 tests/ui/wf/wf-dyn-in-hrtb-bound-const-mismatch.rs create mode 100644 tests/ui/wf/wf-dyn-in-hrtb-bound-const-mismatch.stderr create mode 100644 tests/ui/wf/wf-dyn-in-hrtb-bound-issue-157122.rs diff --git a/tests/ui/wf/wf-dyn-in-hrtb-bound-const-mismatch.rs b/tests/ui/wf/wf-dyn-in-hrtb-bound-const-mismatch.rs new file mode 100644 index 0000000000000..db3e36224367d --- /dev/null +++ b/tests/ui/wf/wf-dyn-in-hrtb-bound-const-mismatch.rs @@ -0,0 +1,19 @@ +// Companion to #157122 / `wf-dyn-in-hrtb-bound-issue-157122.rs`. +// +// That test fixes an ICE in `WfPredicates::visit_ty` where a `dyn Trait` nested +// inside a `for<'a>` binder reached `ExistentialTraitRef::with_self_ty` with an +// escaping self type. The fix substitutes a placeholder self type for that case +// instead of skipping the block. Skipping would have been a silent regression: +// the block emits the `ConstArgHasType` obligation that type-checks a `dyn`'s +// const argument, so dropping it makes an ill-typed const argument compile. +// +// Here `B` has type `bool` but `HasConst` expects `const N: usize`, and the +// `dyn HasConst<'a, B>` carries the escaping late-bound `'a`. This must still be +// rejected, exactly as it is without the surrounding `for<'a>` binder. + +trait HasConst<'a, const N: usize> {} + +fn nested(_f: &dyn for<'a> Fn(&'a (), &'a dyn HasConst<'a, B>)) {} +//~^ ERROR the constant `B` is not of type `usize` + +fn main() {} diff --git a/tests/ui/wf/wf-dyn-in-hrtb-bound-const-mismatch.stderr b/tests/ui/wf/wf-dyn-in-hrtb-bound-const-mismatch.stderr new file mode 100644 index 0000000000000..317fbb5dcafe1 --- /dev/null +++ b/tests/ui/wf/wf-dyn-in-hrtb-bound-const-mismatch.stderr @@ -0,0 +1,14 @@ +error: the constant `B` is not of type `usize` + --> $DIR/wf-dyn-in-hrtb-bound-const-mismatch.rs:16:30 + | +LL | fn nested(_f: &dyn for<'a> Fn(&'a (), &'a dyn HasConst<'a, B>)) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool` + | +note: required by a const generic parameter in `HasConst` + --> $DIR/wf-dyn-in-hrtb-bound-const-mismatch.rs:14:20 + | +LL | trait HasConst<'a, const N: usize> {} + | ^^^^^^^^^^^^^^ required by this const generic parameter in `HasConst` + +error: aborting due to 1 previous error + diff --git a/tests/ui/wf/wf-dyn-in-hrtb-bound-issue-157122.rs b/tests/ui/wf/wf-dyn-in-hrtb-bound-issue-157122.rs new file mode 100644 index 0000000000000..8fca3828efeb1 --- /dev/null +++ b/tests/ui/wf/wf-dyn-in-hrtb-bound-issue-157122.rs @@ -0,0 +1,28 @@ +//@ check-pass + +// Regression test for #157122. +// +// When WF-checking a type, the visitor recurses through higher-ranked binders +// without instantiating them, so a `dyn Trait` nested inside a `for<'a>` binder +// reaches the `ty::Dynamic` arm of `WfPredicates::visit_ty` while still carrying +// escaping bound vars. Building the principal trait ref there via +// `ExistentialTraitRef::with_self_ty` fed that escaping self type straight into +// `debug_assert!(!self_ty.has_escaping_bound_vars())`, causing an ICE. We now +// substitute a placeholder self type for the escaping case (the self type is +// irrelevant to the `ConstArgHasType` clauses this code reads off), so the +// assertion holds and the const-argument check is still performed -- see +// `wf-dyn-in-hrtb-bound-const-mismatch.rs` for the latter. Distilled from +// `itertools`'s `FormatWith` `Display` impl. + +use std::fmt; + +fn call(mut f: F) +where + F: FnMut(&mut dyn FnMut(&dyn fmt::Display) -> fmt::Result) -> fmt::Result, +{ + let _ = f(&mut |_disp: &dyn fmt::Display| Ok(())); +} + +fn main() { + call(|cb| cb(&0i32)); +} From de37dfd1fb8ca66662d4c571b4804ea2dbbe01ef Mon Sep 17 00:00:00 2001 From: Peter Hall Date: Tue, 6 Feb 2024 13:49:41 +0000 Subject: [PATCH 08/59] Add or_try_* variants for HashMap Entry API Doc typo --- library/std/src/collections/hash/map.rs | 76 +++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 5 deletions(-) diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 887efd12f550f..3eca5b6f974b6 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -2538,9 +2538,42 @@ impl<'a, K, V, A: Allocator> Entry<'a, K, V, A> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn or_insert_with V>(self, default: F) -> &'a mut V { + self.or_try_insert_with(|| Result::<_, !>::Ok(default())).unwrap() + } + + /// Ensures a value is in the entry by inserting the result of a fallible default function + /// if empty, and returns a mutable reference to the value in the entry. + /// + /// This method works identically to [`or_insert_with`] except that the default function + /// should return a `Result` and, in the case of an error, the error is propagated. + /// + /// [`or_insert_with`]: Self::or_insert_with + /// + /// # Examples + /// + /// ``` + /// # #![feature(try_entry)] + /// # fn main() -> Result<(), std::num::ParseIntError> { + /// use std::collections::HashMap; + /// + /// let mut map: HashMap<&str, usize> = HashMap::new(); + /// let value = "42"; + /// + /// map.entry("poneyland").or_try_insert_with(|| value.parse())?; + /// + /// assert_eq!(map["poneyland"], 42); + /// # Ok(()) + /// # } + /// ``` + #[inline] + #[unstable(feature = "try_entry", issue = "none")] + pub fn or_try_insert_with Result, E>( + self, + default: F, + ) -> Result<&'a mut V, E> { match self { - Occupied(entry) => entry.into_mut(), - Vacant(entry) => entry.insert(default()), + Occupied(entry) => Ok(entry.into_mut()), + Vacant(entry) => Ok(entry.insert(default()?)), } } @@ -2565,11 +2598,44 @@ impl<'a, K, V, A: Allocator> Entry<'a, K, V, A> { #[inline] #[stable(feature = "or_insert_with_key", since = "1.50.0")] pub fn or_insert_with_key V>(self, default: F) -> &'a mut V { + self.or_try_insert_with_key(|k| Result::<_, !>::Ok(default(k))).unwrap() + } + + /// Ensures a value is in the entry by inserting, if empty, the result of the default function. + /// This method allows for generating key-derived values for insertion by providing the default + /// function a reference to the key that was moved during the `entry(key)` method call. + /// + /// This method works identically to [`or_insert_with_key`] except that the default function + /// should return a `Result` and, in the case of an error, the error is propagated. + /// + /// [`or_insert_with_key`]: Self::or_insert_with_key + /// + /// # Examples + /// + /// ``` + /// # #![feature(try_entry)] + /// # fn main() -> Result<(), std::num::ParseIntError> { + /// use std::collections::HashMap; + /// + /// let mut map: HashMap<&str, usize> = HashMap::new(); + /// + /// map.entry("42").or_try_insert_with_key(|key| key.parse())?; + /// + /// assert_eq!(map["42"], 42); + /// # Ok(()) + /// # } + /// ``` + #[inline] + #[unstable(feature = "try_entry", issue = "none")] + pub fn or_try_insert_with_key Result, E>( + self, + default: F, + ) -> Result<&'a mut V, E> { match self { - Occupied(entry) => entry.into_mut(), + Occupied(entry) => Ok(entry.into_mut()), Vacant(entry) => { - let value = default(entry.key()); - entry.insert(value) + let value = default(entry.key())?; + Ok(entry.insert(value)) } } } From 92175ed50675228c14456d25658ceec1d319491b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 2 Jun 2026 09:13:38 +0200 Subject: [PATCH 09/59] platform support: add SNaN erratum to MIPS targets --- src/doc/rustc/src/platform-support.md | 38 +++++++++++++++------------ 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 26dd6b31b8991..b81e5becd7448 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -347,23 +347,23 @@ target | std | host | notes [`loongarch32-unknown-none-softfloat`](platform-support/loongarch-none.md) | * | | LoongArch32 Bare-metal (ILP32S ABI) [`m68k-unknown-linux-gnu`](platform-support/m68k-unknown-linux-gnu.md) | ? | | Motorola 680x0 Linux [`m68k-unknown-none-elf`](platform-support/m68k-unknown-none-elf.md) | | | Motorola 680x0 -`mips-unknown-linux-gnu` | ✓ | ✓ | MIPS Linux (kernel 4.4, glibc 2.23) -`mips-unknown-linux-musl` | ✓ | | MIPS Linux with musl 1.2.5 -`mips-unknown-linux-uclibc` | ✓ | | MIPS Linux with uClibc -[`mips64-openwrt-linux-musl`](platform-support/mips64-openwrt-linux-musl.md) | ? | | MIPS64 for OpenWrt Linux musl 1.2.5 -`mips64-unknown-linux-gnuabi64` | ✓ | ✓ | MIPS64 Linux, N64 ABI (kernel 4.4, glibc 2.23) -[`mips64-unknown-linux-muslabi64`](platform-support/mips64-unknown-linux-muslabi64.md) | ✓ | ✓ | MIPS64 Linux, N64 ABI, musl 1.2.5 -`mips64el-unknown-linux-gnuabi64` | ✓ | ✓ | MIPS64 (little endian) Linux, N64 ABI (kernel 4.4, glibc 2.23) -`mips64el-unknown-linux-muslabi64` | ✓ | | MIPS64 (little endian) Linux, N64 ABI, musl 1.2.5 -`mipsel-sony-psp` | * | | MIPS (LE) Sony PlayStation Portable (PSP) -[`mipsel-sony-psx`](platform-support/mipsel-sony-psx.md) | * | | MIPS (LE) Sony PlayStation 1 (PSX) -[`mipsel-unknown-linux-gnu`](platform-support/mipsel-unknown-linux-gnu.md) | ✓ | ✓ | MIPS (little endian) Linux (kernel 4.4, glibc 2.23) -`mipsel-unknown-linux-musl` | ✓ | | MIPS (little endian) Linux with musl 1.2.5 -`mipsel-unknown-linux-uclibc` | ✓ | | MIPS (LE) Linux with uClibc -[`mipsel-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | 32-bit MIPS (LE), requires mips32 cpu support -`mipsel-unknown-none` | * | | Bare MIPS (LE) softfloat -[`mips-mti-none-elf`](platform-support/mips-mti-none-elf.md) | * | | Bare MIPS32r2 (BE) softfloat -[`mipsel-mti-none-elf`](platform-support/mips-mti-none-elf.md) | * | | Bare MIPS32r2 (LE) softfloat +`mips-unknown-linux-gnu` | ✓ | ✓ | MIPS Linux (kernel 4.4, glibc 2.23) [^snan-inverted] +`mips-unknown-linux-musl` | ✓ | | MIPS Linux with musl 1.2.5 [^snan-inverted] +`mips-unknown-linux-uclibc` | ✓ | | MIPS Linux with uClibc [^snan-inverted] +[`mips64-openwrt-linux-musl`](platform-support/mips64-openwrt-linux-musl.md) | ? | | MIPS64 for OpenWrt Linux musl 1.2.5 [^snan-inverted] +`mips64-unknown-linux-gnuabi64` | ✓ | ✓ | MIPS64 Linux, N64 ABI (kernel 4.4, glibc 2.23) [^snan-inverted] +[`mips64-unknown-linux-muslabi64`](platform-support/mips64-unknown-linux-muslabi64.md) | ✓ | ✓ | MIPS64 Linux, N64 ABI, musl 1.2.5 [^snan-inverted] +`mips64el-unknown-linux-gnuabi64` | ✓ | ✓ | MIPS64 (little endian) Linux, N64 ABI (kernel 4.4, glibc 2.23) [^snan-inverted] +`mips64el-unknown-linux-muslabi64` | ✓ | | MIPS64 (little endian) Linux, N64 ABI, musl 1.2.5 [^snan-inverted] +`mipsel-sony-psp` | * | | MIPS (LE) Sony PlayStation Portable (PSP) [^snan-inverted] +[`mipsel-sony-psx`](platform-support/mipsel-sony-psx.md) | * | | MIPS (LE) Sony PlayStation 1 (PSX) [^snan-inverted] +[`mipsel-unknown-linux-gnu`](platform-support/mipsel-unknown-linux-gnu.md) | ✓ | ✓ | MIPS (little endian) Linux (kernel 4.4, glibc 2.23) [^snan-inverted] +`mipsel-unknown-linux-musl` | ✓ | | MIPS (little endian) Linux with musl 1.2.5 [^snan-inverted] +`mipsel-unknown-linux-uclibc` | ✓ | | MIPS (LE) Linux with uClibc [^snan-inverted] +[`mipsel-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | 32-bit MIPS (LE), requires mips32 cpu support [^snan-inverted] +`mipsel-unknown-none` | * | | Bare MIPS (LE) softfloat [^snan-inverted] +[`mips-mti-none-elf`](platform-support/mips-mti-none-elf.md) | * | | Bare MIPS32r2 (BE) softfloat [^snan-inverted] +[`mipsel-mti-none-elf`](platform-support/mips-mti-none-elf.md) | * | | Bare MIPS32r2 (LE) softfloat [^snan-inverted] [`mipsisa32r6-unknown-linux-gnu`](platform-support/mips-release-6.md) | ? | | 32-bit MIPS Release 6 Big Endian [`mipsisa32r6el-unknown-linux-gnu`](platform-support/mips-release-6.md) | ? | | 32-bit MIPS Release 6 Little Endian [`mipsisa64r6-unknown-linux-gnuabi64`](platform-support/mips-release-6.md) | ? | | 64-bit MIPS Release 6 Big Endian @@ -472,3 +472,7 @@ target | std | host | notes [runs on NVIDIA GPUs]: https://github.com/japaric-archived/nvptx#targets [the AMD GPU]: https://llvm.org/docs/AMDGPUUsage.html#processors + +[^snan-inverted]: On these targets, the treatment of floating-point NaN values is non-compliant. The bit representation for signaling NaNs is inverted compared to [what Rust expects](../std/primitive.f32.html). This means that operations that are expected to return a quiet NaN may return a signaling NaN. See [issue #68925][snan-issue]. + +[snan-issue]: https://github.com/rust-lang/rust/issues/68925 From a055c7cff03b60e5de5ef5a9b53066a4850f64c0 Mon Sep 17 00:00:00 2001 From: lapla Date: Thu, 23 Apr 2026 03:41:37 +0900 Subject: [PATCH 10/59] Register `ConstArgHasType` obligation when normalizing trait projection consts --- .../src/solve/normalizes_to/mod.rs | 16 ++++++++-- .../src/traits/project.rs | 14 +++++++- ...e-const-value-type-mismatch.current.stderr | 32 +++++++++++++++++++ ...type-const-value-type-mismatch.next.stderr | 30 +++++++++++++++++ .../mgca/type-const-value-type-mismatch.rs | 29 +++++++++++++++++ 5 files changed, 118 insertions(+), 3 deletions(-) create mode 100644 tests/ui/const-generics/mgca/type-const-value-type-mismatch.current.stderr create mode 100644 tests/ui/const-generics/mgca/type-const-value-type-mismatch.next.stderr create mode 100644 tests/ui/const-generics/mgca/type-const-value-type-mismatch.rs diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index d35e05aa33cf2..b9912ae7b324f 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -410,10 +410,22 @@ where ty::AliasTermKind::ProjectionConst { .. } if cx.is_type_const(target_item_def_id.into()) => { - cx.const_of_item(target_item_def_id.into()) + let term: I::Term = cx + .const_of_item(target_item_def_id.into()) .instantiate(cx, target_args) .skip_norm_wip() - .into() + .into(); + if let Some(ct) = term.as_const() { + let expected_ty = cx + .type_of(target_item_def_id.into()) + .instantiate(cx, target_args) + .skip_norm_wip(); + ecx.add_goal( + GoalSource::Misc, + goal.with(cx, ty::ClauseKind::ConstArgHasType(ct, expected_ty)), + ); + } + term } ty::AliasTermKind::ProjectionConst { .. } => { let uv = ty::UnevaluatedConst::new( diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index e392ca6fa2cf9..5dc25b0c08bb5 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -2049,7 +2049,19 @@ fn confirm_impl_candidate<'cx, 'tcx>( Progress { term: err, obligations: nested } } else { assoc_term_own_obligations(selcx, obligation, &mut nested); - Progress { term: term.instantiate(tcx, args).skip_norm_wip(), obligations: nested } + let instantiated_term: Term<'tcx> = term.instantiate(tcx, args).skip_norm_wip(); + if let Some(ct) = instantiated_term.as_const() { + let expected_ty = + tcx.type_of(assoc_term.item.def_id).instantiate(tcx, args).skip_norm_wip(); + nested.push(Obligation::with_depth( + tcx, + obligation.cause.clone(), + obligation.recursion_depth + 1, + obligation.param_env, + ty::ClauseKind::ConstArgHasType(ct, expected_ty), + )); + } + Progress { term: instantiated_term, obligations: nested } }; Ok(Projected::Progress(progress)) } diff --git a/tests/ui/const-generics/mgca/type-const-value-type-mismatch.current.stderr b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.current.stderr new file mode 100644 index 0000000000000..7ce0513c91d13 --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.current.stderr @@ -0,0 +1,32 @@ +error[E0053]: method `arr` has an incompatible type for trait + --> $DIR/type-const-value-type-mismatch.rs:22:5 + | +LL | fn arr() -> [u8; const { Self::LEN }] {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an array with a size of 0, found one with a size of const { Self::LEN } + | +note: type in trait + --> $DIR/type-const-value-type-mismatch.rs:15:5 + | +LL | fn arr() -> [u8; Self::LEN]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: expected signature `fn() -> [u8; 0]` + found signature `fn() -> [u8; const { Self::LEN }]` + +error: the constant `0` is not of type `usize` + --> $DIR/type-const-value-type-mismatch.rs:19:5 + | +LL | type const LEN: usize = 0u8; + | ^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `u8` + +error[E0308]: mismatched types + --> $DIR/type-const-value-type-mismatch.rs:22:17 + | +LL | fn arr() -> [u8; const { Self::LEN }] {} + | --- ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `[u8; const { Self::LEN }]`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0053, E0308. +For more information about an error, try `rustc --explain E0053`. diff --git a/tests/ui/const-generics/mgca/type-const-value-type-mismatch.next.stderr b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.next.stderr new file mode 100644 index 0000000000000..77885cbcfecde --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.next.stderr @@ -0,0 +1,30 @@ +error[E0271]: type mismatch resolving `::LEN normalizes-to 0` + --> $DIR/type-const-value-type-mismatch.rs:22:5 + | +LL | fn arr() -> [u8; const { Self::LEN }] {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + +error: the constant `0` is not of type `usize` + --> $DIR/type-const-value-type-mismatch.rs:19:5 + | +LL | type const LEN: usize = 0u8; + | ^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `u8` + +error[E0284]: type annotations needed: cannot normalize `::arr::{constant#0}` + --> $DIR/type-const-value-type-mismatch.rs:22:17 + | +LL | fn arr() -> [u8; const { Self::LEN }] {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `::arr::{constant#0}` + +error[E0308]: mismatched types + --> $DIR/type-const-value-type-mismatch.rs:22:17 + | +LL | fn arr() -> [u8; const { Self::LEN }] {} + | --- ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `[u8; _]`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0271, E0284, E0308. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/const-generics/mgca/type-const-value-type-mismatch.rs b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.rs new file mode 100644 index 0000000000000..273e7e340fef1 --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.rs @@ -0,0 +1,29 @@ +// Regression test for https://github.com/rust-lang/rust/issues/152962 + +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ compile-flags: -Zvalidate-mir + +#![feature(min_generic_const_args)] +#![expect(incomplete_features)] + +pub struct A; + +pub trait Array { + type const LEN: usize; + fn arr() -> [u8; Self::LEN]; +} + +impl Array for A { + type const LEN: usize = 0u8; + //~^ ERROR the constant `0` is not of type `usize` + + fn arr() -> [u8; const { Self::LEN }] {} + //~^ ERROR mismatched types [E0308] + //[current]~| ERROR method `arr` has an incompatible type for trait [E0053] + //[next]~| ERROR type annotations needed + //[next]~| ERROR type mismatch resolving `::LEN normalizes-to 0` [E0271] +} + +fn main() {} From 7c5236891b6e8f7997795259c3e2a2475a2349a6 Mon Sep 17 00:00:00 2001 From: lapla Date: Thu, 23 Apr 2026 03:41:53 +0900 Subject: [PATCH 11/59] Register `ConstArgHasType` obligation when normalizing inherent projection consts --- .../src/solve/normalizes_to/inherent.rs | 13 +++++++++- .../src/traits/project.rs | 11 +++++++++ ...nherent-value-type-mismatch.current.stderr | 17 +++++++++++++ ...t-inherent-value-type-mismatch.next.stderr | 24 +++++++++++++++++++ ...type-const-inherent-value-type-mismatch.rs | 22 +++++++++++++++++ 5 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.current.stderr create mode 100644 tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.next.stderr create mode 100644 tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.rs diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs index 16a86cc44ccf9..6cf609d8cdacf 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs @@ -5,6 +5,7 @@ //! 2. equate the self type, and //! 3. instantiate and register where clauses. +use rustc_type_ir::inherent::*; use rustc_type_ir::solve::QueryResultOrRerunNonErased; use rustc_type_ir::{self as ty, Interner, Unnormalized}; @@ -54,7 +55,7 @@ where .map(|pred| goal.with(cx, pred)), ); - let normalized = match inherent.kind { + let normalized: I::Term = match inherent.kind { ty::AliasTermKind::InherentTy { def_id } => { cx.type_of(def_id.into()).instantiate(cx, inherent_args).skip_norm_wip().into() } @@ -74,6 +75,16 @@ where } kind => panic!("expected inherent alias, found {kind:?}"), }; + + if let Some(ct) = normalized.as_const() { + let expected_ty = + cx.type_of(inherent.def_id()).instantiate(cx, inherent_args).skip_norm_wip(); + self.add_goal( + GoalSource::Misc, + goal.with(cx, ty::ClauseKind::ConstArgHasType(ct, expected_ty)), + ); + } + self.instantiate_normalizes_to_term(goal, normalized); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 5dc25b0c08bb5..97d56fc22f4ec 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -554,6 +554,17 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>( tcx.const_of_item(alias_term.def_id()).instantiate(tcx, args).skip_norm_wip().into() }; + if let Some(ct) = term.as_const() { + let expected_ty = tcx.type_of(alias_term.def_id()).instantiate(tcx, args).skip_norm_wip(); + obligations.push(Obligation::with_depth( + tcx, + cause.clone(), + depth + 1, + param_env, + ty::ClauseKind::ConstArgHasType(ct, expected_ty), + )); + } + let mut term = selcx.infcx.resolve_vars_if_possible(term); if term.has_aliases() { term = diff --git a/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.current.stderr b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.current.stderr new file mode 100644 index 0000000000000..bf34bcaf9fc9c --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.current.stderr @@ -0,0 +1,17 @@ +error: the constant `"this isn't a usize"` is not of type `usize` + --> $DIR/type-const-inherent-value-type-mismatch.rs:14:5 + | +LL | type const N: usize = "this isn't a usize"; + | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&'static str` + +error[E0308]: mismatched types + --> $DIR/type-const-inherent-value-type-mismatch.rs:18:11 + | +LL | fn f() -> [u8; const { Struct::N }] {} + | - ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `[u8; const { Struct::N }]`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.next.stderr b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.next.stderr new file mode 100644 index 0000000000000..5d0b81f4a3e0d --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.next.stderr @@ -0,0 +1,24 @@ +error[E0284]: type annotations needed: cannot normalize `f::{constant#0}` + --> $DIR/type-const-inherent-value-type-mismatch.rs:18:11 + | +LL | fn f() -> [u8; const { Struct::N }] {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `f::{constant#0}` + +error: the constant `"this isn't a usize"` is not of type `usize` + --> $DIR/type-const-inherent-value-type-mismatch.rs:14:5 + | +LL | type const N: usize = "this isn't a usize"; + | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&'static str` + +error[E0308]: mismatched types + --> $DIR/type-const-inherent-value-type-mismatch.rs:18:11 + | +LL | fn f() -> [u8; const { Struct::N }] {} + | - ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `[u8; _]`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0284, E0308. +For more information about an error, try `rustc --explain E0284`. diff --git a/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.rs b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.rs new file mode 100644 index 0000000000000..1f00b4410c4d7 --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.rs @@ -0,0 +1,22 @@ +// Regression test for https://github.com/rust-lang/rust/issues/152962 + +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ compile-flags: -Zvalidate-mir + +#![feature(min_generic_const_args)] +#![expect(incomplete_features)] + +struct Struct; + +impl Struct { + type const N: usize = "this isn't a usize"; + //~^ ERROR the constant `"this isn't a usize"` is not of type `usize` +} + +fn f() -> [u8; const { Struct::N }] {} +//~^ ERROR mismatched types [E0308] +//[next]~| ERROR type annotations needed + +fn main() {} From d8cd4cc5ba8f198dc0e54fd7c4b07ec03f0cb7ca Mon Sep 17 00:00:00 2001 From: lapla Date: Thu, 23 Apr 2026 03:42:03 +0900 Subject: [PATCH 12/59] Add test that free type const value type mismatch does not ICE --- .../mgca/type-const-free-value-type-mismatch.rs | 13 +++++++++++++ .../type-const-free-value-type-mismatch.stderr | 15 +++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs create mode 100644 tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.stderr diff --git a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs new file mode 100644 index 0000000000000..5e9147b9a7b91 --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs @@ -0,0 +1,13 @@ +#![feature(min_generic_const_args)] +#![expect(incomplete_features)] + +//@ compile-flags: -Zvalidate-mir +//@ normalize-stderr: "\d+-byte" -> "$$BYTE-byte" + +type const N: usize = "this isn't a usize"; +//~^ ERROR the constant `"this isn't a usize"` is not of type `usize` + +fn f() -> [u8; const { N }] {} +//~^ ERROR transmuting from + +fn main() {} diff --git a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.stderr b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.stderr new file mode 100644 index 0000000000000..20ffb7b335a55 --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.stderr @@ -0,0 +1,15 @@ +error: the constant `"this isn't a usize"` is not of type `usize` + --> $DIR/type-const-free-value-type-mismatch.rs:7:1 + | +LL | type const N: usize = "this isn't a usize"; + | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&'static str` + +error[E0080]: transmuting from $BYTE-byte type to $BYTE-byte type: `&str` -> `usize` + --> $DIR/type-const-free-value-type-mismatch.rs:10:24 + | +LL | fn f() -> [u8; const { N }] {} + | ^ evaluation of `f::{constant#0}` failed here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0080`. From 1f9a5140de7473602384232113c62e398d7c9bda Mon Sep 17 00:00:00 2001 From: lapla Date: Thu, 23 Apr 2026 03:42:14 +0900 Subject: [PATCH 13/59] Extract shared helper for registering `ConstArgHasType` during const projection normalization --- .../src/solve/normalizes_to/inherent.rs | 12 +--- .../src/solve/normalizes_to/mod.rs | 40 ++++++----- .../src/traits/project.rs | 66 +++++++++++++------ 3 files changed, 71 insertions(+), 47 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs index 6cf609d8cdacf..68e1fe34f8797 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs @@ -5,7 +5,6 @@ //! 2. equate the self type, and //! 3. instantiate and register where clauses. -use rustc_type_ir::inherent::*; use rustc_type_ir::solve::QueryResultOrRerunNonErased; use rustc_type_ir::{self as ty, Interner, Unnormalized}; @@ -76,16 +75,7 @@ where kind => panic!("expected inherent alias, found {kind:?}"), }; - if let Some(ct) = normalized.as_const() { - let expected_ty = - cx.type_of(inherent.def_id()).instantiate(cx, inherent_args).skip_norm_wip(); - self.add_goal( - GoalSource::Misc, - goal.with(cx, ty::ClauseKind::ConstArgHasType(ct, expected_ty)), - ); - } - - self.instantiate_normalizes_to_term(goal, normalized); + self.instantiate_normalizes_to_term_with_type_check(goal, normalized); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } } diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index b9912ae7b324f..c9ef2ae737683 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -130,6 +130,28 @@ where .expect("expected goal term to be fully unconstrained"); } + /// Like `instantiate_normalizes_to_term`, but also registers a + /// `ConstArgHasType` goal when the term is a const. This ensures that + /// the const value's type matches the type of the alias it was + /// normalized from, preventing ICEs from type mismatches. + pub fn instantiate_normalizes_to_term_with_type_check( + &mut self, + goal: Goal>, + term: I::Term, + ) { + if let Some(ct) = term.as_const() { + let cx = self.cx(); + let alias = goal.predicate.alias; + let expected_ty = + cx.type_of(alias.def_id()).instantiate(cx, alias.args).skip_norm_wip(); + self.add_goal( + GoalSource::Misc, + goal.with(cx, ty::ClauseKind::ConstArgHasType(ct, expected_ty)), + ); + } + self.instantiate_normalizes_to_term(goal, term); + } + /// Unlike `instantiate_normalizes_to_term` this instantiates the expected term /// with a rigid alias. Using this is pretty much always wrong. pub fn structurally_instantiate_normalizes_to_term( @@ -410,22 +432,10 @@ where ty::AliasTermKind::ProjectionConst { .. } if cx.is_type_const(target_item_def_id.into()) => { - let term: I::Term = cx - .const_of_item(target_item_def_id.into()) + cx.const_of_item(target_item_def_id.into()) .instantiate(cx, target_args) .skip_norm_wip() - .into(); - if let Some(ct) = term.as_const() { - let expected_ty = cx - .type_of(target_item_def_id.into()) - .instantiate(cx, target_args) - .skip_norm_wip(); - ecx.add_goal( - GoalSource::Misc, - goal.with(cx, ty::ClauseKind::ConstArgHasType(ct, expected_ty)), - ); - } - term + .into() } ty::AliasTermKind::ProjectionConst { .. } => { let uv = ty::UnevaluatedConst::new( @@ -440,7 +450,7 @@ where kind => panic!("expected projection, found {kind:?}"), }; - ecx.instantiate_normalizes_to_term(goal, term); + ecx.instantiate_normalizes_to_term_with_type_check(goal, term); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes).map_err(Into::into) }) } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 97d56fc22f4ec..d149911a92de5 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -5,6 +5,7 @@ use std::ops::ControlFlow; use rustc_data_structures::sso::SsoHashSet; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::ErrorGuaranteed; +use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::resolve::OpportunisticRegionResolver; @@ -487,6 +488,30 @@ fn normalize_to_error<'a, 'tcx>( Normalized { value: new_value, obligations } } +/// When normalizing a const alias, register a `ConstArgHasType` obligation +/// to ensure the const value's type matches the declared type. +fn push_const_arg_has_type_obligation<'tcx>( + tcx: TyCtxt<'tcx>, + obligations: &mut PredicateObligations<'tcx>, + cause: &ObligationCause<'tcx>, + depth: usize, + param_env: ty::ParamEnv<'tcx>, + term: Term<'tcx>, + def_id: DefId, + args: ty::GenericArgsRef<'tcx>, +) { + if let Some(ct) = term.as_const() { + let expected_ty = tcx.type_of(def_id).instantiate(tcx, args).skip_norm_wip(); + obligations.push(Obligation::with_depth( + tcx, + cause.clone(), + depth, + param_env, + ty::ClauseKind::ConstArgHasType(ct, expected_ty), + )); + } +} + /// Confirm and normalize the given inherent projection. // FIXME(mgca): While this supports constants, it is only used for types by default right now #[instrument(level = "debug", skip(selcx, param_env, cause, obligations))] @@ -554,16 +579,16 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>( tcx.const_of_item(alias_term.def_id()).instantiate(tcx, args).skip_norm_wip().into() }; - if let Some(ct) = term.as_const() { - let expected_ty = tcx.type_of(alias_term.def_id()).instantiate(tcx, args).skip_norm_wip(); - obligations.push(Obligation::with_depth( - tcx, - cause.clone(), - depth + 1, - param_env, - ty::ClauseKind::ConstArgHasType(ct, expected_ty), - )); - } + push_const_arg_has_type_obligation( + tcx, + obligations, + &cause, + depth + 1, + param_env, + term, + alias_term.def_id(), + args, + ); let mut term = selcx.infcx.resolve_vars_if_possible(term); if term.has_aliases() { @@ -2061,17 +2086,16 @@ fn confirm_impl_candidate<'cx, 'tcx>( } else { assoc_term_own_obligations(selcx, obligation, &mut nested); let instantiated_term: Term<'tcx> = term.instantiate(tcx, args).skip_norm_wip(); - if let Some(ct) = instantiated_term.as_const() { - let expected_ty = - tcx.type_of(assoc_term.item.def_id).instantiate(tcx, args).skip_norm_wip(); - nested.push(Obligation::with_depth( - tcx, - obligation.cause.clone(), - obligation.recursion_depth + 1, - obligation.param_env, - ty::ClauseKind::ConstArgHasType(ct, expected_ty), - )); - } + push_const_arg_has_type_obligation( + tcx, + &mut nested, + &obligation.cause, + obligation.recursion_depth + 1, + obligation.param_env, + instantiated_term, + assoc_term.item.def_id, + args, + ); Progress { term: instantiated_term, obligations: nested } }; Ok(Projected::Progress(progress)) From 1240be2939d29d3805b948cd7d203f34d904eed6 Mon Sep 17 00:00:00 2001 From: lapla Date: Sat, 9 May 2026 14:14:48 +0900 Subject: [PATCH 14/59] Register `ConstArgHasType` when normalizing free const aliases --- .../src/solve/normalizes_to/free_alias.rs | 2 +- .../src/traits/normalize.rs | 15 +++++++++++- .../src/traits/query/normalize.rs | 14 ++++++++++- .../src/normalize_erasing_regions.rs | 4 ++-- .../type-const-free-anon-const-mismatch.rs | 12 ++++++++++ ...type-const-free-anon-const-mismatch.stderr | 15 ++++++++++++ ...t-free-value-type-mismatch.current.stderr} | 4 ++-- ...const-free-value-type-mismatch.next.stderr | 24 +++++++++++++++++++ .../type-const-free-value-type-mismatch.rs | 7 +++++- .../mgca/type_const-mismatched-types.rs | 3 ++- .../mgca/type_const-mismatched-types.stderr | 10 ++++++-- 11 files changed, 99 insertions(+), 11 deletions(-) create mode 100644 tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.rs create mode 100644 tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.stderr rename tests/ui/const-generics/mgca/{type-const-free-value-type-mismatch.stderr => type-const-free-value-type-mismatch.current.stderr} (81%) create mode 100644 tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.next.stderr diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs index ad050b69425c5..9673d9352e581 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs @@ -49,7 +49,7 @@ where kind => panic!("expected free alias, found {kind:?}"), }; - self.instantiate_normalizes_to_term(goal, actual); + self.instantiate_normalizes_to_term_with_type_check(goal, actual); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } } diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index d3bad276d5688..22ef6faf96aed 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -339,7 +339,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { }), ); self.depth += 1; - let res = if free.kind.is_type() { + let res: ty::Term<'tcx> = if free.kind.is_type() { infcx .tcx .type_of(free.def_id()) @@ -356,6 +356,19 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { .fold_with(self) .into() }; + // When normalizing a free const alias, register a `ConstArgHasType` + // obligation to ensure the const value's type matches the declared type. + if let Some(ct) = res.as_const() { + let expected_ty = + infcx.tcx.type_of(free.def_id()).instantiate(infcx.tcx, free.args).skip_norm_wip(); + self.obligations.push(Obligation::with_depth( + infcx.tcx, + self.cause.clone(), + self.depth, + self.param_env, + ty::ClauseKind::ConstArgHasType(ct, expected_ty), + )); + } self.depth -= 1; res } diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 03badcbc7251e..b3f8f486f258d 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -4,7 +4,7 @@ use rustc_data_structures::sso::SsoHashMap; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_infer::traits::PredicateObligations; +use rustc_infer::traits::{Obligation, PredicateObligations}; use rustc_macros::extension; pub use rustc_middle::traits::query::NormalizationResult; use rustc_middle::ty::{ @@ -372,6 +372,18 @@ impl<'a, 'tcx> QueryNormalizer<'a, 'tcx> { } else { result.normalized_term }; + // When normalizing a const alias, register a `ConstArgHasType` obligation + // to ensure the const value's type matches the declared type. + if let Some(ct) = res.as_const() { + let expected_ty = + tcx.type_of(term.def_id()).instantiate(tcx, term.args).skip_norm_wip(); + self.obligations.push(Obligation::new( + tcx, + self.cause.clone(), + self.param_env, + ty::ClauseKind::ConstArgHasType(ct, expected_ty), + )); + } // `tcx.normalize_canonicalized_projection` may normalize to a type that // still has unevaluated consts, so keep normalizing here if that's the case. // Similarly, `tcx.normalize_canonicalized_free_alias` will only unwrap one layer diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index d3a2c4d20f95d..d41d2cf27f624 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -63,11 +63,11 @@ fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable> + Par fn not_outlives_predicate(p: ty::Predicate<'_>) -> bool { match p.kind().skip_binder() { ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..)) - | ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..)) => false, + | ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..)) + | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) => false, ty::PredicateKind::Clause(ty::ClauseKind::Trait(..)) | ty::PredicateKind::Clause(ty::ClauseKind::Projection(..)) | ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..)) - | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) | ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(_)) | ty::PredicateKind::NormalizesTo(..) | ty::PredicateKind::AliasRelate(..) diff --git a/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.rs b/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.rs new file mode 100644 index 0000000000000..906bd5e7ef912 --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.rs @@ -0,0 +1,12 @@ +//@ compile-flags: -Zvalidate-mir -Znext-solver + +#![feature(min_generic_const_args)] +#![expect(incomplete_features)] + +type const X: usize = const { N }; +//~^ ERROR type annotations needed + +type const N: usize = "this isn't a usize"; +//~^ ERROR the constant `"this isn't a usize"` is not of type `usize` + +fn main() {} diff --git a/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.stderr b/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.stderr new file mode 100644 index 0000000000000..0718b739cad0e --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.stderr @@ -0,0 +1,15 @@ +error[E0284]: type annotations needed: cannot normalize `X::{constant#0}` + --> $DIR/type-const-free-anon-const-mismatch.rs:6:1 + | +LL | type const X: usize = const { N }; + | ^^^^^^^^^^^^^^^^^^^ cannot normalize `X::{constant#0}` + +error: the constant `"this isn't a usize"` is not of type `usize` + --> $DIR/type-const-free-anon-const-mismatch.rs:9:1 + | +LL | type const N: usize = "this isn't a usize"; + | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&'static str` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.stderr b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.current.stderr similarity index 81% rename from tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.stderr rename to tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.current.stderr index 20ffb7b335a55..a734b4062b2a6 100644 --- a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.stderr +++ b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.current.stderr @@ -1,11 +1,11 @@ error: the constant `"this isn't a usize"` is not of type `usize` - --> $DIR/type-const-free-value-type-mismatch.rs:7:1 + --> $DIR/type-const-free-value-type-mismatch.rs:10:1 | LL | type const N: usize = "this isn't a usize"; | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&'static str` error[E0080]: transmuting from $BYTE-byte type to $BYTE-byte type: `&str` -> `usize` - --> $DIR/type-const-free-value-type-mismatch.rs:10:24 + --> $DIR/type-const-free-value-type-mismatch.rs:13:24 | LL | fn f() -> [u8; const { N }] {} | ^ evaluation of `f::{constant#0}` failed here diff --git a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.next.stderr b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.next.stderr new file mode 100644 index 0000000000000..2fbd629878bfe --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.next.stderr @@ -0,0 +1,24 @@ +error: the constant `"this isn't a usize"` is not of type `usize` + --> $DIR/type-const-free-value-type-mismatch.rs:10:1 + | +LL | type const N: usize = "this isn't a usize"; + | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&'static str` + +error[E0284]: type annotations needed: cannot normalize `f::{constant#0}` + --> $DIR/type-const-free-value-type-mismatch.rs:13:11 + | +LL | fn f() -> [u8; const { N }] {} + | ^^^^^^^^^^^^^^^^^ cannot normalize `f::{constant#0}` + +error[E0308]: mismatched types + --> $DIR/type-const-free-value-type-mismatch.rs:13:11 + | +LL | fn f() -> [u8; const { N }] {} + | - ^^^^^^^^^^^^^^^^^ expected `[u8; _]`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0284, E0308. +For more information about an error, try `rustc --explain E0284`. diff --git a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs index 5e9147b9a7b91..1b66a5d54f7e6 100644 --- a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs +++ b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs @@ -1,6 +1,9 @@ #![feature(min_generic_const_args)] #![expect(incomplete_features)] +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver //@ compile-flags: -Zvalidate-mir //@ normalize-stderr: "\d+-byte" -> "$$BYTE-byte" @@ -8,6 +11,8 @@ type const N: usize = "this isn't a usize"; //~^ ERROR the constant `"this isn't a usize"` is not of type `usize` fn f() -> [u8; const { N }] {} -//~^ ERROR transmuting from +//[current]~^ ERROR transmuting from +//[next]~^^ ERROR type annotations needed +//[next]~| ERROR mismatched types [E0308] fn main() {} diff --git a/tests/ui/const-generics/mgca/type_const-mismatched-types.rs b/tests/ui/const-generics/mgca/type_const-mismatched-types.rs index b17a5b2b978a6..74f6aa5a2ddf2 100644 --- a/tests/ui/const-generics/mgca/type_const-mismatched-types.rs +++ b/tests/ui/const-generics/mgca/type_const-mismatched-types.rs @@ -5,7 +5,8 @@ type const FREE: u32 = 5_usize; //~^ ERROR the constant `5` is not of type `u32` type const FREE2: isize = FREE; -//~^ ERROR the constant `5` is not of type `isize` +//~^ ERROR the constant `5` is not of type `u32` +//~| ERROR the constant `5` is not of type `isize` trait Tr { type const N: usize; diff --git a/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr b/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr index e2c916cf6d05a..df728d8065923 100644 --- a/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr +++ b/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr @@ -4,6 +4,12 @@ error: the constant `5` is not of type `u32` LL | type const FREE: u32 = 5_usize; | ^^^^^^^^^^^^^^^^^^^^ expected `u32`, found `usize` +error: the constant `5` is not of type `u32` + --> $DIR/type_const-mismatched-types.rs:7:1 + | +LL | type const FREE2: isize = FREE; + | ^^^^^^^^^^^^^^^^^^^^^^^ expected `u32`, found `usize` + error: the constant `5` is not of type `isize` --> $DIR/type_const-mismatched-types.rs:7:1 | @@ -11,10 +17,10 @@ LL | type const FREE2: isize = FREE; | ^^^^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `usize` error: the constant `false` is not of type `usize` - --> $DIR/type_const-mismatched-types.rs:15:5 + --> $DIR/type_const-mismatched-types.rs:16:5 | LL | type const N: usize = false; | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool` -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors From 51001cf7efdf1b35ddb21ccb7f7659fefc1e5f74 Mon Sep 17 00:00:00 2001 From: xmakro Date: Tue, 2 Jun 2026 20:19:03 -0700 Subject: [PATCH 15/59] Make the retained dep graph deterministic under the parallel frontend The in-memory dep graph kept for `-Zquery-dep-graph` is built by `GraphEncoder::record`, which pushed each node using `try_lock` and silently dropped the node when the lock was contended. Single-threaded the only contention is a query forced re-entrantly from within `with_retained_dep_graph`, so dropping was harmless. Under the parallel frontend several encoder threads record nodes at the same time, so a contended `try_lock` dropped nodes and edges at random, leaving the retained graph nondeterministic and making the dep-graph ui tests, which assert on its contents, fail intermittently. Remove that reentrancy in `check_paths`: read the graph into owned results while the lock is held, then emit the diagnostics afterwards. The only query forced inside the old closure was `def_path_str` (for the error messages), which can create dep nodes and re-enter the encoder; doing the emission after the lock is released means `record` never re-enters while the lock is held. `record` can then block on the lock unconditionally instead of using `try_lock`, so concurrent encoders never drop a node or edge. This only affects compilation with `-Zquery-dep-graph`; with the flag off the retained graph is absent and nothing changes. --- .../src/graph/linked_graph/mod.rs | 4 +- .../rustc_incremental/src/assert_dep_graph.rs | 45 +++++++++++-------- compiler/rustc_middle/src/dep_graph/graph.rs | 10 +++-- .../rustc_middle/src/dep_graph/retained.rs | 1 + .../rustc_middle/src/dep_graph/serialized.rs | 16 +++---- 5 files changed, 45 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_data_structures/src/graph/linked_graph/mod.rs b/compiler/rustc_data_structures/src/graph/linked_graph/mod.rs index 2223e85a24957..cecb051172598 100644 --- a/compiler/rustc_data_structures/src/graph/linked_graph/mod.rs +++ b/compiler/rustc_data_structures/src/graph/linked_graph/mod.rs @@ -45,17 +45,19 @@ mod tests; /// This graph implementation predates the later [graph traits](crate::graph), /// and does not implement those traits, so it has its own implementations of a /// few basic graph algorithms. +#[derive(Clone)] pub struct LinkedGraph { nodes: IndexVec>, edges: Vec>, } +#[derive(Clone)] pub struct Node { first_edge: [EdgeIndex; 2], // see module comment pub data: Option, } -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct Edge { next_edge: [EdgeIndex; 2], // see module comment source: NodeIndex, diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index 36439160b7d20..b3f9a137817a7 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -57,8 +57,14 @@ use crate::errors; #[allow(missing_docs)] pub(crate) fn assert_dep_graph(tcx: TyCtxt<'_>) { tcx.dep_graph.with_ignore(|| { + // Clone the retained dep graph once and share it between the graph dump and the path + // checks below, rather than locking and cloning it separately for each. + let retained_dep_graph = tcx.dep_graph.retained_dep_graph(); + if tcx.sess.opts.unstable_opts.dump_dep_graph { - tcx.dep_graph.with_retained_dep_graph(dump_graph); + if let Some(graph) = &retained_dep_graph { + dump_graph(graph); + } } if !tcx.sess.opts.unstable_opts.query_dep_graph { @@ -92,7 +98,7 @@ pub(crate) fn assert_dep_graph(tcx: TyCtxt<'_>) { } // Check paths. - check_paths(tcx, &if_this_changed, &then_this_would_need); + check_paths(tcx, retained_dep_graph.as_ref(), &if_this_changed, &then_this_would_need); }) } @@ -172,30 +178,33 @@ impl<'tcx> Visitor<'tcx> for IfThisChanged<'tcx> { } } -fn check_paths<'tcx>(tcx: TyCtxt<'tcx>, if_this_changed: &Sources, then_this_would_need: &Targets) { - // Return early here so as not to construct the query, which is not cheap. +fn check_paths<'tcx>( + tcx: TyCtxt<'tcx>, + retained_dep_graph: Option<&RetainedDepGraph>, + if_this_changed: &Sources, + then_this_would_need: &Targets, +) { if if_this_changed.is_empty() { for &(target_span, _, _, _) in then_this_would_need { tcx.dcx().emit_err(errors::MissingIfThisChanged { span: target_span }); } return; } - tcx.dep_graph.with_retained_dep_graph(|query| { - for &(_, source_def_id, ref source_dep_node) in if_this_changed { - let dependents = query.transitive_predecessors(source_dep_node); - for &(target_span, ref target_pass, _, ref target_dep_node) in then_this_would_need { - if !dependents.contains(&target_dep_node) { - tcx.dcx().emit_err(errors::NoPath { - span: target_span, - source: tcx.def_path_str(source_def_id), - target: *target_pass, - }); - } else { - tcx.dcx().emit_err(errors::Ok { span: target_span }); - } + let Some(query) = retained_dep_graph else { return }; + for &(_, source_def_id, ref source_dep_node) in if_this_changed { + let dependents = query.transitive_predecessors(source_dep_node); + for &(target_span, ref target_pass, _, ref target_dep_node) in then_this_would_need { + if !dependents.contains(&target_dep_node) { + tcx.dcx().emit_err(errors::NoPath { + span: target_span, + source: tcx.def_path_str(source_def_id), + target: *target_pass, + }); + } else { + tcx.dcx().emit_err(errors::Ok { span: target_span }); } } - }); + } } fn dump_graph(graph: &RetainedDepGraph) { diff --git a/compiler/rustc_middle/src/dep_graph/graph.rs b/compiler/rustc_middle/src/dep_graph/graph.rs index b5c32a1848aeb..fa408fd3f832b 100644 --- a/compiler/rustc_middle/src/dep_graph/graph.rs +++ b/compiler/rustc_middle/src/dep_graph/graph.rs @@ -195,10 +195,12 @@ impl DepGraph { self.data.is_some() } - pub fn with_retained_dep_graph(&self, f: impl Fn(&RetainedDepGraph)) { - if let Some(data) = &self.data { - data.current.encoder.with_retained_dep_graph(f) - } + /// Returns a clone of the in-memory retained dep graph, if it is being built + /// (i.e. `-Zquery-dep-graph` is set). Cloning rather than exposing the lock keeps + /// callers from holding it while forcing queries, which would deadlock against a + /// reentrant `record` under the parallel frontend. + pub fn retained_dep_graph(&self) -> Option { + self.data.as_ref().and_then(|data| data.current.encoder.retained_dep_graph()) } pub fn assert_ignored(&self) { diff --git a/compiler/rustc_middle/src/dep_graph/retained.rs b/compiler/rustc_middle/src/dep_graph/retained.rs index 626b3b7821794..7949a47346845 100644 --- a/compiler/rustc_middle/src/dep_graph/retained.rs +++ b/compiler/rustc_middle/src/dep_graph/retained.rs @@ -9,6 +9,7 @@ use super::{DepNode, DepNodeIndex}; /// Normally, dependencies recorded during the current session are written to /// disk and then forgotten, to avoid wasting memory on information that is /// not needed when the compiler is working correctly. +#[derive(Clone)] pub struct RetainedDepGraph { pub inner: LinkedGraph, pub indices: FxHashMap, diff --git a/compiler/rustc_middle/src/dep_graph/serialized.rs b/compiler/rustc_middle/src/dep_graph/serialized.rs index ef5e3d9268ad7..7db646e95bf19 100644 --- a/compiler/rustc_middle/src/dep_graph/serialized.rs +++ b/compiler/rustc_middle/src/dep_graph/serialized.rs @@ -636,10 +636,12 @@ impl EncoderState { // Outline the build of the full dep graph as it's typically disabled and cold. outline(move || { - // Do not ICE when a query is called from within `with_query`. - if let Some(retained_graph) = &mut retained_graph.try_lock() { - retained_graph.push(index, *node, &edges); - } + // Block on the lock rather than using `try_lock`: under the parallel frontend + // several threads record nodes concurrently, and dropping a node on lock + // contention would make the retained graph nondeterministic. Readers take a + // clone of the graph (`retained_dep_graph`) rather than holding the lock, so + // this never deadlocks against a reentrant `record`. + retained_graph.lock().push(index, *node, &edges); }); } @@ -874,10 +876,8 @@ impl GraphEncoder { GraphEncoder { status, retained_graph, profiler: sess.prof.clone() } } - pub(crate) fn with_retained_dep_graph(&self, f: impl Fn(&RetainedDepGraph)) { - if let Some(retained_graph) = &self.retained_graph { - f(&retained_graph.lock()) - } + pub(crate) fn retained_dep_graph(&self) -> Option { + self.retained_graph.as_ref().map(|retained_graph| retained_graph.lock().clone()) } /// Encodes a node that does not exists in the previous graph. From d00722c8507330d0a6633a57aef511dab4f24dc6 Mon Sep 17 00:00:00 2001 From: xmakro Date: Wed, 3 Jun 2026 08:50:15 -0700 Subject: [PATCH 16/59] Re-enable dep-graph ui tests under the parallel frontend These tests assert on the contents of the retained dep graph, which is now built deterministically under the parallel frontend, so they no longer need to be ignored there. Replace the ignore-parallel-frontend directives with blank lines rather than deleting them, so the following line numbers stay the same and the expected output is unchanged. --- tests/ui/dep-graph/dep-graph-assoc-type-codegen.rs | 2 +- tests/ui/dep-graph/dep-graph-caller-callee.rs | 2 +- tests/ui/dep-graph/dep-graph-struct-signature.rs | 2 +- .../ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs | 2 +- tests/ui/dep-graph/dep-graph-trait-impl.rs | 2 +- tests/ui/dep-graph/dep-graph-type-alias.rs | 2 +- tests/ui/dep-graph/dep-graph-variance-alias.rs | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/ui/dep-graph/dep-graph-assoc-type-codegen.rs b/tests/ui/dep-graph/dep-graph-assoc-type-codegen.rs index 8b87499966de5..3c228d81e0e56 100644 --- a/tests/ui/dep-graph/dep-graph-assoc-type-codegen.rs +++ b/tests/ui/dep-graph/dep-graph-assoc-type-codegen.rs @@ -1,6 +1,6 @@ // Test that when a trait impl changes, fns whose body uses that trait // must also be recompiled. -//@ ignore-parallel-frontend dep graph + //@ incremental //@ compile-flags: -Z query-dep-graph diff --git a/tests/ui/dep-graph/dep-graph-caller-callee.rs b/tests/ui/dep-graph/dep-graph-caller-callee.rs index 43d10cd57cdbb..c4bba8bb2d0b5 100644 --- a/tests/ui/dep-graph/dep-graph-caller-callee.rs +++ b/tests/ui/dep-graph/dep-graph-caller-callee.rs @@ -3,7 +3,7 @@ //@ incremental //@ compile-flags: -Z query-dep-graph -//@ ignore-parallel-frontend dep graph + #![feature(rustc_attrs)] #![allow(dead_code)] diff --git a/tests/ui/dep-graph/dep-graph-struct-signature.rs b/tests/ui/dep-graph/dep-graph-struct-signature.rs index abef7d2e98845..f00a22cf67cf0 100644 --- a/tests/ui/dep-graph/dep-graph-struct-signature.rs +++ b/tests/ui/dep-graph/dep-graph-struct-signature.rs @@ -1,6 +1,6 @@ // Test cases where a changing struct appears in the signature of fns // and methods. -//@ ignore-parallel-frontend dep graph + //@ incremental //@ compile-flags: -Z query-dep-graph diff --git a/tests/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs b/tests/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs index ccdd2ff570f61..cdb74b9c97119 100644 --- a/tests/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs +++ b/tests/ui/dep-graph/dep-graph-trait-impl-two-traits-same-method.rs @@ -1,6 +1,6 @@ // Test that adding an impl to a trait `Foo` DOES affect functions // that only use `Bar` if they have methods in common. -//@ ignore-parallel-frontend dep graph + //@ incremental //@ compile-flags: -Z query-dep-graph diff --git a/tests/ui/dep-graph/dep-graph-trait-impl.rs b/tests/ui/dep-graph/dep-graph-trait-impl.rs index 952ccf61c7d5e..a0aefba6e4658 100644 --- a/tests/ui/dep-graph/dep-graph-trait-impl.rs +++ b/tests/ui/dep-graph/dep-graph-trait-impl.rs @@ -1,6 +1,6 @@ // Test that when a trait impl changes, fns whose body uses that trait // must also be recompiled. -//@ ignore-parallel-frontend dep graph + //@ incremental //@ compile-flags: -Z query-dep-graph diff --git a/tests/ui/dep-graph/dep-graph-type-alias.rs b/tests/ui/dep-graph/dep-graph-type-alias.rs index 8d0407a74ca86..a083f905b8ff9 100644 --- a/tests/ui/dep-graph/dep-graph-type-alias.rs +++ b/tests/ui/dep-graph/dep-graph-type-alias.rs @@ -1,5 +1,5 @@ // Test that changing what a `type` points to does not go unnoticed. -//@ ignore-parallel-frontend dep graph + //@ incremental //@ compile-flags: -Z query-dep-graph diff --git a/tests/ui/dep-graph/dep-graph-variance-alias.rs b/tests/ui/dep-graph/dep-graph-variance-alias.rs index 5e86e77b24a27..8a67fe6d7271d 100644 --- a/tests/ui/dep-graph/dep-graph-variance-alias.rs +++ b/tests/ui/dep-graph/dep-graph-variance-alias.rs @@ -1,6 +1,6 @@ // Test that changing what a `type` points to does not go unnoticed // by the variance analysis. -//@ ignore-parallel-frontend dep graph + //@ incremental //@ compile-flags: -Z query-dep-graph From 5a7ca04b70c4f33c04820f9467b5ba1e14fedf8b Mon Sep 17 00:00:00 2001 From: steamproof <93405617+pbkx@users.noreply.github.com> Date: Fri, 5 Jun 2026 01:00:31 -0700 Subject: [PATCH 17/59] Use field-index fallback for undescribed fields --- compiler/rustc_borrowck/src/diagnostics/mod.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 0b21ab419886b..564b6f09f0095 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -525,7 +525,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ty::Array(ty, _) | ty::Slice(ty) => { self.describe_field_from_ty(ty, field, variant_index, including_tuple_field) } - ty::Param(_) => Some(field.index().to_string()), ty::Closure(def_id, _) | ty::Coroutine(def_id, _) => { // We won't be borrowck'ing here if the closure came from another crate, // so it's safe to call `expect_local`. @@ -538,9 +537,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { Some(self.infcx.tcx.hir_name(var_id).to_string()) } _ => { - // Might need a revision when the fields in trait RFC is implemented - // (https://github.com/rust-lang/rfcs/pull/1546) - bug!("End-user description not implemented for field access on `{:?}`", ty); + // This can happen for field accesses on `Box`: the field is + // described from the boxed type, which may have no named fields + Some(field.index().to_string()) } } } From 2e34f41bef64eaa839a033d6b753d34891a6b465 Mon Sep 17 00:00:00 2001 From: lapla Date: Fri, 5 Jun 2026 20:46:52 +0900 Subject: [PATCH 18/59] Make `instantiate_normalizes_to_term()` also handle `ConstArgHasType` checks --- .../src/solve/normalizes_to/free_alias.rs | 2 +- .../src/solve/normalizes_to/inherent.rs | 2 +- .../src/solve/normalizes_to/mod.rs | 22 ++++++------------- 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs index 9673d9352e581..ad050b69425c5 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs @@ -49,7 +49,7 @@ where kind => panic!("expected free alias, found {kind:?}"), }; - self.instantiate_normalizes_to_term_with_type_check(goal, actual); + self.instantiate_normalizes_to_term(goal, actual); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } } diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs index 68e1fe34f8797..85d079e84073e 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs @@ -75,7 +75,7 @@ where kind => panic!("expected inherent alias, found {kind:?}"), }; - self.instantiate_normalizes_to_term_with_type_check(goal, normalized); + self.instantiate_normalizes_to_term(goal, normalized); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } } diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index c9ef2ae737683..07ad13fc1b135 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -121,23 +121,14 @@ where /// We know `term` to always be a fully unconstrained inference variable, so /// `eq` should never fail here. However, in case `term` contains aliases, we /// emit nested `AliasRelate` goals to structurally normalize the alias. + /// + /// Additionally, when `term` is a const, this registers a `ConstArgHasType` + /// goal to ensure that the const value's type matches the type of the + /// alias it was normalized from, preventing ICEs from type mismatches. pub fn instantiate_normalizes_to_term( &mut self, goal: Goal>, term: I::Term, - ) { - self.eq(goal.param_env, goal.predicate.term, term) - .expect("expected goal term to be fully unconstrained"); - } - - /// Like `instantiate_normalizes_to_term`, but also registers a - /// `ConstArgHasType` goal when the term is a const. This ensures that - /// the const value's type matches the type of the alias it was - /// normalized from, preventing ICEs from type mismatches. - pub fn instantiate_normalizes_to_term_with_type_check( - &mut self, - goal: Goal>, - term: I::Term, ) { if let Some(ct) = term.as_const() { let cx = self.cx(); @@ -149,7 +140,8 @@ where goal.with(cx, ty::ClauseKind::ConstArgHasType(ct, expected_ty)), ); } - self.instantiate_normalizes_to_term(goal, term); + self.eq(goal.param_env, goal.predicate.term, term) + .expect("expected goal term to be fully unconstrained"); } /// Unlike `instantiate_normalizes_to_term` this instantiates the expected term @@ -450,7 +442,7 @@ where kind => panic!("expected projection, found {kind:?}"), }; - ecx.instantiate_normalizes_to_term_with_type_check(goal, term); + ecx.instantiate_normalizes_to_term(goal, term); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes).map_err(Into::into) }) } From e8390d892fb045ef44ba1a65e18b5dafd8a4f417 Mon Sep 17 00:00:00 2001 From: lapla Date: Fri, 5 Jun 2026 21:59:53 +0900 Subject: [PATCH 19/59] Register `ConstArgHasType` in queries --- .../src/traits/query/normalize.rs | 14 +------ .../src/normalize_erasing_regions.rs | 4 +- .../src/normalize_projection_ty.rs | 41 ++++++++++++++++++- ...st-free-value-type-mismatch.current.stderr | 12 +++--- ...const-free-value-type-mismatch.next.stderr | 6 +-- .../type-const-free-value-type-mismatch.rs | 3 +- 6 files changed, 53 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index b3f8f486f258d..03badcbc7251e 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -4,7 +4,7 @@ use rustc_data_structures::sso::SsoHashMap; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_infer::traits::{Obligation, PredicateObligations}; +use rustc_infer::traits::PredicateObligations; use rustc_macros::extension; pub use rustc_middle::traits::query::NormalizationResult; use rustc_middle::ty::{ @@ -372,18 +372,6 @@ impl<'a, 'tcx> QueryNormalizer<'a, 'tcx> { } else { result.normalized_term }; - // When normalizing a const alias, register a `ConstArgHasType` obligation - // to ensure the const value's type matches the declared type. - if let Some(ct) = res.as_const() { - let expected_ty = - tcx.type_of(term.def_id()).instantiate(tcx, term.args).skip_norm_wip(); - self.obligations.push(Obligation::new( - tcx, - self.cause.clone(), - self.param_env, - ty::ClauseKind::ConstArgHasType(ct, expected_ty), - )); - } // `tcx.normalize_canonicalized_projection` may normalize to a type that // still has unevaluated consts, so keep normalizing here if that's the case. // Similarly, `tcx.normalize_canonicalized_free_alias` will only unwrap one layer diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index d41d2cf27f624..d3a2c4d20f95d 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -63,11 +63,11 @@ fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable> + Par fn not_outlives_predicate(p: ty::Predicate<'_>) -> bool { match p.kind().skip_binder() { ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..)) - | ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..)) - | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) => false, + | ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..)) => false, ty::PredicateKind::Clause(ty::ClauseKind::Trait(..)) | ty::PredicateKind::Clause(ty::ClauseKind::Projection(..)) | ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..)) + | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) | ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(_)) | ty::PredicateKind::NormalizesTo(..) | ty::PredicateKind::AliasRelate(..) diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs index 96586713aed6f..1505fd20bbdb1 100644 --- a/compiler/rustc_traits/src/normalize_projection_ty.rs +++ b/compiler/rustc_traits/src/normalize_projection_ty.rs @@ -2,7 +2,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_infer::traits::PredicateObligations; use rustc_middle::query::Providers; -use rustc_middle::ty::{ParamEnvAnd, TyCtxt}; +use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::infer::InferCtxtBuilderExt; use rustc_trait_selection::traits::query::normalize::NormalizationResult; @@ -19,6 +19,25 @@ pub(crate) fn provide(p: &mut Providers) { }; } +/// If `normalized_term` is a const, returns a `ConstArgHasType` obligation +/// to verify that the const value's type matches the alias's declared type. +/// Returns `None` if the term is a type rather than a const. +fn const_arg_has_type_obligation<'tcx>( + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + normalized_term: ty::Term<'tcx>, + goal: ty::AliasTerm<'tcx>, +) -> Option> { + let ct = normalized_term.as_const()?; + let expected_ty = tcx.type_of(goal.def_id()).instantiate(tcx, goal.args).skip_norm_wip(); + Some(traits::Obligation::new( + tcx, + ObligationCause::dummy(), + param_env, + ty::ClauseKind::ConstArgHasType(ct, expected_ty), + )) +} + fn normalize_canonicalized_projection<'tcx>( tcx: TyCtxt<'tcx>, goal: CanonicalAliasGoal<'tcx>, @@ -40,6 +59,12 @@ fn normalize_canonicalized_projection<'tcx>( 0, &mut obligations, ); + obligations.extend(const_arg_has_type_obligation( + tcx, + param_env, + normalized_term, + goal.into(), + )); ocx.register_obligations(obligations); // #112047: With projections and opaques, we are able to create opaques that // are recursive (given some generic parameters of the opaque's type variables). @@ -86,11 +111,17 @@ fn normalize_canonicalized_free_alias<'tcx>( }, ); ocx.register_obligations(obligations); - let normalized_term = if goal.kind.is_type() { + let normalized_term: ty::Term<'tcx> = if goal.kind.is_type() { tcx.type_of(goal.def_id()).instantiate(tcx, goal.args).skip_norm_wip().into() } else { tcx.const_of_item(goal.def_id()).instantiate(tcx, goal.args).skip_norm_wip().into() }; + ocx.register_obligations(const_arg_has_type_obligation( + tcx, + param_env, + normalized_term, + goal.into(), + )); Ok(NormalizationResult { normalized_term }) }, ) @@ -116,6 +147,12 @@ fn normalize_canonicalized_inherent_projection<'tcx>( 0, &mut obligations, ); + obligations.extend(const_arg_has_type_obligation( + tcx, + param_env, + normalized_term, + goal.into(), + )); ocx.register_obligations(obligations); Ok(NormalizationResult { normalized_term }) diff --git a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.current.stderr b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.current.stderr index a734b4062b2a6..8ce226a564b0f 100644 --- a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.current.stderr +++ b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.current.stderr @@ -1,15 +1,17 @@ error: the constant `"this isn't a usize"` is not of type `usize` - --> $DIR/type-const-free-value-type-mismatch.rs:10:1 + --> $DIR/type-const-free-value-type-mismatch.rs:9:1 | LL | type const N: usize = "this isn't a usize"; | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&'static str` -error[E0080]: transmuting from $BYTE-byte type to $BYTE-byte type: `&str` -> `usize` - --> $DIR/type-const-free-value-type-mismatch.rs:13:24 +error[E0308]: mismatched types + --> $DIR/type-const-free-value-type-mismatch.rs:12:11 | LL | fn f() -> [u8; const { N }] {} - | ^ evaluation of `f::{constant#0}` failed here + | - ^^^^^^^^^^^^^^^^^ expected `[u8; const { N }]`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0080`. +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.next.stderr b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.next.stderr index 2fbd629878bfe..c69455b82dd42 100644 --- a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.next.stderr +++ b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.next.stderr @@ -1,17 +1,17 @@ error: the constant `"this isn't a usize"` is not of type `usize` - --> $DIR/type-const-free-value-type-mismatch.rs:10:1 + --> $DIR/type-const-free-value-type-mismatch.rs:9:1 | LL | type const N: usize = "this isn't a usize"; | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&'static str` error[E0284]: type annotations needed: cannot normalize `f::{constant#0}` - --> $DIR/type-const-free-value-type-mismatch.rs:13:11 + --> $DIR/type-const-free-value-type-mismatch.rs:12:11 | LL | fn f() -> [u8; const { N }] {} | ^^^^^^^^^^^^^^^^^ cannot normalize `f::{constant#0}` error[E0308]: mismatched types - --> $DIR/type-const-free-value-type-mismatch.rs:13:11 + --> $DIR/type-const-free-value-type-mismatch.rs:12:11 | LL | fn f() -> [u8; const { N }] {} | - ^^^^^^^^^^^^^^^^^ expected `[u8; _]`, found `()` diff --git a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs index 1b66a5d54f7e6..ad2e584f34938 100644 --- a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs +++ b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs @@ -5,13 +5,12 @@ //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ compile-flags: -Zvalidate-mir -//@ normalize-stderr: "\d+-byte" -> "$$BYTE-byte" type const N: usize = "this isn't a usize"; //~^ ERROR the constant `"this isn't a usize"` is not of type `usize` fn f() -> [u8; const { N }] {} -//[current]~^ ERROR transmuting from +//[current]~^ ERROR mismatched types [E0308] //[next]~^^ ERROR type annotations needed //[next]~| ERROR mismatched types [E0308] From c1cd23675f1c705134f0fa1a4490499b0c98411c Mon Sep 17 00:00:00 2001 From: xmakro Date: Fri, 5 Jun 2026 09:52:21 -0700 Subject: [PATCH 20/59] Attribute post-monomorphization error notes by emitting thread --- compiler/rustc_errors/src/lib.rs | 72 +++++++++++++------- compiler/rustc_monomorphize/src/collector.rs | 4 +- 2 files changed, 51 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 55f10867c9321..c2d09da3b0e82 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -24,6 +24,7 @@ use std::io::Write; use std::num::NonZero; use std::ops::DerefMut; use std::path::{Path, PathBuf}; +use std::thread::ThreadId; use std::{assert_matches, fmt, panic}; use Level::*; @@ -297,11 +298,12 @@ impl<'a> std::ops::Deref for DiagCtxtHandle<'a> { struct DiagCtxtInner { flags: DiagCtxtFlags, - /// The error guarantees from all emitted errors. The length gives the error count. - err_guars: Vec, - /// The error guarantee from all emitted lint errors. The length gives the - /// lint error count. - lint_err_guars: Vec, + /// The error guarantees from all emitted errors, each paired with the + /// thread that emitted it. The length gives the error count. + err_guars: Vec<(ErrorGuaranteed, ThreadId)>, + /// The error guarantee from all emitted lint errors, each paired with the + /// thread that emitted it. The length gives the lint error count. + lint_err_guars: Vec<(ErrorGuaranteed, ThreadId)>, /// The delayed bugs and their error guarantees. delayed_bugs: Vec<(DelayedDiagInner, ErrorGuaranteed)>, @@ -343,7 +345,7 @@ struct DiagCtxtInner { /// `emit_stashed_diagnostics` by the time the `DiagCtxtInner` is dropped, /// otherwise an assertion failure will occur. stashed_diagnostics: - FxIndexMap)>>, + FxIndexMap, ThreadId)>>, future_breakage_diagnostics: Vec, @@ -613,7 +615,7 @@ impl<'a> DiagCtxtHandle<'a> { .stashed_diagnostics .entry(key) .or_default() - .insert(span.with_parent(None), (diag, guar)); + .insert(span.with_parent(None), (diag, guar, std::thread::current().id())); guar } @@ -623,7 +625,7 @@ impl<'a> DiagCtxtHandle<'a> { /// error. pub fn steal_non_err(self, span: Span, key: StashKey) -> Option> { // FIXME(#120456) - is `swap_remove` correct? - let (diag, guar) = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then( + let (diag, guar, _) = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then( |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)), )?; assert!(!diag.is_error()); @@ -648,7 +650,7 @@ impl<'a> DiagCtxtHandle<'a> { let err = self.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then( |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)), ); - err.map(|(err, guar)| { + err.map(|(err, guar, _)| { // The use of `::` is safe because level is `Level::Error`. assert_eq!(err.level, Error); assert!(guar.is_some()); @@ -673,7 +675,7 @@ impl<'a> DiagCtxtHandle<'a> { |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)), ); match old_err { - Some((old_err, guar)) => { + Some((old_err, guar, _)) => { assert_eq!(old_err.level, Error); assert!(guar.is_some()); // Because `old_err` has already been counted, it can only be @@ -710,7 +712,27 @@ impl<'a> DiagCtxtHandle<'a> { + inner .stashed_diagnostics .values() - .map(|a| a.values().filter(|(_, guar)| guar.is_some()).count()) + .map(|a| a.values().filter(|(_, guar, _)| guar.is_some()).count()) + .sum::() + } + + /// The number of errors that have been emitted on the *current thread*. + /// + /// Like [`DiagCtxtHandle::err_count`], but only counts errors whose recorded + /// emitting thread is the calling thread. + pub fn err_count_on_current_thread(&self) -> usize { + let inner = self.inner.borrow(); + let current = std::thread::current().id(); + inner.err_guars.iter().filter(|(_, thread)| *thread == current).count() + + inner.lint_err_guars.iter().filter(|(_, thread)| *thread == current).count() + + inner + .stashed_diagnostics + .values() + .map(|a| { + a.values() + .filter(|(_, guar, thread)| guar.is_some() && *thread == current) + .count() + }) .sum::() } @@ -879,7 +901,8 @@ impl<'a> DiagCtxtHandle<'a> { // This `unchecked_error_guaranteed` is valid. It is where the // `ErrorGuaranteed` for unused_extern errors originates. #[allow(deprecated)] - inner.lint_err_guars.push(ErrorGuaranteed::unchecked_error_guaranteed()); + let guar = ErrorGuaranteed::unchecked_error_guaranteed(); + inner.lint_err_guars.push((guar, std::thread::current().id())); inner.panic_if_treat_err_as_bug(); } @@ -1178,7 +1201,7 @@ impl DiagCtxtInner { let mut guar = None; let has_errors = !self.err_guars.is_empty(); for (_, stashed_diagnostics) in std::mem::take(&mut self.stashed_diagnostics).into_iter() { - for (_, (diag, _guar)) in stashed_diagnostics { + for (_, (diag, _guar, _thread)) in stashed_diagnostics { if !diag.is_error() { // Unless they're forced, don't flush stashed warnings when // there are errors, to avoid causing warning overload. The @@ -1347,13 +1370,14 @@ impl DiagCtxtInner { // `ErrorGuaranteed` for errors and lint errors originates. #[allow(deprecated)] let guar = ErrorGuaranteed::unchecked_error_guaranteed(); + let thread = std::thread::current().id(); if is_lint { - self.lint_err_guars.push(guar); + self.lint_err_guars.push((guar, thread)); } else { if let Some(taint) = taint { taint.set(Some(guar)); } - self.err_guars.push(guar); + self.err_guars.push((guar, thread)); } self.panic_if_treat_err_as_bug(); Some(guar) @@ -1377,12 +1401,12 @@ impl DiagCtxtInner { } fn has_errors_excluding_lint_errors(&self) -> Option { - self.err_guars.get(0).copied().or_else(|| { - if let Some((_diag, guar)) = self + self.err_guars.get(0).map(|(guar, _)| *guar).or_else(|| { + if let Some((_diag, guar, _)) = self .stashed_diagnostics .values() .flat_map(|stashed_diagnostics| stashed_diagnostics.values()) - .find(|(diag, guar)| guar.is_some() && diag.is_lint.is_none()) + .find(|(diag, guar, _)| guar.is_some() && diag.is_lint.is_none()) { *guar } else { @@ -1392,13 +1416,15 @@ impl DiagCtxtInner { } fn has_errors(&self) -> Option { - self.err_guars.get(0).copied().or_else(|| self.lint_err_guars.get(0).copied()).or_else( - || { + self.err_guars + .get(0) + .map(|(guar, _)| *guar) + .or_else(|| self.lint_err_guars.get(0).map(|(guar, _)| *guar)) + .or_else(|| { self.stashed_diagnostics.values().find_map(|stashed_diagnostics| { - stashed_diagnostics.values().find_map(|(_, guar)| *guar) + stashed_diagnostics.values().find_map(|(_, guar, _)| *guar) }) - }, - ) + }) } fn has_errors_or_delayed_bugs(&self) -> Option { diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 9ddd33678c341..8c5a8a625ec99 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -413,7 +413,7 @@ fn collect_items_rec<'tcx>( // current step of mono items collection. // // FIXME: don't rely on global state, instead bubble up errors. Note: this is very hard to do. - let error_count = tcx.dcx().err_count(); + let error_count = tcx.dcx().err_count_on_current_thread(); // In `mentioned_items` we collect items that were mentioned in this MIR but possibly do not // need to be monomorphized. This is done to ensure that optimizing away function calls does not @@ -538,7 +538,7 @@ fn collect_items_rec<'tcx>( // Check for PMEs and emit a diagnostic if one happened. To try to show relevant edges of the // mono item graph. - if tcx.dcx().err_count() > error_count + if tcx.dcx().err_count_on_current_thread() > error_count && starting_item.node.is_generic_fn() && starting_item.node.is_user_defined() { From 2e128c71c8b319347771b0c3332120208028bea9 Mon Sep 17 00:00:00 2001 From: xmakro Date: Fri, 5 Jun 2026 09:52:21 -0700 Subject: [PATCH 21/59] Re-enable parallel frontend tests for post-monomorphization errors --- tests/ui/abi/simd-abi-checks-avx.rs | 2 +- tests/ui/consts/const-eval/index-out-of-bounds-never-type.rs | 2 +- tests/ui/consts/const-eval/issue-50814-2.rs | 2 +- tests/ui/consts/const-eval/issue-50814.rs | 2 +- tests/ui/consts/mono-reachable-invalid-const.rs | 2 +- tests/ui/consts/required-consts/collect-in-called-fn.rs | 2 +- tests/ui/consts/required-consts/collect-in-dead-closure.rs | 2 +- tests/ui/consts/required-consts/collect-in-dead-drop.rs | 2 +- .../required-consts/collect-in-dead-fn-behind-assoc-type.rs | 2 +- .../consts/required-consts/collect-in-dead-fn-behind-generic.rs | 2 +- .../required-consts/collect-in-dead-fn-behind-opaque-type.rs | 2 +- tests/ui/consts/required-consts/collect-in-dead-fn.rs | 2 +- .../ui/consts/required-consts/collect-in-dead-fnptr-in-const.rs | 2 +- tests/ui/consts/required-consts/collect-in-dead-fnptr.rs | 2 +- tests/ui/consts/required-consts/collect-in-dead-forget.rs | 2 +- tests/ui/consts/required-consts/collect-in-dead-move.rs | 2 +- tests/ui/consts/required-consts/collect-in-dead-vtable.rs | 2 +- tests/ui/consts/required-consts/collect-in-promoted-const.rs | 2 +- tests/ui/consts/required-consts/interpret-in-const-called-fn.rs | 2 +- tests/ui/consts/required-consts/interpret-in-promoted.rs | 2 +- tests/ui/consts/required-consts/interpret-in-static.rs | 2 +- tests/ui/inline-const/required-const.rs | 2 +- tests/ui/lint/large_assignments/copy_into_box_rc_arc.rs | 2 +- tests/ui/lint/large_assignments/copy_into_fn.rs | 2 +- tests/ui/lint/large_assignments/inline_mir.rs | 2 +- tests/ui/lint/large_assignments/large_future.rs | 2 +- tests/ui/lint/large_assignments/move_into_fn.rs | 2 +- tests/ui/simd/const-err-trumps-simd-err.rs | 2 +- tests/ui/structs/default-field-values/post-mono.rs | 2 +- 29 files changed, 29 insertions(+), 29 deletions(-) diff --git a/tests/ui/abi/simd-abi-checks-avx.rs b/tests/ui/abi/simd-abi-checks-avx.rs index c68ba2fb5f890..7432381d15b72 100644 --- a/tests/ui/abi/simd-abi-checks-avx.rs +++ b/tests/ui/abi/simd-abi-checks-avx.rs @@ -1,7 +1,7 @@ //@ only-x86_64 //@ build-fail //@ compile-flags: -C target-feature=-avx -//@ ignore-parallel-frontend post-monomorphization errors + #![feature(portable_simd)] #![feature(simd_ffi)] #![allow(improper_ctypes_definitions)] diff --git a/tests/ui/consts/const-eval/index-out-of-bounds-never-type.rs b/tests/ui/consts/const-eval/index-out-of-bounds-never-type.rs index dbe507e3cd137..6777bee050a16 100644 --- a/tests/ui/consts/const-eval/index-out-of-bounds-never-type.rs +++ b/tests/ui/consts/const-eval/index-out-of-bounds-never-type.rs @@ -1,5 +1,5 @@ //@ build-fail -//@ ignore-parallel-frontend post-monomorphization errors + // Regression test for #66975 #![warn(unconditional_panic)] #![feature(never_type)] diff --git a/tests/ui/consts/const-eval/issue-50814-2.rs b/tests/ui/consts/const-eval/issue-50814-2.rs index 34a200e2887b9..1b917a0916da3 100644 --- a/tests/ui/consts/const-eval/issue-50814-2.rs +++ b/tests/ui/consts/const-eval/issue-50814-2.rs @@ -2,7 +2,7 @@ //@ revisions: normal mir-opt //@ [mir-opt]compile-flags: -Zmir-opt-level=4 //@ dont-require-annotations: NOTE -//@ ignore-parallel-frontend post-monomorphization errors + trait C { const BOO: usize; } diff --git a/tests/ui/consts/const-eval/issue-50814.rs b/tests/ui/consts/const-eval/issue-50814.rs index 3901a2c0c9316..011f065ad814b 100644 --- a/tests/ui/consts/const-eval/issue-50814.rs +++ b/tests/ui/consts/const-eval/issue-50814.rs @@ -1,6 +1,6 @@ //@ build-fail //@ dont-require-annotations: NOTE -//@ ignore-parallel-frontend post-monomorphization errors + trait Unsigned { const MAX: u8; } diff --git a/tests/ui/consts/mono-reachable-invalid-const.rs b/tests/ui/consts/mono-reachable-invalid-const.rs index 3d76e4a65a4e2..aba41dabe71f9 100644 --- a/tests/ui/consts/mono-reachable-invalid-const.rs +++ b/tests/ui/consts/mono-reachable-invalid-const.rs @@ -1,5 +1,5 @@ //@ build-fail -//@ ignore-parallel-frontend post-monomorphization errors + struct Bar; impl Bar { diff --git a/tests/ui/consts/required-consts/collect-in-called-fn.rs b/tests/ui/consts/required-consts/collect-in-called-fn.rs index d07c0927a16a9..2045b8266c792 100644 --- a/tests/ui/consts/required-consts/collect-in-called-fn.rs +++ b/tests/ui/consts/required-consts/collect-in-called-fn.rs @@ -4,7 +4,7 @@ //@[opt] compile-flags: -O //! Make sure we detect erroneous constants post-monomorphization even when they are unused. This is //! crucial, people rely on it for soundness. (https://github.com/rust-lang/rust/issues/112090) -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/collect-in-dead-closure.rs b/tests/ui/consts/required-consts/collect-in-dead-closure.rs index 825336e9d3ef3..5f8b6bbb174c4 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-closure.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-closure.rs @@ -3,7 +3,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! This fails without optimizations, so it should also fail with optimizations. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/collect-in-dead-drop.rs b/tests/ui/consts/required-consts/collect-in-dead-drop.rs index fa9b8730c11c9..f7293d162df7b 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-drop.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-drop.rs @@ -3,7 +3,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! This fails without optimizations, so it should also fail with optimizations. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-assoc-type.rs b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-assoc-type.rs index a76481b673132..e6be9f56cb7a0 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-assoc-type.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-assoc-type.rs @@ -4,7 +4,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! This fails without optimizations, so it should also fail with optimizations. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-generic.rs b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-generic.rs index 4fe05db34d78e..a86902af52677 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-generic.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-generic.rs @@ -3,7 +3,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! This fails without optimizations, so it should also fail with optimizations. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-opaque-type.rs b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-opaque-type.rs index a6132ef1fe07e..4cdb27413540f 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-opaque-type.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-opaque-type.rs @@ -4,7 +4,7 @@ //@[opt] compile-flags: -O //! This fails without optimizations, so it should also fail with optimizations. #![feature(type_alias_impl_trait)] -//@ ignore-parallel-frontend post-monomorphization errors + mod m { struct Fail(T); impl Fail { diff --git a/tests/ui/consts/required-consts/collect-in-dead-fn.rs b/tests/ui/consts/required-consts/collect-in-dead-fn.rs index f4627323249d4..0c4795801068d 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fn.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-fn.rs @@ -3,7 +3,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! This fails without optimizations, so it should also fail with optimizations. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/collect-in-dead-fnptr-in-const.rs b/tests/ui/consts/required-consts/collect-in-dead-fnptr-in-const.rs index 8808a4e26f0cb..04544cb413984 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fnptr-in-const.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-fnptr-in-const.rs @@ -3,7 +3,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! This fails without optimizations, so it should also fail with optimizations. -//@ ignore-parallel-frontend post-monomorphization errors + struct Late(T); impl Late { const FAIL: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/collect-in-dead-fnptr.rs b/tests/ui/consts/required-consts/collect-in-dead-fnptr.rs index 1a9b99f9868f6..4cdb50f4385a1 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fnptr.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-fnptr.rs @@ -3,7 +3,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! This fails without optimizations, so it should also fail with optimizations. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/collect-in-dead-forget.rs b/tests/ui/consts/required-consts/collect-in-dead-forget.rs index bc717edbe73ee..7586004116c36 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-forget.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-forget.rs @@ -3,7 +3,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! This passes without optimizations, so it can (and should) also pass with optimizations. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); diff --git a/tests/ui/consts/required-consts/collect-in-dead-move.rs b/tests/ui/consts/required-consts/collect-in-dead-move.rs index 05491136e8d5e..4e2d959db32c7 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-move.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-move.rs @@ -3,7 +3,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! This fails without optimizations, so it should also fail with optimizations. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/collect-in-dead-vtable.rs b/tests/ui/consts/required-consts/collect-in-dead-vtable.rs index 1ca52064a3fdd..d4ad730837730 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-vtable.rs +++ b/tests/ui/consts/required-consts/collect-in-dead-vtable.rs @@ -3,7 +3,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! This fails without optimizations, so it should also fail with optimizations. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/collect-in-promoted-const.rs b/tests/ui/consts/required-consts/collect-in-promoted-const.rs index 415f22fd05dda..c475720938697 100644 --- a/tests/ui/consts/required-consts/collect-in-promoted-const.rs +++ b/tests/ui/consts/required-consts/collect-in-promoted-const.rs @@ -3,7 +3,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! Make sure we error on erroneous consts even if they get promoted. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR evaluation panicked: explicit panic diff --git a/tests/ui/consts/required-consts/interpret-in-const-called-fn.rs b/tests/ui/consts/required-consts/interpret-in-const-called-fn.rs index 2d63c620a0384..9309457e22a46 100644 --- a/tests/ui/consts/required-consts/interpret-in-const-called-fn.rs +++ b/tests/ui/consts/required-consts/interpret-in-const-called-fn.rs @@ -2,7 +2,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! Make sure we error on erroneous consts even if they are unused. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR explicit panic diff --git a/tests/ui/consts/required-consts/interpret-in-promoted.rs b/tests/ui/consts/required-consts/interpret-in-promoted.rs index cbb1a309006c5..b223e6d16aa12 100644 --- a/tests/ui/consts/required-consts/interpret-in-promoted.rs +++ b/tests/ui/consts/required-consts/interpret-in-promoted.rs @@ -2,7 +2,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //@ dont-require-annotations: NOTE -//@ ignore-parallel-frontend post-monomorphization errors + //! Make sure we evaluate const fn calls even if they get promoted and their result ignored. const unsafe fn ub() { diff --git a/tests/ui/consts/required-consts/interpret-in-static.rs b/tests/ui/consts/required-consts/interpret-in-static.rs index edc7b1d01fd6c..19ad6be1c9fa7 100644 --- a/tests/ui/consts/required-consts/interpret-in-static.rs +++ b/tests/ui/consts/required-consts/interpret-in-static.rs @@ -2,7 +2,7 @@ //@[noopt] compile-flags: -Copt-level=0 //@[opt] compile-flags: -O //! Make sure we error on erroneous consts even if they are unused. -//@ ignore-parallel-frontend post-monomorphization errors + struct Fail(T); impl Fail { const C: () = panic!(); //~ERROR explicit panic diff --git a/tests/ui/inline-const/required-const.rs b/tests/ui/inline-const/required-const.rs index 437652532ec54..8f640e933d019 100644 --- a/tests/ui/inline-const/required-const.rs +++ b/tests/ui/inline-const/required-const.rs @@ -1,6 +1,6 @@ //@ build-fail //@ compile-flags: -Zmir-opt-level=3 -//@ ignore-parallel-frontend post-monomorphization errors + fn foo() { if false { const { panic!() } //~ ERROR E0080 diff --git a/tests/ui/lint/large_assignments/copy_into_box_rc_arc.rs b/tests/ui/lint/large_assignments/copy_into_box_rc_arc.rs index a8e23c0246eeb..dfa0b8015d037 100644 --- a/tests/ui/lint/large_assignments/copy_into_box_rc_arc.rs +++ b/tests/ui/lint/large_assignments/copy_into_box_rc_arc.rs @@ -3,7 +3,7 @@ #![move_size_limit = "1000"] //@ build-fail //@ only-64bit -//@ ignore-parallel-frontend post-monomorphization errors + //@ edition:2018 //@ compile-flags: -Zmir-opt-level=1 diff --git a/tests/ui/lint/large_assignments/copy_into_fn.rs b/tests/ui/lint/large_assignments/copy_into_fn.rs index 8f8e7f0822bbc..5222e833bcc8f 100644 --- a/tests/ui/lint/large_assignments/copy_into_fn.rs +++ b/tests/ui/lint/large_assignments/copy_into_fn.rs @@ -1,5 +1,5 @@ //@ build-fail -//@ ignore-parallel-frontend post-monomorphization errors + #![feature(large_assignments)] #![move_size_limit = "1000"] #![deny(large_assignments)] diff --git a/tests/ui/lint/large_assignments/inline_mir.rs b/tests/ui/lint/large_assignments/inline_mir.rs index 68c5de4902f34..d16aae6ab145b 100644 --- a/tests/ui/lint/large_assignments/inline_mir.rs +++ b/tests/ui/lint/large_assignments/inline_mir.rs @@ -13,7 +13,7 @@ //! ``` //! //! We want the diagnostics to point to the relevant user code. -//@ ignore-parallel-frontend post-monomorphization errors + //@ build-fail //@ compile-flags: -Zmir-opt-level=1 -Zinline-mir diff --git a/tests/ui/lint/large_assignments/large_future.rs b/tests/ui/lint/large_assignments/large_future.rs index 1be66f16313bb..28c358bdbf086 100644 --- a/tests/ui/lint/large_assignments/large_future.rs +++ b/tests/ui/lint/large_assignments/large_future.rs @@ -5,7 +5,7 @@ //@ only-64bit //@ revisions: attribute option //@ [option]compile-flags: -Zmove-size-limit=1000 -//@ ignore-parallel-frontend post-monomorphization errors + //@ edition:2018 //@ compile-flags: -Zmir-opt-level=0 diff --git a/tests/ui/lint/large_assignments/move_into_fn.rs b/tests/ui/lint/large_assignments/move_into_fn.rs index 1e793a082e3ea..b3b2160ca36e1 100644 --- a/tests/ui/lint/large_assignments/move_into_fn.rs +++ b/tests/ui/lint/large_assignments/move_into_fn.rs @@ -1,5 +1,5 @@ //@ build-fail -//@ ignore-parallel-frontend post-monomorphization errors + #![feature(large_assignments)] #![move_size_limit = "1000"] #![deny(large_assignments)] diff --git a/tests/ui/simd/const-err-trumps-simd-err.rs b/tests/ui/simd/const-err-trumps-simd-err.rs index 282d5dabf72fa..33f0abb06f3ea 100644 --- a/tests/ui/simd/const-err-trumps-simd-err.rs +++ b/tests/ui/simd/const-err-trumps-simd-err.rs @@ -1,6 +1,6 @@ //@build-fail //@ dont-require-annotations: NOTE -//@ ignore-parallel-frontend post-monomorphization errors + //! Make sure that monomorphization-time const errors from `static_assert` take priority over the //! error from simd_extract. Basically this checks that if a const fails to evaluate in some //! function, we don't bother codegen'ing the function. diff --git a/tests/ui/structs/default-field-values/post-mono.rs b/tests/ui/structs/default-field-values/post-mono.rs index 57092083ca102..68dfa391bb485 100644 --- a/tests/ui/structs/default-field-values/post-mono.rs +++ b/tests/ui/structs/default-field-values/post-mono.rs @@ -1,6 +1,6 @@ //@ build-fail //@ revisions: direct indirect -//@ ignore-parallel-frontend post-monomorphization errors + #![feature(default_field_values)] struct Z { From e777ac31403cb85288d2852c60f8c1a35183d5ac Mon Sep 17 00:00:00 2001 From: lapla Date: Sat, 6 Jun 2026 19:38:16 +0900 Subject: [PATCH 22/59] Explain why we register `ConstArgHasType` in `instantiate_normalizes_to_term` --- .../src/solve/normalizes_to/mod.rs | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 07ad13fc1b135..f36b6017b162b 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -123,8 +123,25 @@ where /// emit nested `AliasRelate` goals to structurally normalize the alias. /// /// Additionally, when `term` is a const, this registers a `ConstArgHasType` - /// goal to ensure that the const value's type matches the type of the - /// alias it was normalized from, preventing ICEs from type mismatches. + /// goal to ensure that the const value's type matches the declared type of + /// the alias it was normalized from. + /// + /// You may reasonably wonder: shouldn't `wfcheck::check_type_const` already + /// catch any such type mismatch at the definition site, so that the + /// definition is tainted and we never even attempt to normalize a reference + /// to it? In principle that's exactly what should happen. However, we cannot + /// simply force the defining item's wfcheck to run before all uses are + /// normalized: wfcheck itself may depend on typeck, trait solving, and + /// normalization, so enforcing such a strict ordering would easily create + /// query cycles. + /// + /// However, when CTFE runs on a MIR body, normalizing a type const within + /// that body can change the type of the resulting value, causing the MIR + /// to become ill-formed. If `check_type_const` for that alias has not yet + /// reported its error, no prior error has been recorded and MIR validation + /// fires a `span_bug!`. Registering the obligation here ensures the type + /// mismatch is reported during normalization itself, tainting the MIR + /// before validation runs. pub fn instantiate_normalizes_to_term( &mut self, goal: Goal>, From fa11f19f1620634935f1759927fea47e77b5c0a2 Mon Sep 17 00:00:00 2001 From: lapla Date: Mon, 8 Jun 2026 19:00:21 +0900 Subject: [PATCH 23/59] Add `type-const-free-value-used-in-body.rs` regression test --- .../mgca/type-const-free-value-used-in-body.rs | 16 ++++++++++++++++ .../type-const-free-value-used-in-body.stderr | 14 ++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 tests/ui/const-generics/mgca/type-const-free-value-used-in-body.rs create mode 100644 tests/ui/const-generics/mgca/type-const-free-value-used-in-body.stderr diff --git a/tests/ui/const-generics/mgca/type-const-free-value-used-in-body.rs b/tests/ui/const-generics/mgca/type-const-free-value-used-in-body.rs new file mode 100644 index 0000000000000..90740e191807d --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-free-value-used-in-body.rs @@ -0,0 +1,16 @@ +// Regression test for https://github.com/rust-lang/rust/issues/154748 and https://github.com/rust-lang/rust/issues/154750 + +#![feature(min_generic_const_args)] + +//@ compile-flags: --emit=mir + +type const CONST: usize = 1u32; +//~^ ERROR the constant `1` is not of type `usize` + +type const S: bool = 1i32; +//~^ ERROR the constant `1` is not of type `bool` + +fn main() { + CONST; + S; +} diff --git a/tests/ui/const-generics/mgca/type-const-free-value-used-in-body.stderr b/tests/ui/const-generics/mgca/type-const-free-value-used-in-body.stderr new file mode 100644 index 0000000000000..759efca661303 --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-free-value-used-in-body.stderr @@ -0,0 +1,14 @@ +error: the constant `1` is not of type `usize` + --> $DIR/type-const-free-value-used-in-body.rs:7:1 + | +LL | type const CONST: usize = 1u32; + | ^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `u32` + +error: the constant `1` is not of type `bool` + --> $DIR/type-const-free-value-used-in-body.rs:10:1 + | +LL | type const S: bool = 1i32; + | ^^^^^^^^^^^^^^^^^^ expected `bool`, found `i32` + +error: aborting due to 2 previous errors + From 277dcccbaf122a99452f21e528ee4c9d6b392f2f Mon Sep 17 00:00:00 2001 From: lapla Date: Mon, 8 Jun 2026 19:02:48 +0900 Subject: [PATCH 24/59] Remove no longer needed `#![expect(incomplete_features)]` --- .../mgca/type-const-free-anon-const-mismatch.rs | 1 - .../mgca/type-const-free-anon-const-mismatch.stderr | 4 ++-- .../type-const-free-value-type-mismatch.current.stderr | 4 ++-- .../mgca/type-const-free-value-type-mismatch.next.stderr | 6 +++--- .../mgca/type-const-free-value-type-mismatch.rs | 1 - ...type-const-inherent-value-type-mismatch.current.stderr | 4 ++-- .../type-const-inherent-value-type-mismatch.next.stderr | 6 +++--- .../mgca/type-const-inherent-value-type-mismatch.rs | 1 - .../mgca/type-const-value-type-mismatch.current.stderr | 8 ++++---- .../mgca/type-const-value-type-mismatch.next.stderr | 8 ++++---- .../const-generics/mgca/type-const-value-type-mismatch.rs | 1 - 11 files changed, 20 insertions(+), 24 deletions(-) diff --git a/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.rs b/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.rs index 906bd5e7ef912..2332c97a70ee8 100644 --- a/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.rs +++ b/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.rs @@ -1,7 +1,6 @@ //@ compile-flags: -Zvalidate-mir -Znext-solver #![feature(min_generic_const_args)] -#![expect(incomplete_features)] type const X: usize = const { N }; //~^ ERROR type annotations needed diff --git a/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.stderr b/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.stderr index 0718b739cad0e..482a241b43c75 100644 --- a/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.stderr +++ b/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.stderr @@ -1,11 +1,11 @@ error[E0284]: type annotations needed: cannot normalize `X::{constant#0}` - --> $DIR/type-const-free-anon-const-mismatch.rs:6:1 + --> $DIR/type-const-free-anon-const-mismatch.rs:5:1 | LL | type const X: usize = const { N }; | ^^^^^^^^^^^^^^^^^^^ cannot normalize `X::{constant#0}` error: the constant `"this isn't a usize"` is not of type `usize` - --> $DIR/type-const-free-anon-const-mismatch.rs:9:1 + --> $DIR/type-const-free-anon-const-mismatch.rs:8:1 | LL | type const N: usize = "this isn't a usize"; | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&'static str` diff --git a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.current.stderr b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.current.stderr index 8ce226a564b0f..28f7064d99325 100644 --- a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.current.stderr +++ b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.current.stderr @@ -1,11 +1,11 @@ error: the constant `"this isn't a usize"` is not of type `usize` - --> $DIR/type-const-free-value-type-mismatch.rs:9:1 + --> $DIR/type-const-free-value-type-mismatch.rs:8:1 | LL | type const N: usize = "this isn't a usize"; | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&'static str` error[E0308]: mismatched types - --> $DIR/type-const-free-value-type-mismatch.rs:12:11 + --> $DIR/type-const-free-value-type-mismatch.rs:11:11 | LL | fn f() -> [u8; const { N }] {} | - ^^^^^^^^^^^^^^^^^ expected `[u8; const { N }]`, found `()` diff --git a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.next.stderr b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.next.stderr index c69455b82dd42..171969b7efb9b 100644 --- a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.next.stderr +++ b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.next.stderr @@ -1,17 +1,17 @@ error: the constant `"this isn't a usize"` is not of type `usize` - --> $DIR/type-const-free-value-type-mismatch.rs:9:1 + --> $DIR/type-const-free-value-type-mismatch.rs:8:1 | LL | type const N: usize = "this isn't a usize"; | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&'static str` error[E0284]: type annotations needed: cannot normalize `f::{constant#0}` - --> $DIR/type-const-free-value-type-mismatch.rs:12:11 + --> $DIR/type-const-free-value-type-mismatch.rs:11:11 | LL | fn f() -> [u8; const { N }] {} | ^^^^^^^^^^^^^^^^^ cannot normalize `f::{constant#0}` error[E0308]: mismatched types - --> $DIR/type-const-free-value-type-mismatch.rs:12:11 + --> $DIR/type-const-free-value-type-mismatch.rs:11:11 | LL | fn f() -> [u8; const { N }] {} | - ^^^^^^^^^^^^^^^^^ expected `[u8; _]`, found `()` diff --git a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs index ad2e584f34938..50661eb6f7e10 100644 --- a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs +++ b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs @@ -1,5 +1,4 @@ #![feature(min_generic_const_args)] -#![expect(incomplete_features)] //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) diff --git a/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.current.stderr b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.current.stderr index bf34bcaf9fc9c..bfcc9a8fef63c 100644 --- a/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.current.stderr +++ b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.current.stderr @@ -1,11 +1,11 @@ error: the constant `"this isn't a usize"` is not of type `usize` - --> $DIR/type-const-inherent-value-type-mismatch.rs:14:5 + --> $DIR/type-const-inherent-value-type-mismatch.rs:13:5 | LL | type const N: usize = "this isn't a usize"; | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&'static str` error[E0308]: mismatched types - --> $DIR/type-const-inherent-value-type-mismatch.rs:18:11 + --> $DIR/type-const-inherent-value-type-mismatch.rs:17:11 | LL | fn f() -> [u8; const { Struct::N }] {} | - ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `[u8; const { Struct::N }]`, found `()` diff --git a/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.next.stderr b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.next.stderr index 5d0b81f4a3e0d..812bce07c1e3c 100644 --- a/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.next.stderr +++ b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.next.stderr @@ -1,17 +1,17 @@ error[E0284]: type annotations needed: cannot normalize `f::{constant#0}` - --> $DIR/type-const-inherent-value-type-mismatch.rs:18:11 + --> $DIR/type-const-inherent-value-type-mismatch.rs:17:11 | LL | fn f() -> [u8; const { Struct::N }] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `f::{constant#0}` error: the constant `"this isn't a usize"` is not of type `usize` - --> $DIR/type-const-inherent-value-type-mismatch.rs:14:5 + --> $DIR/type-const-inherent-value-type-mismatch.rs:13:5 | LL | type const N: usize = "this isn't a usize"; | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&'static str` error[E0308]: mismatched types - --> $DIR/type-const-inherent-value-type-mismatch.rs:18:11 + --> $DIR/type-const-inherent-value-type-mismatch.rs:17:11 | LL | fn f() -> [u8; const { Struct::N }] {} | - ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `[u8; _]`, found `()` diff --git a/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.rs b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.rs index 1f00b4410c4d7..ad6d551968b03 100644 --- a/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.rs +++ b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.rs @@ -6,7 +6,6 @@ //@ compile-flags: -Zvalidate-mir #![feature(min_generic_const_args)] -#![expect(incomplete_features)] struct Struct; diff --git a/tests/ui/const-generics/mgca/type-const-value-type-mismatch.current.stderr b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.current.stderr index 7ce0513c91d13..7c4b0f58fb98b 100644 --- a/tests/ui/const-generics/mgca/type-const-value-type-mismatch.current.stderr +++ b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.current.stderr @@ -1,11 +1,11 @@ error[E0053]: method `arr` has an incompatible type for trait - --> $DIR/type-const-value-type-mismatch.rs:22:5 + --> $DIR/type-const-value-type-mismatch.rs:21:5 | LL | fn arr() -> [u8; const { Self::LEN }] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an array with a size of 0, found one with a size of const { Self::LEN } | note: type in trait - --> $DIR/type-const-value-type-mismatch.rs:15:5 + --> $DIR/type-const-value-type-mismatch.rs:14:5 | LL | fn arr() -> [u8; Self::LEN]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,13 +13,13 @@ LL | fn arr() -> [u8; Self::LEN]; found signature `fn() -> [u8; const { Self::LEN }]` error: the constant `0` is not of type `usize` - --> $DIR/type-const-value-type-mismatch.rs:19:5 + --> $DIR/type-const-value-type-mismatch.rs:18:5 | LL | type const LEN: usize = 0u8; | ^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `u8` error[E0308]: mismatched types - --> $DIR/type-const-value-type-mismatch.rs:22:17 + --> $DIR/type-const-value-type-mismatch.rs:21:17 | LL | fn arr() -> [u8; const { Self::LEN }] {} | --- ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `[u8; const { Self::LEN }]`, found `()` diff --git a/tests/ui/const-generics/mgca/type-const-value-type-mismatch.next.stderr b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.next.stderr index 77885cbcfecde..a172367ea0980 100644 --- a/tests/ui/const-generics/mgca/type-const-value-type-mismatch.next.stderr +++ b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.next.stderr @@ -1,23 +1,23 @@ error[E0271]: type mismatch resolving `::LEN normalizes-to 0` - --> $DIR/type-const-value-type-mismatch.rs:22:5 + --> $DIR/type-const-value-type-mismatch.rs:21:5 | LL | fn arr() -> [u8; const { Self::LEN }] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ error: the constant `0` is not of type `usize` - --> $DIR/type-const-value-type-mismatch.rs:19:5 + --> $DIR/type-const-value-type-mismatch.rs:18:5 | LL | type const LEN: usize = 0u8; | ^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `u8` error[E0284]: type annotations needed: cannot normalize `::arr::{constant#0}` - --> $DIR/type-const-value-type-mismatch.rs:22:17 + --> $DIR/type-const-value-type-mismatch.rs:21:17 | LL | fn arr() -> [u8; const { Self::LEN }] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `::arr::{constant#0}` error[E0308]: mismatched types - --> $DIR/type-const-value-type-mismatch.rs:22:17 + --> $DIR/type-const-value-type-mismatch.rs:21:17 | LL | fn arr() -> [u8; const { Self::LEN }] {} | --- ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `[u8; _]`, found `()` diff --git a/tests/ui/const-generics/mgca/type-const-value-type-mismatch.rs b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.rs index 273e7e340fef1..d5a4d963b755f 100644 --- a/tests/ui/const-generics/mgca/type-const-value-type-mismatch.rs +++ b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.rs @@ -6,7 +6,6 @@ //@ compile-flags: -Zvalidate-mir #![feature(min_generic_const_args)] -#![expect(incomplete_features)] pub struct A; From 3ecbb3978a796b1df5b6af19cf79ebd8c4fcf4da Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 8 Jun 2026 14:35:24 +0200 Subject: [PATCH 25/59] Update `browser-ui-test` version to `0.24.0` --- package.json | 2 +- yarn.lock | 1104 ++++++++++---------------------------------------- 2 files changed, 218 insertions(+), 888 deletions(-) diff --git a/package.json b/package.json index 9e9bfd7b1e208..a4f6e18bcf422 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "dependencies": { - "browser-ui-test": "^0.23.5", + "browser-ui-test": "^0.24.0", "es-check": "^9.4.4", "eslint": "^8.57.1", "typescript": "^5.8.3" diff --git a/yarn.lock b/yarn.lock index a027ec6304b9c..cd35ba9089e46 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,49 +2,21 @@ # yarn lockfile v1 -"@babel/code-frame@^7.0.0": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be" - integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg== - dependencies: - "@babel/helper-validator-identifier" "^7.27.1" - js-tokens "^4.0.0" - picocolors "^1.1.1" - -"@babel/helper-validator-identifier@^7.27.1": - version "7.28.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz#010b6938fab7cb7df74aa2bbc06aa503b8fe5fb4" - integrity sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q== - -"@colors/colors@1.6.0", "@colors/colors@^1.6.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.6.0.tgz#ec6cd237440700bc23ca23087f513c75508958b0" - integrity sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA== - -"@dabh/diagnostics@^2.0.2": - version "2.0.8" - resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.8.tgz#ead97e72ca312cf0e6dd7af0d300b58993a31a5e" - integrity sha512-R4MSXTVnuMzGD7bzHdW2ZhhdPC/igELENcq5IjEverBvq5hn1SXCWcsi6eSsdWP0/Ur+SItRRjAktmdoX/8R/Q== - dependencies: - "@so-ric/colorspace" "^1.1.6" - enabled "2.0.x" - kuler "^2.0.0" - "@eslint-community/eslint-utils@^4.2.0": - version "4.9.0" - resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz#7308df158e064f0dd8b8fdb58aa14fa2a7f913b3" - integrity sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g== + version "4.9.1" + resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz" + integrity sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ== dependencies: eslint-visitor-keys "^3.4.3" "@eslint-community/regexpp@^4.6.1": version "4.12.2" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.2.tgz#bccdf615bcf7b6e8db830ec0b8d21c9a25de597b" + resolved "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz" integrity sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew== "@eslint/eslintrc@^2.1.4": version "2.1.4" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" + resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz" integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== dependencies: ajv "^6.12.4" @@ -59,12 +31,12 @@ "@eslint/js@8.57.1": version "8.57.1" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.1.tgz#de633db3ec2ef6a3c89e2f19038063e8a122e2c2" + resolved "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz" integrity sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q== "@humanwhocodes/config-array@^0.13.0": version "0.13.0" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.13.0.tgz#fb907624df3256d04b9aa2df50d7aa97ec648748" + resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz" integrity sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw== dependencies: "@humanwhocodes/object-schema" "^2.0.3" @@ -73,17 +45,17 @@ "@humanwhocodes/module-importer@^1.0.1": version "1.0.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + resolved "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz" integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== "@humanwhocodes/object-schema@^2.0.3": version "2.0.3" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" + resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz" integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== "@nodelib/fs.scandir@2.1.5": version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== dependencies: "@nodelib/fs.stat" "2.0.5" @@ -91,93 +63,44 @@ "@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== "@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== dependencies: "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@puppeteer/browsers@2.13.0": - version "2.13.0" - resolved "https://registry.yarnpkg.com/@puppeteer/browsers/-/browsers-2.13.0.tgz#10f980c6d65efeff77f8a3cac6e1a7ac10604500" - integrity sha512-46BZJYJjc/WwmKjsvDFykHtXrtomsCIrwYQPOP7VfMJoZY2bsDF9oROBABR3paDjDcmkUye1Pb1BqdcdiipaWA== +"@puppeteer/browsers@3.0.4": + version "3.0.4" + resolved "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-3.0.4.tgz" + integrity sha512-HGM8iAmGTf+Y7t0373szVbTmt3d7vPkYL/1bpOkOFO0YUYLgSeuYBCzESklogNPvOBnZ/MRD5f07OkpqH1trtA== dependencies: - debug "^4.4.3" - extract-zip "^2.0.1" - progress "^2.0.3" - proxy-agent "^6.5.0" - semver "^7.7.4" - tar-fs "^3.1.1" + modern-tar "^0.7.6" yargs "^17.7.2" -"@so-ric/colorspace@^1.1.6": - version "1.1.6" - resolved "https://registry.yarnpkg.com/@so-ric/colorspace/-/colorspace-1.1.6.tgz#62515d8b9f27746b76950a83bde1af812d91923b" - integrity sha512-/KiKkpHNOBgkFJwu9sh48LkHSMYGyuTcSFK/qMBdnOAlrRJzRSXAOFB5qwzaVQuDl8wAvHVMkaASQDReTahxuw== - dependencies: - color "^5.0.2" - text-hex "1.0.x" - -"@tootallnate/quickjs-emscripten@^0.23.0": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz#db4ecfd499a9765ab24002c3b696d02e6d32a12c" - integrity sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA== - -"@types/node@*": - version "24.10.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-24.10.0.tgz#6b79086b0dfc54e775a34ba8114dcc4e0221f31f" - integrity sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A== - dependencies: - undici-types "~7.16.0" - -"@types/triple-beam@^1.3.2": - version "1.3.5" - resolved "https://registry.yarnpkg.com/@types/triple-beam/-/triple-beam-1.3.5.tgz#74fef9ffbaa198eb8b588be029f38b00299caa2c" - integrity sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw== - -"@types/yauzl@^2.9.1": - version "2.10.3" - resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.10.3.tgz#e9b2808b4f109504a03cda958259876f61017999" - integrity sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q== - dependencies: - "@types/node" "*" - "@ungap/structured-clone@^1.2.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.3.0.tgz#d06bbb384ebcf6c505fde1c3d0ed4ddffe0aaff8" - integrity sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g== + version "1.3.1" + resolved "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.1.tgz" + integrity sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ== acorn-jsx@^5.3.2: version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn-walk@^8.3.4: - version "8.3.4" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.4.tgz#794dd169c3977edf4ba4ea47583587c5866236b7" - integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g== - dependencies: - acorn "^8.11.0" - -acorn@8.15.0, acorn@^8.11.0, acorn@^8.9.0: - version "8.15.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" - integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== - -agent-base@^7.1.0, agent-base@^7.1.2: - version "7.1.4" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.4.tgz#e3cd76d4c548ee895d3c3fd8dc1f6c5b9032e7a8" - integrity sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ== +acorn@8.16.0, acorn@^8.9.0: + version "8.16.0" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz" + integrity sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw== ajv@^6.12.4: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + version "6.15.0" + resolved "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz" + integrity sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw== dependencies: fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" @@ -186,165 +109,75 @@ ajv@^6.12.4: ansi-regex@^5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: color-convert "^2.0.1" argparse@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== -ast-types@^0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.4.tgz#ee0d77b343263965ecc3fb62da16e7222b2b6782" - integrity sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w== - dependencies: - tslib "^2.0.1" - -async@^3.2.3: - version "3.2.6" - resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce" - integrity sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA== - -b4a@^1.6.4: - version "1.7.3" - resolved "https://registry.yarnpkg.com/b4a/-/b4a-1.7.3.tgz#24cf7ccda28f5465b66aec2bac69e32809bf112f" - integrity sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q== - balanced-match@^1.0.0: version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -bare-events@^2.5.4, bare-events@^2.7.0: - version "2.8.2" - resolved "https://registry.yarnpkg.com/bare-events/-/bare-events-2.8.2.tgz#7b3e10bd8e1fc80daf38bb516921678f566ab89f" - integrity sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ== - -bare-fs@^4.0.1: - version "4.5.0" - resolved "https://registry.yarnpkg.com/bare-fs/-/bare-fs-4.5.0.tgz#f3227b4bc79a65ca7e91a1c05be5919c7c7d8340" - integrity sha512-GljgCjeupKZJNetTqxKaQArLK10vpmK28or0+RwWjEl5Rk+/xG3wkpmkv+WrcBm3q1BwHKlnhXzR8O37kcvkXQ== - dependencies: - bare-events "^2.5.4" - bare-path "^3.0.0" - bare-stream "^2.6.4" - bare-url "^2.2.2" - fast-fifo "^1.3.2" - -bare-os@^3.0.1: - version "3.6.2" - resolved "https://registry.yarnpkg.com/bare-os/-/bare-os-3.6.2.tgz#b3c4f5ad5e322c0fd0f3c29fc97d19009e2796e5" - integrity sha512-T+V1+1srU2qYNBmJCXZkUY5vQ0B4FSlL3QDROnKQYOqeiQR8UbjNHlPa+TIbM4cuidiN9GaTaOZgSEgsvPbh5A== - -bare-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bare-path/-/bare-path-3.0.0.tgz#b59d18130ba52a6af9276db3e96a2e3d3ea52178" - integrity sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw== - dependencies: - bare-os "^3.0.1" - -bare-stream@^2.6.4: - version "2.7.0" - resolved "https://registry.yarnpkg.com/bare-stream/-/bare-stream-2.7.0.tgz#5b9e7dd0a354d06e82d6460c426728536c35d789" - integrity sha512-oyXQNicV1y8nc2aKffH+BUHFRXmx6VrPzlnaEvMhram0nPBrKcEdcyBg5r08D0i8VxngHFAiVyn1QKXpSG0B8A== - dependencies: - streamx "^2.21.0" - -bare-url@^2.2.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/bare-url/-/bare-url-2.3.2.tgz#4aef382efa662b2180a6fe4ca07a71b39bdf7ca3" - integrity sha512-ZMq4gd9ngV5aTMa5p9+UfY0b3skwhHELaDkhEHetMdX0LRkW9kzaym4oo/Eh+Ghm0CCDuMTsRIGM/ytUc1ZYmw== - dependencies: - bare-path "^3.0.0" - -baseline-browser-mapping@^2.8.19: - version "2.8.25" - resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.8.25.tgz#947dc6f81778e0fa0424a2ab9ea09a3033e71109" - integrity sha512-2NovHVesVF5TXefsGX1yzx1xgr7+m9JQenvz6FQY3qd+YXkKkYiv+vTCc7OriP9mcDZpTC5mAOYN4ocd29+erA== - -basic-ftp@^5.0.2: - version "5.0.5" - resolved "https://registry.yarnpkg.com/basic-ftp/-/basic-ftp-5.0.5.tgz#14a474f5fffecca1f4f406f1c26b18f800225ac0" - integrity sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg== - brace-expansion@^1.1.7: - version "1.1.12" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" - integrity sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg== + version "1.1.15" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz" + integrity sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" braces@^3.0.3: version "3.0.3" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + resolved "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz" integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== dependencies: fill-range "^7.1.1" -browser-ui-test@^0.23.5: - version "0.23.5" - resolved "https://registry.yarnpkg.com/browser-ui-test/-/browser-ui-test-0.23.5.tgz#f8fab778a1e00f339f53bb44e76ad14c5b57ce4f" - integrity sha512-S4ztxfOa3vSqV86xS6huIrA8MKSrSqfZUFJfAgEN29U17eRtrYQt/ZGKYJBUP5sv5UYH6ZgnE05z8+Werm/8sw== +browser-ui-test@^0.24.0: + version "0.24.0" + resolved "https://registry.npmjs.org/browser-ui-test/-/browser-ui-test-0.24.0.tgz" + integrity sha512-jVpAdq/M1cCHG/2K6pAS8NUYJ6BcNSHune72JOheeoASk+oLuGcWcY1SalYAdkWet3dlyfUSyKKtq+DDjYgdVg== dependencies: css-unit-converter "^1.1.2" pngjs "^3.4.0" - puppeteer "^24.31.0" + puppeteer "^25.1.0" readline-sync "^1.4.10" -browserslist@^4.23.3: - version "4.27.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.27.0.tgz#755654744feae978fbb123718b2f139bc0fa6697" - integrity sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw== - dependencies: - baseline-browser-mapping "^2.8.19" - caniuse-lite "^1.0.30001751" - electron-to-chromium "^1.5.238" - node-releases "^2.0.26" - update-browserslist-db "^1.1.4" - -buffer-crc32@~0.2.3: - version "0.2.13" - resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" - integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ== - callsites@^3.0.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -caniuse-lite@^1.0.30001751: - version "1.0.30001754" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001754.tgz#7758299d9a72cce4e6b038788a15b12b44002759" - integrity sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg== - chalk@^4.0.0: version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== dependencies: ansi-styles "^4.1.0" supports-color "^7.1.0" -chromium-bidi@14.0.0: - version "14.0.0" - resolved "https://registry.yarnpkg.com/chromium-bidi/-/chromium-bidi-14.0.0.tgz#15a12ab083ae519a49a724e94994ca0a9ced9c8e" - integrity sha512-9gYlLtS6tStdRWzrtXaTMnqcM4dudNegMXJxkR0I/CXObHalYeYcAMPrL19eroNZHtJ8DQmu1E+ZNOYu/IXMXw== +chromium-bidi@16.0.1: + version "16.0.1" + resolved "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-16.0.1.tgz" + integrity sha512-J63PGu/9PpeCwLIcKYyzWP6yaVL5pxuBc0shlYCYM8BaAkmlwiQboXO1iNbOgSDbVklEyYFfNEcHD8oOAWacUA== dependencies: mitt "^3.0.1" zod "^3.24.1" cliui@^8.0.1: version "8.0.1" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + resolved "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz" integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== dependencies: string-width "^4.2.0" @@ -353,66 +186,24 @@ cliui@^8.0.1: color-convert@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== dependencies: color-name "~1.1.4" -color-convert@^3.0.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-3.1.2.tgz#cef9e0fd4cb90b07c14697b3fa70af9d7f4870f1" - integrity sha512-UNqkvCDXstVck3kdowtOTWROIJQwafjOfXSmddoDrXo4cewMKmusCeF22Q24zvjR8nwWib/3S/dfyzPItPEiJg== - dependencies: - color-name "^2.0.0" - -color-name@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-2.0.2.tgz#85054825a23e6d6f81d3503f660c4c4a2a15f04f" - integrity sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A== - color-name@~1.1.4: version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -color-string@^2.0.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-2.1.2.tgz#db1dd52414cc9037ada8fa7d936b8e9f6c3366c9" - integrity sha512-RxmjYxbWemV9gKu4zPgiZagUxbH3RQpEIO77XoSSX0ivgABDZ+h8Zuash/EMFLTI4N9QgFPOJ6JQpPZKFxa+dA== - dependencies: - color-name "^2.0.0" - -color@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/color/-/color-5.0.2.tgz#712ec894007ab27b37207732d182784e001b4a3d" - integrity sha512-e2hz5BzbUPcYlIRHo8ieAhYgoajrJr+hWoceg6E345TPsATMUKqDgzt8fSXZJJbxfpiPzkWyphz8yn8At7q3fA== - dependencies: - color-convert "^3.0.1" - color-string "^2.0.0" - -commander@14.0.1: - version "14.0.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-14.0.1.tgz#2f9225c19e6ebd0dc4404dd45821b2caa17ea09b" - integrity sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A== - concat-map@0.0.1: version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== -cosmiconfig@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-9.0.0.tgz#34c3fc58287b915f3ae905ab6dc3de258b55ad9d" - integrity sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg== - dependencies: - env-paths "^2.2.1" - import-fresh "^3.3.0" - js-yaml "^4.1.0" - parse-json "^5.2.0" - cross-spawn@^7.0.2: version "7.0.6" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz" integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== dependencies: path-key "^3.1.0" @@ -421,121 +212,59 @@ cross-spawn@^7.0.2: css-unit-converter@^1.1.2: version "1.1.2" - resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.2.tgz#4c77f5a1954e6dbff60695ecb214e3270436ab21" + resolved "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.2.tgz" integrity sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA== -data-uri-to-buffer@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz#8a58bb67384b261a38ef18bea1810cb01badd28b" - integrity sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw== - -debug@4, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.4.3: +debug@^4.3.1, debug@^4.3.2: version "4.4.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" + resolved "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz" integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== dependencies: ms "^2.1.3" deep-is@^0.1.3: version "0.1.4" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== -degenerator@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/degenerator/-/degenerator-5.0.1.tgz#9403bf297c6dad9a1ece409b37db27954f91f2f5" - integrity sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ== - dependencies: - ast-types "^0.13.4" - escodegen "^2.1.0" - esprima "^4.0.1" - -devtools-protocol@0.0.1581282: - version "0.0.1581282" - resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1581282.tgz#7f289b837e052ad04eb16e9575877801c2b3716c" - integrity sha512-nv7iKtNZQshSW2hKzYNr46nM/Cfh5SEvE2oV0/SEGgc9XupIY5ggf84Cz8eJIkBce7S3bmTAauFD6aysMpnqsQ== +devtools-protocol@0.0.1624250: + version "0.0.1624250" + resolved "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1624250.tgz" + integrity sha512-YFAat/lOiIk0ARmBweG+ygrEcbZrq5B9urRyUoeQKp53MlidHXE2TmTbxKcaXoQj7u/aX+jebDO4BW55rs0WwA== doctrine@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + resolved "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz" integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== dependencies: esutils "^2.0.2" -electron-to-chromium@^1.5.238: - version "1.5.249" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.249.tgz#e4fc3a3e60bb347361e4e876bb31903a9132a447" - integrity sha512-5vcfL3BBe++qZ5kuFhD/p8WOM1N9m3nwvJPULJx+4xf2usSlZFJ0qoNYO2fOX4hi3ocuDcmDobtA+5SFr4OmBg== - emoji-regex@^8.0.0: version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== -enabled@2.0.x: - version "2.0.0" - resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2" - integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ== - -end-of-stream@^1.1.0: - version "1.4.5" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.5.tgz#7344d711dea40e0b74abc2ed49778743ccedb08c" - integrity sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg== - dependencies: - once "^1.4.0" - -env-paths@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" - integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== - -error-ex@^1.3.1: - version "1.3.4" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.4.tgz#b3a8d8bb6f92eecc1629e3e27d3c8607a8a32414" - integrity sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ== - dependencies: - is-arrayish "^0.2.1" - es-check@^9.4.4: - version "9.4.4" - resolved "https://registry.yarnpkg.com/es-check/-/es-check-9.4.4.tgz#1dfbdf9f0bac746fee096ab1328841d11fa9a4f0" - integrity sha512-Ppp6r1diw1jy0t5uQX47HN3JqvosoAymZshdimrwpxCY1GQfZvqTqb9tHiiDbkm+aqGLdVDCZoL9okue7tdXZw== + version "9.6.4" + resolved "https://registry.npmjs.org/es-check/-/es-check-9.6.4.tgz" + integrity sha512-tZq2twJz5EVZk4THqPt9Nm+/EZbwYspus9bs86WLQ6cG08Du75dHB/1ZXyRVGRbeJoxKhsFXNWxCQrOISfuC3w== dependencies: - acorn "8.15.0" - acorn-walk "^8.3.4" - browserslist "^4.23.3" - commander "14.0.1" - fast-brake "^0.1.4" + acorn "8.16.0" fast-glob "^3.3.3" - lilconfig "^3.1.3" - source-map "^0.7.4" - supports-color "8.1.1" - winston "3.17.0" -escalade@^3.1.1, escalade@^3.2.0: +escalade@^3.1.1: version "3.2.0" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + resolved "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz" integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== escape-string-regexp@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -escodegen@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.1.0.tgz#ba93bbb7a43986d29d6041f99f5262da773e2e17" - integrity sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w== - dependencies: - esprima "^4.0.1" - estraverse "^5.2.0" - esutils "^2.0.2" - optionalDependencies: - source-map "~0.6.1" - eslint-scope@^7.2.2: version "7.2.2" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" + resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz" integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== dependencies: esrecurse "^4.3.0" @@ -543,12 +272,12 @@ eslint-scope@^7.2.2: eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: version "3.4.3" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== eslint@^8.57.1: version "8.57.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.1.tgz#7df109654aba7e3bbe5c8eae533c5e461d3c6ca9" + resolved "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz" integrity sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA== dependencies: "@eslint-community/eslint-utils" "^4.2.0" @@ -592,78 +321,45 @@ eslint@^8.57.1: espree@^9.6.0, espree@^9.6.1: version "9.6.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + resolved "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz" integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== dependencies: acorn "^8.9.0" acorn-jsx "^5.3.2" eslint-visitor-keys "^3.4.1" -esprima@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - esquery@^1.4.2: - version "1.6.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" - integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== + version "1.7.0" + resolved "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz" + integrity sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g== dependencies: estraverse "^5.1.0" esrecurse@^4.3.0: version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== dependencies: estraverse "^5.2.0" estraverse@^5.1.0, estraverse@^5.2.0: version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== esutils@^2.0.2: version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -events-universal@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/events-universal/-/events-universal-1.0.1.tgz#b56a84fd611b6610e0a2d0f09f80fdf931e2dfe6" - integrity sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw== - dependencies: - bare-events "^2.7.0" - -extract-zip@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" - integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg== - dependencies: - debug "^4.1.1" - get-stream "^5.1.0" - yauzl "^2.10.0" - optionalDependencies: - "@types/yauzl" "^2.9.1" - -fast-brake@^0.1.4: - version "0.1.6" - resolved "https://registry.yarnpkg.com/fast-brake/-/fast-brake-0.1.6.tgz#9776e16ccd528a8bcf445b48b4b38f8fc522ae20" - integrity sha512-V3j0HTIs70OOxRpbqT0bWVdrmP86s6N8TBPw/WyKJqdJ2Fwh3CuMmlO83uIIDpqik6m1Io9fT6qwNn69EqvXYA== - fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-fifo@^1.2.0, fast-fifo@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.2.tgz#286e31de96eb96d38a97899815740ba2a4f3640c" - integrity sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ== - fast-glob@^3.3.3: version "3.3.3" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818" + resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz" integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== dependencies: "@nodelib/fs.stat" "^2.0.2" @@ -674,50 +370,38 @@ fast-glob@^3.3.3: fast-json-stable-stringify@^2.0.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== fast-levenshtein@^2.0.6: version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== fastq@^1.6.0: - version "1.19.1" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.1.tgz#d50eaba803c8846a883c16492821ebcd2cda55f5" - integrity sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ== + version "1.20.1" + resolved "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz" + integrity sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw== dependencies: reusify "^1.0.4" -fd-slicer@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" - integrity sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g== - dependencies: - pend "~1.2.0" - -fecha@^4.2.0: - version "4.2.3" - resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd" - integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw== - file-entry-cache@^6.0.1: version "6.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz" integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== dependencies: flat-cache "^3.0.4" fill-range@^7.1.1: version "7.1.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz" integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== dependencies: to-regex-range "^5.0.1" find-up@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== dependencies: locate-path "^6.0.0" @@ -725,7 +409,7 @@ find-up@^5.0.0: flat-cache@^3.0.4: version "3.2.0" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" + resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz" integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== dependencies: flatted "^3.2.9" @@ -733,58 +417,37 @@ flat-cache@^3.0.4: rimraf "^3.0.2" flatted@^3.2.9: - version "3.3.3" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.3.tgz#67c8fad95454a7c7abebf74bb78ee74a44023358" - integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg== - -fn.name@1.x.x: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" - integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== + version "3.4.2" + resolved "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz" + integrity sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA== fs.realpath@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== get-caller-file@^2.0.5: version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-stream@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" - integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== - dependencies: - pump "^3.0.0" - -get-uri@^6.0.1: - version "6.0.5" - resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-6.0.5.tgz#714892aa4a871db671abc5395e5e9447bc306a16" - integrity sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg== - dependencies: - basic-ftp "^5.0.2" - data-uri-to-buffer "^6.0.2" - debug "^4.3.4" - glob-parent@^5.1.2: version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: is-glob "^4.0.1" glob-parent@^6.0.2: version "6.0.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz" integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== dependencies: is-glob "^4.0.3" glob@^7.1.3: version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== dependencies: fs.realpath "^1.0.0" @@ -796,45 +459,29 @@ glob@^7.1.3: globals@^13.19.0: version "13.24.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" + resolved "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz" integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== dependencies: type-fest "^0.20.2" graphemer@^1.4.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + resolved "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== has-flag@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -http-proxy-agent@^7.0.0, http-proxy-agent@^7.0.1: - version "7.0.2" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" - integrity sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig== - dependencies: - agent-base "^7.1.0" - debug "^4.3.4" - -https-proxy-agent@^7.0.6: - version "7.0.6" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz#da8dfeac7da130b05c2ba4b59c9b6cd66611a6b9" - integrity sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw== - dependencies: - agent-base "^7.1.2" - debug "4" - ignore@^5.2.0: version "5.3.2" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" + resolved "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz" integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== -import-fresh@^3.2.1, import-fresh@^3.3.0: +import-fresh@^3.2.1: version "3.3.1" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.1.tgz#9cecb56503c0ada1f2741dbbd6546e4b13b57ccf" + resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz" integrity sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ== dependencies: parent-module "^1.0.0" @@ -842,116 +489,86 @@ import-fresh@^3.2.1, import-fresh@^3.3.0: imurmurhash@^0.1.4: version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== inflight@^1.0.4: version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== dependencies: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.3: +inherits@2: version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -ip-address@^10.0.1: - version "10.1.0" - resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-10.1.0.tgz#d8dcffb34d0e02eb241427444a6e23f5b0595aa4" - integrity sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q== - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== - is-extglob@^2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== is-fullwidth-code-point@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== dependencies: is-extglob "^2.1.1" is-number@^7.0.0: version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== is-path-inside@^3.0.3: version "3.0.3" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + resolved "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== -is-stream@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== - isexe@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== -js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + version "4.2.0" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz" + integrity sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw== dependencies: argparse "^2.0.1" json-buffer@3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + resolved "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz" integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== -json-parse-even-better-errors@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - json-schema-traverse@^0.4.1: version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== keyv@^4.5.3: version "4.5.4" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + resolved "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz" integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== dependencies: json-buffer "3.0.1" -kuler@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3" - integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A== - levn@^0.4.1: version "0.4.1" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz" integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== dependencies: prelude-ls "^1.2.1" @@ -959,105 +576,71 @@ levn@^0.4.1: lilconfig@^3.1.3: version "3.1.3" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.3.tgz#a1bcfd6257f9585bf5ae14ceeebb7b559025e4c4" + resolved "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz" integrity sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw== -lines-and-columns@^1.1.6: - version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== - locate-path@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== dependencies: p-locate "^5.0.0" lodash.merge@^4.6.2: version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -logform@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/logform/-/logform-2.7.0.tgz#cfca97528ef290f2e125a08396805002b2d060d1" - integrity sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ== - dependencies: - "@colors/colors" "1.6.0" - "@types/triple-beam" "^1.3.2" - fecha "^4.2.0" - ms "^2.1.1" - safe-stable-stringify "^2.3.1" - triple-beam "^1.3.0" - -lru-cache@^7.14.1: - version "7.18.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89" - integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA== - merge2@^1.3.0: version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== micromatch@^4.0.8: version "4.0.8" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz" integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== dependencies: braces "^3.0.3" picomatch "^2.3.1" minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + version "3.1.5" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz" + integrity sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w== dependencies: brace-expansion "^1.1.7" mitt@^3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/mitt/-/mitt-3.0.1.tgz#ea36cf0cc30403601ae074c8f77b7092cdab36d1" + resolved "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz" integrity sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw== -ms@^2.1.1, ms@^2.1.3: +modern-tar@^0.7.6: + version "0.7.6" + resolved "https://registry.npmjs.org/modern-tar/-/modern-tar-0.7.6.tgz" + integrity sha512-sweCIVXzx1aIGTCdzcMlSZt1h8k5Tmk08VNAuRk3IU28XamGiOH5ypi11g6De2CH7PhYqSSnGy2A/EFhbWnVKg== + +ms@^2.1.3: version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== natural-compare@^1.4.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== -netmask@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/netmask/-/netmask-2.0.2.tgz#8b01a07644065d536383835823bc52004ebac5e7" - integrity sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg== - -node-releases@^2.0.26: - version "2.0.27" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.27.tgz#eedca519205cf20f650f61d56b070db111231e4e" - integrity sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA== - -once@^1.3.0, once@^1.3.1, once@^1.4.0: +once@^1.3.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" -one-time@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/one-time/-/one-time-1.0.0.tgz#e06bc174aed214ed58edede573b433bbf827cb45" - integrity sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g== - dependencies: - fn.name "1.x.x" - optionator@^0.9.3: version "0.9.4" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" + resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz" integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== dependencies: deep-is "^0.1.3" @@ -1069,469 +652,224 @@ optionator@^0.9.3: p-limit@^3.0.2: version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== dependencies: yocto-queue "^0.1.0" p-locate@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz" integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== dependencies: p-limit "^3.0.2" -pac-proxy-agent@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz#9cfaf33ff25da36f6147a20844230ec92c06e5df" - integrity sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA== - dependencies: - "@tootallnate/quickjs-emscripten" "^0.23.0" - agent-base "^7.1.2" - debug "^4.3.4" - get-uri "^6.0.1" - http-proxy-agent "^7.0.0" - https-proxy-agent "^7.0.6" - pac-resolver "^7.0.1" - socks-proxy-agent "^8.0.5" - -pac-resolver@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/pac-resolver/-/pac-resolver-7.0.1.tgz#54675558ea368b64d210fd9c92a640b5f3b8abb6" - integrity sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg== - dependencies: - degenerator "^5.0.0" - netmask "^2.0.2" - parent-module@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz" integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== dependencies: callsites "^3.0.0" -parse-json@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" - integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== - dependencies: - "@babel/code-frame" "^7.0.0" - error-ex "^1.3.1" - json-parse-even-better-errors "^2.3.0" - lines-and-columns "^1.1.6" - path-exists@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== path-is-absolute@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== path-key@^3.1.0: version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== -pend@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" - integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg== - -picocolors@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" - integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== - picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + version "2.3.2" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz" + integrity sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA== pngjs@^3.4.0: version "3.4.0" - resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f" + resolved "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz" integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w== prelude-ls@^1.2.1: version "1.2.1" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -progress@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" - integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== - -proxy-agent@^6.5.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-6.5.0.tgz#9e49acba8e4ee234aacb539f89ed9c23d02f232d" - integrity sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A== - dependencies: - agent-base "^7.1.2" - debug "^4.3.4" - http-proxy-agent "^7.0.1" - https-proxy-agent "^7.0.6" - lru-cache "^7.14.1" - pac-proxy-agent "^7.1.0" - proxy-from-env "^1.1.0" - socks-proxy-agent "^8.0.5" - -proxy-from-env@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" - integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== - -pump@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.3.tgz#151d979f1a29668dc0025ec589a455b53282268d" - integrity sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - punycode@^2.1.0: version "2.3.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== -puppeteer-core@24.40.0: - version "24.40.0" - resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-24.40.0.tgz#1f389cd9432cb077f703ca2cb6758490cdccbc7e" - integrity sha512-MWL3XbUCfVgGR0gRsidzT6oKJT2QydPLhMITU6HoVWiiv4gkb6gJi3pcdAa8q4HwjBTbqISOWVP4aJiiyUJvag== - dependencies: - "@puppeteer/browsers" "2.13.0" - chromium-bidi "14.0.0" - debug "^4.4.3" - devtools-protocol "0.0.1581282" - typed-query-selector "^2.12.1" - webdriver-bidi-protocol "0.4.1" - ws "^8.19.0" - -puppeteer@^24.31.0: - version "24.40.0" - resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-24.40.0.tgz#6df6aeee9dabf29bed3bb2be5c209d00518d4a79" - integrity sha512-IxQbDq93XHVVLWHrAkFP7F7iHvb9o0mgfsSIMlhHb+JM+JjM1V4v4MNSQfcRWJopx9dsNOr9adYv0U5fm9BJBQ== - dependencies: - "@puppeteer/browsers" "2.13.0" - chromium-bidi "14.0.0" - cosmiconfig "^9.0.0" - devtools-protocol "0.0.1581282" - puppeteer-core "24.40.0" - typed-query-selector "^2.12.1" +puppeteer-core@25.1.0: + version "25.1.0" + resolved "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-25.1.0.tgz" + integrity sha512-jKzy5y4WG6uNuFbTWgW1D7mqoT9o0nllc/6a1DGF775T1mPmgw3scdFEtEq67yVFikavQmbYq6NLfbTfxHSlqQ== + dependencies: + "@puppeteer/browsers" "3.0.4" + chromium-bidi "16.0.1" + devtools-protocol "0.0.1624250" + typed-query-selector "^2.12.2" + webdriver-bidi-protocol "0.4.2" + ws "^8.21.0" + +puppeteer@^25.1.0: + version "25.1.0" + resolved "https://registry.npmjs.org/puppeteer/-/puppeteer-25.1.0.tgz" + integrity sha512-7L6/0JM7XStK99lIL4xQySyNEXNfII6pk0BxkI5kKBTOhR7AsoQiv067YTsE/rIXxQiq9ajlO4WcqBjS/FWK1A== + dependencies: + "@puppeteer/browsers" "3.0.4" + chromium-bidi "16.0.1" + devtools-protocol "0.0.1624250" + lilconfig "^3.1.3" + puppeteer-core "25.1.0" + typed-query-selector "^2.12.2" queue-microtask@^1.2.2: version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== -readable-stream@^3.4.0, readable-stream@^3.6.2: - version "3.6.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" - integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - readline-sync@^1.4.10: version "1.4.10" - resolved "https://registry.yarnpkg.com/readline-sync/-/readline-sync-1.4.10.tgz#41df7fbb4b6312d673011594145705bf56d8873b" + resolved "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.10.tgz" integrity sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw== require-directory@^2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== resolve-from@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== reusify@^1.0.4: version "1.1.0" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.1.0.tgz#0fe13b9522e1473f51b558ee796e08f11f9b489f" + resolved "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz" integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== rimraf@^3.0.2: version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== dependencies: glob "^7.1.3" run-parallel@^1.1.9: version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== dependencies: queue-microtask "^1.2.2" -safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safe-stable-stringify@^2.3.1: - version "2.5.0" - resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz#4ca2f8e385f2831c432a719b108a3bf7af42a1dd" - integrity sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA== - -semver@^7.7.4: - version "7.7.4" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.4.tgz#28464e36060e991fa7a11d0279d2d3f3b57a7e8a" - integrity sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA== - shebang-command@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== dependencies: shebang-regex "^3.0.0" shebang-regex@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -smart-buffer@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" - integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== - -socks-proxy-agent@^8.0.5: - version "8.0.5" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz#b9cdb4e7e998509d7659d689ce7697ac21645bee" - integrity sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw== - dependencies: - agent-base "^7.1.2" - debug "^4.3.4" - socks "^2.8.3" - -socks@^2.8.3: - version "2.8.7" - resolved "https://registry.yarnpkg.com/socks/-/socks-2.8.7.tgz#e2fb1d9a603add75050a2067db8c381a0b5669ea" - integrity sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A== - dependencies: - ip-address "^10.0.1" - smart-buffer "^4.2.0" - -source-map@^0.7.4: - version "0.7.6" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.6.tgz#a3658ab87e5b6429c8a1f3ba0083d4c61ca3ef02" - integrity sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ== - -source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -stack-trace@0.0.x: - version "0.0.10" - resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" - integrity sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg== - -streamx@^2.15.0, streamx@^2.21.0: - version "2.23.0" - resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.23.0.tgz#7d0f3d00d4a6c5de5728aecd6422b4008d66fd0b" - integrity sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg== - dependencies: - events-universal "^1.0.0" - fast-fifo "^1.3.2" - text-decoder "^1.1.0" - string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== dependencies: emoji-regex "^8.0.0" is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: ansi-regex "^5.0.1" strip-json-comments@^3.1.1: version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -supports-color@8.1.1: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - supports-color@^7.1.0: version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: has-flag "^4.0.0" -tar-fs@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-3.1.2.tgz#114b012f54796f31e62f3e57792820a80b83ae6e" - integrity sha512-QGxxTxxyleAdyM3kpFs14ymbYmNFrfY+pHj7Z8FgtbZ7w2//VAgLMac7sT6nRpIHjppXO2AwwEOg0bPFVRcmXw== - dependencies: - pump "^3.0.0" - tar-stream "^3.1.5" - optionalDependencies: - bare-fs "^4.0.1" - bare-path "^3.0.0" - -tar-stream@^3.1.5: - version "3.1.7" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-3.1.7.tgz#24b3fb5eabada19fe7338ed6d26e5f7c482e792b" - integrity sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ== - dependencies: - b4a "^1.6.4" - fast-fifo "^1.2.0" - streamx "^2.15.0" - -text-decoder@^1.1.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/text-decoder/-/text-decoder-1.2.3.tgz#b19da364d981b2326d5f43099c310cc80d770c65" - integrity sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA== - dependencies: - b4a "^1.6.4" - -text-hex@1.0.x: - version "1.0.0" - resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5" - integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg== - text-table@^0.2.0: version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== to-regex-range@^5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== dependencies: is-number "^7.0.0" -triple-beam@^1.3.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.4.1.tgz#6fde70271dc6e5d73ca0c3b24e2d92afb7441984" - integrity sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg== - -tslib@^2.0.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" - integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== - type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz" integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== dependencies: prelude-ls "^1.2.1" type-fest@^0.20.2: version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== -typed-query-selector@^2.12.1: - version "2.12.1" - resolved "https://registry.yarnpkg.com/typed-query-selector/-/typed-query-selector-2.12.1.tgz#04423bfb71b8f3aee3df1c29598ed6c7c8f55284" - integrity sha512-uzR+FzI8qrUEIu96oaeBJmd9E7CFEiQ3goA5qCVgc4s5llSubcfGHq9yUstZx/k4s9dXHVKsE35YWoFyvEqEHA== +typed-query-selector@^2.12.2: + version "2.12.2" + resolved "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.2.tgz" + integrity sha512-EOPFbyIub4ngnEdqi2yOcNeDLaX/0jcE1JoAXQDDMIthap7FoN795lc/SHfIq2d416VufXpM8z/lD+WRm2gfOQ== typescript@^5.8.3: version "5.9.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f" + resolved "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz" integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw== -undici-types@~7.16.0: - version "7.16.0" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.16.0.tgz#ffccdff36aea4884cbfce9a750a0580224f58a46" - integrity sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw== - -update-browserslist-db@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz#7802aa2ae91477f255b86e0e46dbc787a206ad4a" - integrity sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A== - dependencies: - escalade "^3.2.0" - picocolors "^1.1.1" - uri-js@^4.2.2: version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== dependencies: punycode "^2.1.0" -util-deprecate@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== - -webdriver-bidi-protocol@0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/webdriver-bidi-protocol/-/webdriver-bidi-protocol-0.4.1.tgz#d411e7b8e158408d83bb166b0b4f1054fa3f077e" - integrity sha512-ARrjNjtWRRs2w4Tk7nqrf2gBI0QXWuOmMCx2hU+1jUt6d00MjMxURrhxhGbrsoiZKJrhTSTzbIrc554iKI10qw== +webdriver-bidi-protocol@0.4.2: + version "0.4.2" + resolved "https://registry.npmjs.org/webdriver-bidi-protocol/-/webdriver-bidi-protocol-0.4.2.tgz" + integrity sha512-VSV+fzfChirL3e7jay2yUC7B4HQCGtEWEg/MSSQbK+qWbqeGlRLlXTzPpYr3XGUvbpDHumWZBJxgesg4N7dbtA== which@^2.0.1: version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: isexe "^2.0.0" -winston-transport@^4.9.0: - version "4.9.0" - resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.9.0.tgz#3bba345de10297654ea6f33519424560003b3bf9" - integrity sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A== - dependencies: - logform "^2.7.0" - readable-stream "^3.6.2" - triple-beam "^1.3.0" - -winston@3.17.0: - version "3.17.0" - resolved "https://registry.yarnpkg.com/winston/-/winston-3.17.0.tgz#74b8665ce9b4ea7b29d0922cfccf852a08a11423" - integrity sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw== - dependencies: - "@colors/colors" "^1.6.0" - "@dabh/diagnostics" "^2.0.2" - async "^3.2.3" - is-stream "^2.0.0" - logform "^2.7.0" - one-time "^1.0.0" - readable-stream "^3.4.0" - safe-stable-stringify "^2.3.1" - stack-trace "0.0.x" - triple-beam "^1.3.0" - winston-transport "^4.9.0" - word-wrap@^1.2.5: version "1.2.5" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz" integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== wrap-ansi@^7.0.0: version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== dependencies: ansi-styles "^4.0.0" @@ -1540,27 +878,27 @@ wrap-ansi@^7.0.0: wrappy@1: version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -ws@^8.19.0: - version "8.20.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.20.0.tgz#4cd9532358eba60bc863aad1623dfb045a4d4af8" - integrity sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA== +ws@^8.21.0: + version "8.21.0" + resolved "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz" + integrity sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g== y18n@^5.0.5: version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== yargs-parser@^21.1.1: version "21.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== yargs@^17.7.2: version "17.7.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + resolved "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== dependencies: cliui "^8.0.1" @@ -1571,20 +909,12 @@ yargs@^17.7.2: y18n "^5.0.5" yargs-parser "^21.1.1" -yauzl@^2.10.0: - version "2.10.0" - resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" - integrity sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g== - dependencies: - buffer-crc32 "~0.2.3" - fd-slicer "~1.1.0" - yocto-queue@^0.1.0: version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== zod@^3.24.1: version "3.25.76" - resolved "https://registry.yarnpkg.com/zod/-/zod-3.25.76.tgz#26841c3f6fd22a6a2760e7ccb719179768471e34" + resolved "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz" integrity sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ== From 0d980a52e6db8328cba9dfb4352981bf9e912377 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 8 Jun 2026 15:55:48 +0200 Subject: [PATCH 26/59] Update nodejs version used in CI to `24.15.0` --- src/ci/docker/scripts/nodejs.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/docker/scripts/nodejs.sh b/src/ci/docker/scripts/nodejs.sh index 5f6af37c9c36c..c6a1b2f51ff03 100644 --- a/src/ci/docker/scripts/nodejs.sh +++ b/src/ci/docker/scripts/nodejs.sh @@ -2,7 +2,7 @@ set -ex -NODEJS_VERSION=v20.12.2 +NODEJS_VERSION=v24.15.0 YARN_VERSION=1.22.22 INSTALL_PATH=${1:-/node} From df53132a41614129861bb625a06c3cc67bd64cff Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Sun, 26 Apr 2026 18:11:27 -0400 Subject: [PATCH 27/59] Improve `core::char::mathods.rs` docs And rename a struct field. --- library/core/src/char/methods.rs | 180 ++++++++++++++++--------------- library/core/src/fmt/mod.rs | 4 +- library/core/src/str/lossy.rs | 2 +- library/core/src/str/mod.rs | 2 +- library/core/src/unicode/mod.rs | 9 +- library/core/src/wtf8.rs | 2 +- 6 files changed, 105 insertions(+), 94 deletions(-) diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index a397dd8df5359..16d4b1625b289 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -93,13 +93,18 @@ impl char { /// The version of [Unicode](https://www.unicode.org/) that the Unicode parts of /// `char` and `str` methods are based on. /// - /// New versions of Unicode are released regularly and subsequently all methods - /// in the standard library depending on Unicode are updated. Therefore the - /// behavior of some `char` and `str` methods and the value of this constant - /// changes over time. This is *not* considered to be a breaking change. + /// New versions of Unicode are released regularly, and subsequently all methods + /// in the standard library depending on Unicode are updated. Therefore, the + /// behavior of some `char` and `str` methods, and the value of this constant, + /// change over time (within the boundaries of Unicode's [stability policies]). + /// This is *not* considered to be a breaking change. + /// + /// [stability policies]: https://www.unicode.org/policies/stability_policy.html /// /// The version numbering scheme is explained in - /// [Unicode 11.0 or later, Section 3.1 Versions of the Unicode Standard](https://www.unicode.org/versions/Unicode11.0.0/ch03.pdf#page=4). + /// [Section 3.1 (Version Numbering)] of the Unicode Standard. + /// + /// [Section 3.1 (Version Numbering)]: https://www.unicode.org/versions/latest/core-spec/chapter-3/#G49512 #[stable(feature = "assoc_char_consts", since = "1.52.0")] pub const UNICODE_VERSION: (u8, u8, u8) = crate::unicode::UNICODE_VERSION; @@ -480,7 +485,7 @@ impl char { '\\' => EscapeDebug::backslash(ascii::Char::ReverseSolidus), '\"' if args.escape_double_quote => EscapeDebug::backslash(ascii::Char::QuotationMark), '\'' if args.escape_single_quote => EscapeDebug::backslash(ascii::Char::Apostrophe), - _ if args.escape_grapheme_extended && self.is_grapheme_extended() => { + _ if args.escape_grapheme_extender && self.is_grapheme_extender() => { EscapeDebug::unicode(self) } _ if is_printable(self) => EscapeDebug::printable(self), @@ -753,11 +758,11 @@ impl char { /// Returns `true` if this `char` has the `Alphabetic` property. /// - /// `Alphabetic` is described in Chapter 4 (Character Properties) of the [Unicode Standard] and - /// specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`]. + /// `Alphabetic` is [described] in Chapter 4 (Character Properties) of the Unicode Standard, and + /// [specified] in the Unicode Character Database [`DerivedCoreProperties.txt`]. /// - /// [Unicode Standard]: https://www.unicode.org/versions/latest/ - /// [ucd]: https://www.unicode.org/reports/tr44/ + /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-4/#G32524 + /// [specified]: https://www.unicode.org/reports/tr44/#Alphabetic /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt /// /// # Examples @@ -786,11 +791,11 @@ impl char { /// Returns `true` if this `char` has the `Cased` property. /// A character is cased if and only if it is uppercase, lowercase, or titlecase. /// - /// `Cased` is described in Chapter 4 (Character Properties) of the [Unicode Standard] and - /// specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`]. + /// `Cased` is [described] in Chapter 3 (Character Properties) of the Unicode Standard and + /// [specified] in the Unicode Character Database [`DerivedCoreProperties.txt`]. /// - /// [Unicode Standard]: https://www.unicode.org/versions/latest/ - /// [ucd]: https://www.unicode.org/reports/tr44/ + /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-3/#G44595 + /// [specified]: https://www.unicode.org/reports/tr44/#Cased /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt /// /// # Examples @@ -849,11 +854,11 @@ impl char { /// Returns `true` if this `char` has the `Lowercase` property. /// - /// `Lowercase` is described in Chapter 4 (Character Properties) of the [Unicode Standard] and - /// specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`]. + /// `Lowercase` is [described] in Chapter 4 (Character Properties) of the Unicode Standard, and + /// [specified] in the Unicode Character Database [`DerivedCoreProperties.txt`]. /// - /// [Unicode Standard]: https://www.unicode.org/versions/latest/ - /// [ucd]: https://www.unicode.org/reports/tr44/ + /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-4/#G136255 + /// [specified]: https://www.unicode.org/reports/tr44/#Lowercase /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt /// /// # Examples @@ -889,15 +894,15 @@ impl char { } } - /// Returns `true` if this `char` has the general category for titlecase letters. + /// Returns `true` if this `char` is in the general category for titlecase letters. /// Conceptually, these characters consist of an uppercase portion followed by a lowercase portion. /// - /// Titlecase letters (code points with the general category of `Lt`) are described in Chapter 4 - /// (Character Properties) of the [Unicode Standard] and specified in the [Unicode Character - /// Database][ucd] [`UnicodeData.txt`]. + /// Titlecase letters (code points with the general category of `Lt`) are [described] in Chapter 4 + /// (Character Properties) of the Unicode Standard, and [specified] in the Unicode Character + /// Database [`UnicodeData.txt`]. /// - /// [Unicode Standard]: https://www.unicode.org/versions/latest/ - /// [ucd]: https://www.unicode.org/reports/tr44/ + /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-4/#G124722 + /// [specified]: https://www.unicode.org/reports/tr44/#GC_Values_Table /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt /// /// # Examples @@ -925,11 +930,11 @@ impl char { /// Returns `true` if this `char` has the `Uppercase` property. /// - /// `Uppercase` is described in Chapter 4 (Character Properties) of the [Unicode Standard] and - /// specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`]. + /// `Uppercase` is [described] in Chapter 4 (Character Properties) of the Unicode Standard, and + /// [specified] in the Unicode Character Database [`DerivedCoreProperties.txt`]. /// - /// [Unicode Standard]: https://www.unicode.org/versions/latest/ - /// [ucd]: https://www.unicode.org/reports/tr44/ + /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-4/#G136255 + /// [specified]: https://www.unicode.org/reports/tr44/#Uppercase /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt /// /// # Examples @@ -965,11 +970,41 @@ impl char { } } + /// Returns `true` if this `char` satisfies either [`is_alphabetic()`] or [`is_numeric()`]. + /// + /// [`is_alphabetic()`]: Self::is_alphabetic + /// [`is_numeric()`]: Self::is_numeric + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert!('٣'.is_alphanumeric()); + /// assert!('7'.is_alphanumeric()); + /// assert!('৬'.is_alphanumeric()); + /// assert!('¾'.is_alphanumeric()); + /// assert!('①'.is_alphanumeric()); + /// assert!('K'.is_alphanumeric()); + /// assert!('و'.is_alphanumeric()); + /// assert!('藏'.is_alphanumeric()); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_alphanumeric(self) -> bool { + match self { + 'a'..='z' | 'A'..='Z' | '0'..='9' => true, + '\0'..='\u{A9}' => false, + _ => unicode::Alphabetic(self) || unicode::N(self), + } + } + /// Returns `true` if this `char` has the `White_Space` property. /// - /// `White_Space` is specified in the [Unicode Character Database][ucd] [`PropList.txt`]. + /// `White_Space` is [specified] in the Unicode Character Database [`PropList.txt`]. /// - /// [ucd]: https://www.unicode.org/reports/tr44/ + /// [specified]: https://www.unicode.org/reports/tr44/#White_Space /// [`PropList.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/PropList.txt /// /// # Examples @@ -999,44 +1034,15 @@ impl char { } } - /// Returns `true` if this `char` satisfies either [`is_alphabetic()`] or [`is_numeric()`]. - /// - /// [`is_alphabetic()`]: #method.is_alphabetic - /// [`is_numeric()`]: #method.is_numeric - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// assert!('٣'.is_alphanumeric()); - /// assert!('7'.is_alphanumeric()); - /// assert!('৬'.is_alphanumeric()); - /// assert!('¾'.is_alphanumeric()); - /// assert!('①'.is_alphanumeric()); - /// assert!('K'.is_alphanumeric()); - /// assert!('و'.is_alphanumeric()); - /// assert!('藏'.is_alphanumeric()); - /// ``` - #[must_use] - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn is_alphanumeric(self) -> bool { - match self { - 'a'..='z' | 'A'..='Z' | '0'..='9' => true, - '\0'..='\u{A9}' => false, - _ => unicode::Alphabetic(self) || unicode::N(self), - } - } - /// Returns `true` if this `char` has the general category for control codes. /// - /// Control codes (code points with the general category of `Cc`) are described in Chapter 4 - /// (Character Properties) of the [Unicode Standard] and specified in the [Unicode Character - /// Database][ucd] [`UnicodeData.txt`]. + /// Control codes (code points with the general category of `Cc`) are [described] in Chapter 23 + /// (Special Areas and Format Characters) of the Unicode Standard, and [specified] in the Unicode Character + /// Database [`UnicodeData.txt`]. The full set of Unicode control codes is + /// `'\0'..='\x1f' | '\x7f'..='\u{9f}'`, and will never change. /// - /// [Unicode Standard]: https://www.unicode.org/versions/latest/ - /// [ucd]: https://www.unicode.org/reports/tr44/ + /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-23/#G20365 + /// [specified]: https://www.unicode.org/reports/tr44/#GC_Values_Table /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt /// /// # Examples @@ -1044,8 +1050,9 @@ impl char { /// Basic usage: /// /// ``` - /// // U+009C, STRING TERMINATOR - /// assert!('œ'.is_control()); + /// assert!('\t'.is_control()); + /// assert!('\n'.is_control()); + /// assert!('\u{9C}'.is_control()); // STRING TERMINATOR /// assert!(!'q'.is_control()); /// ``` #[must_use] @@ -1062,16 +1069,15 @@ impl char { /// Returns `true` if this `char` has the `Grapheme_Extend` property. /// - /// `Grapheme_Extend` is described in [Unicode Standard Annex #29 (Unicode Text - /// Segmentation)][uax29] and specified in the [Unicode Character Database][ucd] - /// [`DerivedCoreProperties.txt`]. + /// `Grapheme_Extend` is [described] in Chapter 3 (Conformance) of the Unicode Standard, + /// and [specified] in the Unicode Character Database [`DerivedCoreProperties.txt`]. /// - /// [uax29]: https://www.unicode.org/reports/tr29/ - /// [ucd]: https://www.unicode.org/reports/tr44/ + /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-3/#G41165 + /// [specified]: https://www.unicode.org/reports/tr44/#Grapheme_Extend /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt #[must_use] #[inline] - pub(crate) fn is_grapheme_extended(self) -> bool { + fn is_grapheme_extender(self) -> bool { self > '\u{02FF}' && unicode::Grapheme_Extend(self) } @@ -1079,12 +1085,12 @@ impl char { /// is used to implement context-dependent casing for the Greek letter sigma (uppercase 'Σ'), /// which has two lowercase forms. /// - /// `Case_Ignorable` is [described][D136] in Chapter 3 (Conformance) of the Unicode Core Specification, - /// and specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`]. + /// `Case_Ignorable` is [described] in Chapter 3 (Conformance) of the Unicode Core Specification, + /// and [specified] in the Unicode Character Database [`DerivedCoreProperties.txt`]. /// See those resources, as well as [`to_lowercase()`]'s documentation, for more information. /// - /// [D136]: https://www.unicode.org/versions/latest/core-spec/chapter-3/#G63116 - /// [ucd]: https://www.unicode.org/reports/tr44/ + /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-3/#G63116 + /// [specified]: https://www.unicode.org/reports/tr44/#Case_Ignorable /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt /// [`to_lowercase()`]: Self::to_lowercase() #[must_use] @@ -1101,20 +1107,20 @@ impl char { /// Returns `true` if this `char` has one of the general categories for numbers. /// /// The general categories for numbers (`Nd` for decimal digits, `Nl` for letter-like numeric - /// characters, and `No` for other numeric characters) are specified in the [Unicode Character - /// Database][ucd] [`UnicodeData.txt`]. + /// characters, and `No` for other numeric characters) are [specified] in the Unicode Character + /// Database [`UnicodeData.txt`]. /// /// This method doesn't cover everything that could be considered a number, e.g. ideographic numbers like '三'. - /// If you want everything including characters with overlapping purposes then you might want to use - /// a unicode or language-processing library that exposes the appropriate character properties instead - /// of looking at the unicode categories. + /// If you want everything including characters with overlapping purposes, then you might want to use + /// a Unicode or language-processing library that exposes the appropriate character properties + /// (e.g. [`Numeric_Type`]) instead of looking at the Unicode categories. /// /// If you want to parse ASCII decimal digits (0-9) or ASCII base-N, use /// `is_ascii_digit` or `is_digit` instead. /// - /// [Unicode Standard]: https://www.unicode.org/versions/latest/ - /// [ucd]: https://www.unicode.org/reports/tr44/ + /// [specified]: https://www.unicode.org/reports/tr44/#GC_Values_Table /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt + /// [`Numeric_Type`]: https://www.unicode.org/reports/tr44/#Numeric_Type /// /// # Examples /// @@ -2270,8 +2276,8 @@ impl char { } pub(crate) struct EscapeDebugExtArgs { - /// Escape Extended Grapheme codepoints? - pub(crate) escape_grapheme_extended: bool, + /// Escape Grapheme Extender codepoints? + pub(crate) escape_grapheme_extender: bool, /// Escape single quotes? pub(crate) escape_single_quote: bool, @@ -2282,7 +2288,7 @@ pub(crate) struct EscapeDebugExtArgs { impl EscapeDebugExtArgs { pub(crate) const ESCAPE_ALL: Self = Self { - escape_grapheme_extended: true, + escape_grapheme_extender: true, escape_single_quote: true, escape_double_quote: true, }; diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 9e5f693246f33..00694a653be2d 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -2941,7 +2941,7 @@ impl Debug for str { let mut chars = rest.chars(); if let Some(c) = chars.next() { let esc = c.escape_debug_ext(EscapeDebugExtArgs { - escape_grapheme_extended: true, + escape_grapheme_extender: true, escape_single_quote: false, escape_double_quote: true, }); @@ -2973,7 +2973,7 @@ impl Debug for char { fn fmt(&self, f: &mut Formatter<'_>) -> Result { f.write_char('\'')?; let esc = self.escape_debug_ext(EscapeDebugExtArgs { - escape_grapheme_extended: true, + escape_grapheme_extender: true, escape_single_quote: true, escape_double_quote: false, }); diff --git a/library/core/src/str/lossy.rs b/library/core/src/str/lossy.rs index 18ad28f8f3b97..13e287fade36f 100644 --- a/library/core/src/str/lossy.rs +++ b/library/core/src/str/lossy.rs @@ -123,7 +123,7 @@ impl fmt::Debug for Debug<'_> { let mut from = 0; for (i, c) in valid.char_indices() { let esc = c.escape_debug_ext(EscapeDebugExtArgs { - escape_grapheme_extended: true, + escape_grapheme_extender: true, escape_single_quote: false, escape_double_quote: true, }); diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 74e709293f890..2275364ec1de7 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -3266,7 +3266,7 @@ impl_fn_for_zst! { #[derive(Clone)] struct CharEscapeDebugContinue impl Fn = |c: char| -> char::EscapeDebug { c.escape_debug_ext(EscapeDebugExtArgs { - escape_grapheme_extended: false, + escape_grapheme_extender: false, escape_single_quote: true, escape_double_quote: true }) diff --git a/library/core/src/unicode/mod.rs b/library/core/src/unicode/mod.rs index 8b2c526a08878..fb4e5c65d0ce1 100644 --- a/library/core/src/unicode/mod.rs +++ b/library/core/src/unicode/mod.rs @@ -27,8 +27,13 @@ pub mod unicode_data; /// New versions of Unicode are released regularly and subsequently all methods /// in the standard library depending on Unicode are updated. Therefore the /// behavior of some `char` and `str` methods and the value of this constant -/// changes over time. This is *not* considered to be a breaking change. +/// changes over time, within the boundaries of Unicode's [stability policies]. +/// This is *not* considered to be a breaking change. +/// +/// [stability policies]: https://www.unicode.org/policies/stability_policy.html /// /// The version numbering scheme is explained in -/// [Unicode 11.0 or later, Section 3.1 Versions of the Unicode Standard](https://www.unicode.org/versions/Unicode11.0.0/ch03.pdf#page=4). +/// [Section 3.1 (Version Numbering)] of the Unicode Standard. +/// +/// [Section 3.1 (Version Numbering)]: https://www.unicode.org/versions/latest/core-spec/chapter-3/#G49512 pub const UNICODE_VERSION: (u8, u8, u8) = unicode_data::UNICODE_VERSION; diff --git a/library/core/src/wtf8.rs b/library/core/src/wtf8.rs index 698e17a6b8e6d..56679ea3aa9d9 100644 --- a/library/core/src/wtf8.rs +++ b/library/core/src/wtf8.rs @@ -147,7 +147,7 @@ impl fmt::Debug for Wtf8 { use crate::fmt::Write as _; for c in s.chars().flat_map(|c| { c.escape_debug_ext(EscapeDebugExtArgs { - escape_grapheme_extended: true, + escape_grapheme_extender: true, escape_single_quote: false, escape_double_quote: true, }) From c15495fe3f0e5a07499c6cb6fac367fedd17f3e9 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Sun, 26 Apr 2026 18:19:55 -0400 Subject: [PATCH 28/59] `char`: move `is_numeric` next to `is_alphanumeric` --- library/core/src/char/methods.rs | 88 ++++++++++++++++---------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 16d4b1625b289..8739a713a9439 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -970,6 +970,50 @@ impl char { } } + /// Returns `true` if this `char` has one of the general categories for numbers. + /// + /// The general categories for numbers (`Nd` for decimal digits, `Nl` for letter-like numeric + /// characters, and `No` for other numeric characters) are [specified] in the Unicode Character + /// Database [`UnicodeData.txt`]. + /// + /// This method doesn't cover everything that could be considered a number, e.g. ideographic numbers like '三'. + /// If you want everything including characters with overlapping purposes, then you might want to use + /// a Unicode or language-processing library that exposes the appropriate character properties + /// (e.g. [`Numeric_Type`]) instead of looking at the Unicode categories. + /// + /// If you want to parse ASCII decimal digits (0-9) or ASCII base-N, use + /// `is_ascii_digit` or `is_digit` instead. + /// + /// [specified]: https://www.unicode.org/reports/tr44/#GC_Values_Table + /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt + /// [`Numeric_Type`]: https://www.unicode.org/reports/tr44/#Numeric_Type + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// assert!('٣'.is_numeric()); + /// assert!('7'.is_numeric()); + /// assert!('৬'.is_numeric()); + /// assert!('¾'.is_numeric()); + /// assert!('①'.is_numeric()); + /// assert!(!'K'.is_numeric()); + /// assert!(!'و'.is_numeric()); + /// assert!(!'藏'.is_numeric()); + /// assert!(!'三'.is_numeric()); + /// ``` + #[must_use] + #[stable(feature = "rust1", since = "1.0.0")] + #[inline] + pub fn is_numeric(self) -> bool { + match self { + '0'..='9' => true, + '\0'..='\u{B1}' => false, + _ => unicode::N(self), + } + } + /// Returns `true` if this `char` satisfies either [`is_alphabetic()`] or [`is_numeric()`]. /// /// [`is_alphabetic()`]: Self::is_alphabetic @@ -1104,50 +1148,6 @@ impl char { } } - /// Returns `true` if this `char` has one of the general categories for numbers. - /// - /// The general categories for numbers (`Nd` for decimal digits, `Nl` for letter-like numeric - /// characters, and `No` for other numeric characters) are [specified] in the Unicode Character - /// Database [`UnicodeData.txt`]. - /// - /// This method doesn't cover everything that could be considered a number, e.g. ideographic numbers like '三'. - /// If you want everything including characters with overlapping purposes, then you might want to use - /// a Unicode or language-processing library that exposes the appropriate character properties - /// (e.g. [`Numeric_Type`]) instead of looking at the Unicode categories. - /// - /// If you want to parse ASCII decimal digits (0-9) or ASCII base-N, use - /// `is_ascii_digit` or `is_digit` instead. - /// - /// [specified]: https://www.unicode.org/reports/tr44/#GC_Values_Table - /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt - /// [`Numeric_Type`]: https://www.unicode.org/reports/tr44/#Numeric_Type - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// assert!('٣'.is_numeric()); - /// assert!('7'.is_numeric()); - /// assert!('৬'.is_numeric()); - /// assert!('¾'.is_numeric()); - /// assert!('①'.is_numeric()); - /// assert!(!'K'.is_numeric()); - /// assert!(!'و'.is_numeric()); - /// assert!(!'藏'.is_numeric()); - /// assert!(!'三'.is_numeric()); - /// ``` - #[must_use] - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub fn is_numeric(self) -> bool { - match self { - '0'..='9' => true, - '\0'..='\u{B1}' => false, - _ => unicode::N(self), - } - } - /// Returns an iterator that yields the lowercase mapping of this `char` as one or more /// `char`s. /// From 4f20e75f6fc4d3e42b0f762cf3d3448e05b88751 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Sun, 26 Apr 2026 18:36:06 -0400 Subject: [PATCH 29/59] Replace printables table with `unicode_data.rs` tables This gets rid of the `printable.py` script, ensuring that `unicode-table-generator` handles all our Unicode data table generation needs. I've elected to give each Unicode property its own table, instead of merging them all into one. This is slightly less efficient in terms of space, but should allow us to expose these tables in the future with public methods on `char`. --- library/core/src/char/methods.rs | 133 +++- library/core/src/unicode/mod.rs | 4 +- library/core/src/unicode/printable.py | 258 -------- library/core/src/unicode/printable.rs | 608 ------------------ library/core/src/unicode/unicode_data.rs | 177 ++++- library/coretests/tests/unicode.rs | 21 +- library/coretests/tests/unicode/test_data.rs | 246 +++++++ license-metadata.json | 32 +- src/tools/unicode-table-generator/src/main.rs | 47 +- 9 files changed, 614 insertions(+), 912 deletions(-) delete mode 100755 library/core/src/unicode/printable.py delete mode 100644 library/core/src/unicode/printable.rs diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 8739a713a9439..b4569610babe5 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -5,7 +5,6 @@ use crate::panic::const_panic; use crate::slice; use crate::str::from_utf8_unchecked_mut; use crate::ub_checks::assert_unsafe_precondition; -use crate::unicode::printable::is_printable; use crate::unicode::{self, conversions}; impl char { @@ -478,18 +477,29 @@ impl char { #[inline] pub(crate) fn escape_debug_ext(self, args: EscapeDebugExtArgs) -> EscapeDebug { match self { - '\0' => EscapeDebug::backslash(ascii::Char::Digit0), - '\t' => EscapeDebug::backslash(ascii::Char::SmallT), - '\r' => EscapeDebug::backslash(ascii::Char::SmallR), - '\n' => EscapeDebug::backslash(ascii::Char::SmallN), - '\\' => EscapeDebug::backslash(ascii::Char::ReverseSolidus), + // Special escapes '\"' if args.escape_double_quote => EscapeDebug::backslash(ascii::Char::QuotationMark), '\'' if args.escape_single_quote => EscapeDebug::backslash(ascii::Char::Apostrophe), - _ if args.escape_grapheme_extender && self.is_grapheme_extender() => { + '\\' => EscapeDebug::backslash(ascii::Char::ReverseSolidus), + '\n' => EscapeDebug::backslash(ascii::Char::SmallN), + '\t' => EscapeDebug::backslash(ascii::Char::SmallT), + '\r' => EscapeDebug::backslash(ascii::Char::SmallR), + '\0' => EscapeDebug::backslash(ascii::Char::Digit0), + + // ASCII fast path + '\x20'..='\x7E' => EscapeDebug::printable(self), + + _ if self.is_control() + || self.is_private_use() + || self.is_whitespace() + || args.escape_grapheme_extender && self.is_grapheme_extender() + || self.is_format_control() + || self.is_unassigned() => + { EscapeDebug::unicode(self) } - _ if is_printable(self) => EscapeDebug::printable(self), - _ => EscapeDebug::unicode(self), + + _ => EscapeDebug::printable(self), } } @@ -1111,6 +1121,111 @@ impl char { matches!(self, '\0'..='\x1f' | '\x7f'..='\u{9f}') } + /// Returns `true` if this `char` has the general category for [private-use characters]. + /// These characters do not have an interpretation specified by Unicode; individual programs + /// and users are free to assign them whatever meaning they like. + /// + /// [private-use characters]: https://www.unicode.org/faq/private_use#private_use + /// + /// Private-use characters (code points with the general category of `Co`) are [described] in Chapter 23 + /// (Special Areas and Format Characters) of the Unicode Standard, and [specified] in the + /// Unicode Character Database [`UnicodeData.txt`]. The full set of private-use characters is + /// `'\u{E000}'..='\u{F8FF}' | '\u{F0000}'..='\u{FFFFD}' | '\u{100000}'..='\u{10FFFD}'`, + /// and will never change. + /// + /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-23/#G19184 + /// [specified]: https://www.unicode.org/reports/tr44/#GC_Values_Table + /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt + /// + #[must_use] + #[inline] + const fn is_private_use(self) -> bool { + // According to + // https://www.unicode.org/policies/stability_policy.html#Property_Value, + // the set of codepoints in `Co` will never change. + // So we can just hard-code the patterns to match against instead of using a table. + matches!(self, '\u{E000}'..='\u{F8FF}' | '\u{F0000}'..='\u{FFFFD}' | '\u{100000}'..='\u{10FFFD}') + } + + /// Returns `true` if this `char` has the general category for format control characters. + /// + /// Format controls (code points with the general category of `Cf`) are [described] in Chapter 4 + /// (Character Properties) of the Unicode Standard, and [specified] in the Unicode Character + /// Database [`UnicodeData.txt`]. + /// + /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-4/#G134153 + /// [specified]: https://www.unicode.org/reports/tr44/#GC_Values_Table + /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt + /// + /// # Examples + /// + /// Basic usage: + /// + /// ```ignore(private) + /// assert!('\u{AD}'.is_format_control()); // SOFT HYPHEN + /// assert!('\u{200B}'.is_format_control()); // ZERO WIDTH SPACE + /// assert!('\u{E0041}'.is_format_control()); // TAG LATIN CAPITAL LETTER A + /// assert!('۝'.is_format_control()); // ARABIC END OF AYAH + /// assert!('𓐲'.is_format_control()); // EGYPTIAN HIEROGLYPH INSERT AT TOP START + /// assert!(!'q'.is_format_control()); + /// ``` + #[must_use] + #[inline] + fn is_format_control(self) -> bool { + self > '\u{AC}' && unicode::Cf(self) + } + + /// Returns `true` if this `char` has not yet been assigned a meaning by Unicode, as of + /// [`UNICODE_VERSION`]. + /// + /// [`UNICODE_VERSION`]: Self::UNICODE_VERSION + /// + /// These characters may have a meaning assigned in the future, + /// except for the 66 [noncharacters] which will never be assigned a meaning. + /// + /// [noncharacters]: https://www.unicode.org/faq/private_use#noncharacters + /// + /// Many of Unicode's [stability policies] apply only to assigned characters. + /// + /// [stability policies]: https://www.unicode.org/policies/stability_policy.html + /// + /// Unassigned characters (code points with the general category of `Cn`) are [described] in Chapter 4 + /// (Character Properties) of the Unicode Standard, and [specified] in the Unicode Character Database + /// by their exclusion from [`UnicodeData.txt`]. + /// + /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-4/#G134153 + /// [specified]: https://www.unicode.org/reports/tr44/#GC_Values_Table + /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt + /// + /// # Examples + /// + /// Basic usage: + /// + /// ```ignore(private) + /// assert!('\u{FFFE}'.is_unassigned()); // noncharacter, will never be assigned + /// + /// //assert!('\u{7AAAA}'.is_unassigned()); // not currently assigned, but may be in the future, + /// // so we shouldn't rely on the current status + /// + /// assert!(!'γ'.is_unassigned()); // once a character is assigned, it stays assigned forever + /// ``` + #[must_use] + #[inline] + fn is_unassigned(self) -> bool { + match self { + '\0'..='\u{377}' => false, + '\u{378}'..='\u{3FFFD}' => unicode::Cn_planes_0_3(self), + // Assigned character ranges in planes 4 and above. + // `src/tools/unicode-table-generator/src/main.rs` asserts that this is correct + '\u{E0001}' + | '\u{E0020}'..='\u{E007F}' + | '\u{E0100}'..='\u{E01EF}' + | '\u{F0000}'..='\u{FFFFD}' + | '\u{100000}'..='\u{10FFFD}' => false, + _ => true, + } + } + /// Returns `true` if this `char` has the `Grapheme_Extend` property. /// /// `Grapheme_Extend` is [described] in Chapter 3 (Conformance) of the Unicode Standard, diff --git a/library/core/src/unicode/mod.rs b/library/core/src/unicode/mod.rs index fb4e5c65d0ce1..61acb08487057 100644 --- a/library/core/src/unicode/mod.rs +++ b/library/core/src/unicode/mod.rs @@ -9,6 +9,8 @@ pub use unicode_data::conversions; #[rustfmt::skip] pub(crate) use unicode_data::alphabetic::lookup as Alphabetic; pub(crate) use unicode_data::case_ignorable::lookup as Case_Ignorable; +pub(crate) use unicode_data::cf::lookup as Cf; +pub(crate) use unicode_data::cn_planes_0_3::lookup as Cn_planes_0_3; pub(crate) use unicode_data::grapheme_extend::lookup as Grapheme_Extend; pub(crate) use unicode_data::lowercase::lookup as Lowercase; pub(crate) use unicode_data::lt::lookup as Lt; @@ -16,8 +18,6 @@ pub(crate) use unicode_data::n::lookup as N; pub(crate) use unicode_data::uppercase::lookup as Uppercase; pub(crate) use unicode_data::white_space::lookup as White_Space; -pub(crate) mod printable; - #[allow(unreachable_pub)] pub mod unicode_data; diff --git a/library/core/src/unicode/printable.py b/library/core/src/unicode/printable.py deleted file mode 100755 index 260fa9f9e6ad2..0000000000000 --- a/library/core/src/unicode/printable.py +++ /dev/null @@ -1,258 +0,0 @@ -#!/usr/bin/env python - -# This script uses the following Unicode tables: -# - UnicodeData.txt - - -from collections import namedtuple -import csv -import os -import subprocess - -NUM_CODEPOINTS = 0x110000 - - -def to_ranges(iter): - current = None - for i in iter: - if current is None or i != current[1] or i in (0x10000, 0x20000): - if current is not None: - yield tuple(current) - current = [i, i + 1] - else: - current[1] += 1 - if current is not None: - yield tuple(current) - - -def get_escaped(codepoints): - for c in codepoints: - if (c.class_ or "Cn") in "Cc Cf Cs Co Cn Zl Zp Zs".split() and c.value != ord( - " " - ): - yield c.value - - -def get_file(f): - try: - return open(os.path.basename(f)) - except FileNotFoundError: - subprocess.run(["curl", "-O", f], check=True) - return open(os.path.basename(f)) - - -Codepoint = namedtuple("Codepoint", "value class_") - - -def get_codepoints(f): - r = csv.reader(f, delimiter=";") - prev_codepoint = 0 - class_first = None - for row in r: - codepoint = int(row[0], 16) - name = row[1] - class_ = row[2] - - if class_first is not None: - if not name.endswith("Last>"): - raise ValueError("Missing Last after First") - - for c in range(prev_codepoint + 1, codepoint): - yield Codepoint(c, class_first) - - class_first = None - if name.endswith("First>"): - class_first = class_ - - yield Codepoint(codepoint, class_) - prev_codepoint = codepoint - - if class_first is not None: - raise ValueError("Missing Last after First") - - for c in range(prev_codepoint + 1, NUM_CODEPOINTS): - yield Codepoint(c, None) - - -def compress_singletons(singletons): - uppers = [] # (upper, # items in lowers) - lowers = [] - - for i in singletons: - upper = i >> 8 - lower = i & 0xFF - if len(uppers) == 0 or uppers[-1][0] != upper: - uppers.append((upper, 1)) - else: - upper, count = uppers[-1] - uppers[-1] = upper, count + 1 - lowers.append(lower) - - return uppers, lowers - - -def compress_normal(normal): - # lengths 0x00..0x7f are encoded as 00, 01, ..., 7e, 7f - # lengths 0x80..0x7fff are encoded as 80 80, 80 81, ..., ff fe, ff ff - compressed = [] # [truelen, (truelenaux), falselen, (falselenaux)] - - prev_start = 0 - for start, count in normal: - truelen = start - prev_start - falselen = count - prev_start = start + count - - assert truelen < 0x8000 and falselen < 0x8000 - entry = [] - if truelen > 0x7F: - entry.append(0x80 | (truelen >> 8)) - entry.append(truelen & 0xFF) - else: - entry.append(truelen & 0x7F) - if falselen > 0x7F: - entry.append(0x80 | (falselen >> 8)) - entry.append(falselen & 0xFF) - else: - entry.append(falselen & 0x7F) - - compressed.append(entry) - - return compressed - - -def print_singletons(uppers, lowers, uppersname, lowersname): - print("#[rustfmt::skip]") - print("const {}: &[(u8, u8)] = &[".format(uppersname)) - for u, c in uppers: - print(" ({:#04x}, {}),".format(u, c)) - print("];") - print("#[rustfmt::skip]") - print("const {}: &[u8] = &[".format(lowersname)) - for i in range(0, len(lowers), 8): - print( - " {}".format(" ".join("{:#04x},".format(x) for x in lowers[i : i + 8])) - ) - print("];") - - -def print_normal(normal, normalname): - print("#[rustfmt::skip]") - print("const {}: &[u8] = &[".format(normalname)) - for v in normal: - print(" {}".format(" ".join("{:#04x},".format(i) for i in v))) - print("];") - - -def main(): - file = get_file("https://www.unicode.org/Public/UNIDATA/UnicodeData.txt") - - codepoints = get_codepoints(file) - - CUTOFF = 0x10000 - singletons0 = [] - singletons1 = [] - normal0 = [] - normal1 = [] - extra = [] - - for a, b in to_ranges(get_escaped(codepoints)): - if a > 2 * CUTOFF: - extra.append((a, b - a)) - elif a == b - 1: - if a & CUTOFF: - singletons1.append(a & ~CUTOFF) - else: - singletons0.append(a) - elif a == b - 2: - if a & CUTOFF: - singletons1.append(a & ~CUTOFF) - singletons1.append((a + 1) & ~CUTOFF) - else: - singletons0.append(a) - singletons0.append(a + 1) - else: - if a >= 2 * CUTOFF: - extra.append((a, b - a)) - elif a & CUTOFF: - normal1.append((a & ~CUTOFF, b - a)) - else: - normal0.append((a, b - a)) - - singletons0u, singletons0l = compress_singletons(singletons0) - singletons1u, singletons1l = compress_singletons(singletons1) - normal0 = compress_normal(normal0) - normal1 = compress_normal(normal1) - - print("""\ -// NOTE: The following code was generated by "library/core/src/unicode/printable.py", -// do not edit directly! - -fn check(x: u16, singletonuppers: &[(u8, u8)], singletonlowers: &[u8], normal: &[u8]) -> bool { - let xupper = (x >> 8) as u8; - let mut lowerstart = 0; - for &(upper, lowercount) in singletonuppers { - let lowerend = lowerstart + lowercount as usize; - if xupper == upper { - for &lower in &singletonlowers[lowerstart..lowerend] { - if lower == x as u8 { - return false; - } - } - } else if xupper < upper { - break; - } - lowerstart = lowerend; - } - - let mut x = x as i32; - let mut normal = normal.iter().cloned(); - let mut current = true; - while let Some(v) = normal.next() { - let len = if v & 0x80 != 0 { - ((v & 0x7f) as i32) << 8 | normal.next().unwrap() as i32 - } else { - v as i32 - }; - x -= len; - if x < 0 { - break; - } - current = !current; - } - current -} - -pub(crate) fn is_printable(x: char) -> bool { - let x = x as u32; - let lower = x as u16; - - if x < 32 { - // ASCII fast path - false - } else if x < 127 { - // ASCII fast path - true - } else if x < 0x10000 { - check(lower, SINGLETONS0U, SINGLETONS0L, NORMAL0) - } else if x < 0x20000 { - check(lower, SINGLETONS1U, SINGLETONS1L, NORMAL1) - } else {\ -""") - for a, b in extra: - print(" if 0x{:x} <= x && x < 0x{:x} {{".format(a, a + b)) - print(" return false;") - print(" }") - print("""\ - true - } -}\ -""") - print() - print_singletons(singletons0u, singletons0l, "SINGLETONS0U", "SINGLETONS0L") - print_singletons(singletons1u, singletons1l, "SINGLETONS1U", "SINGLETONS1L") - print_normal(normal0, "NORMAL0") - print_normal(normal1, "NORMAL1") - - -if __name__ == "__main__": - main() diff --git a/library/core/src/unicode/printable.rs b/library/core/src/unicode/printable.rs deleted file mode 100644 index 68e1c8ae31c06..0000000000000 --- a/library/core/src/unicode/printable.rs +++ /dev/null @@ -1,608 +0,0 @@ -// NOTE: The following code was generated by "library/core/src/unicode/printable.py", -// do not edit directly! - -fn check(x: u16, singletonuppers: &[(u8, u8)], singletonlowers: &[u8], normal: &[u8]) -> bool { - let xupper = (x >> 8) as u8; - let mut lowerstart = 0; - for &(upper, lowercount) in singletonuppers { - let lowerend = lowerstart + lowercount as usize; - if xupper == upper { - for &lower in &singletonlowers[lowerstart..lowerend] { - if lower == x as u8 { - return false; - } - } - } else if xupper < upper { - break; - } - lowerstart = lowerend; - } - - let mut x = x as i32; - let mut normal = normal.iter().cloned(); - let mut current = true; - while let Some(v) = normal.next() { - let len = if v & 0x80 != 0 { - ((v & 0x7f) as i32) << 8 | normal.next().unwrap() as i32 - } else { - v as i32 - }; - x -= len; - if x < 0 { - break; - } - current = !current; - } - current -} - -pub(crate) fn is_printable(x: char) -> bool { - let x = x as u32; - let lower = x as u16; - - if x < 32 { - // ASCII fast path - false - } else if x < 127 { - // ASCII fast path - true - } else if x < 0x10000 { - check(lower, SINGLETONS0U, SINGLETONS0L, NORMAL0) - } else if x < 0x20000 { - check(lower, SINGLETONS1U, SINGLETONS1L, NORMAL1) - } else { - if 0x2a6e0 <= x && x < 0x2a700 { - return false; - } - if 0x2b81e <= x && x < 0x2b820 { - return false; - } - if 0x2ceae <= x && x < 0x2ceb0 { - return false; - } - if 0x2ebe1 <= x && x < 0x2ebf0 { - return false; - } - if 0x2ee5e <= x && x < 0x2f800 { - return false; - } - if 0x2fa1e <= x && x < 0x30000 { - return false; - } - if 0x3134b <= x && x < 0x31350 { - return false; - } - if 0x3347a <= x && x < 0xe0100 { - return false; - } - if 0xe01f0 <= x && x < 0x110000 { - return false; - } - true - } -} - -#[rustfmt::skip] -const SINGLETONS0U: &[(u8, u8)] = &[ - (0x00, 1), - (0x03, 5), - (0x05, 6), - (0x06, 2), - (0x07, 6), - (0x08, 7), - (0x09, 17), - (0x0a, 28), - (0x0b, 25), - (0x0c, 25), - (0x0d, 16), - (0x0e, 12), - (0x0f, 4), - (0x10, 3), - (0x12, 18), - (0x13, 9), - (0x16, 1), - (0x17, 4), - (0x18, 1), - (0x19, 3), - (0x1a, 9), - (0x1b, 1), - (0x1c, 2), - (0x1f, 22), - (0x20, 3), - (0x2b, 2), - (0x2d, 11), - (0x2e, 1), - (0x30, 4), - (0x31, 2), - (0x32, 1), - (0xa9, 2), - (0xaa, 4), - (0xab, 8), - (0xfa, 2), - (0xfb, 5), - (0xfe, 3), - (0xff, 9), -]; -#[rustfmt::skip] -const SINGLETONS0L: &[u8] = &[ - 0xad, 0x78, 0x79, 0x8b, 0x8d, 0xa2, 0x30, 0x57, - 0x58, 0x8b, 0x8c, 0x90, 0x1c, 0xdd, 0x0e, 0x0f, - 0x4b, 0x4c, 0xfb, 0xfc, 0x2e, 0x2f, 0x3f, 0x5c, - 0x5d, 0x5f, 0xe2, 0x84, 0x8d, 0x8e, 0x91, 0x92, - 0xa9, 0xb1, 0xba, 0xbb, 0xc5, 0xc6, 0xc9, 0xca, - 0xde, 0xe4, 0xe5, 0xff, 0x00, 0x04, 0x11, 0x12, - 0x29, 0x31, 0x34, 0x37, 0x3a, 0x3b, 0x3d, 0x49, - 0x4a, 0x5d, 0x84, 0x8e, 0x92, 0xa9, 0xb1, 0xb4, - 0xba, 0xbb, 0xc6, 0xca, 0xce, 0xcf, 0xe4, 0xe5, - 0x00, 0x04, 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, - 0x34, 0x3a, 0x3b, 0x45, 0x46, 0x49, 0x4a, 0x5e, - 0x64, 0x65, 0x84, 0x91, 0x9b, 0x9d, 0xc9, 0xce, - 0xcf, 0x0d, 0x11, 0x29, 0x3a, 0x3b, 0x45, 0x49, - 0x57, 0x5b, 0x5e, 0x5f, 0x64, 0x65, 0x8d, 0x91, - 0xa9, 0xb4, 0xba, 0xbb, 0xc5, 0xc9, 0xdf, 0xe4, - 0xe5, 0xf0, 0x0d, 0x11, 0x45, 0x49, 0x64, 0x65, - 0x80, 0x84, 0xb2, 0xbc, 0xbe, 0xbf, 0xd5, 0xd7, - 0xf0, 0xf1, 0x83, 0x85, 0x8b, 0xa4, 0xa6, 0xbe, - 0xbf, 0xc5, 0xc7, 0xcf, 0xda, 0xdb, 0x48, 0x98, - 0xbd, 0xcd, 0xc6, 0xce, 0xcf, 0x49, 0x4e, 0x4f, - 0x57, 0x59, 0x5e, 0x5f, 0x89, 0x8e, 0x8f, 0xb1, - 0xb6, 0xb7, 0xbf, 0xc1, 0xc6, 0xc7, 0xd7, 0x11, - 0x16, 0x17, 0x5b, 0x5c, 0xf6, 0xf7, 0xfe, 0xff, - 0x80, 0x6d, 0x71, 0xde, 0xdf, 0x0e, 0x1f, 0x6e, - 0x6f, 0x1c, 0x1d, 0x5f, 0x7d, 0x7e, 0xae, 0xaf, - 0xde, 0xdf, 0x4d, 0xbb, 0xbc, 0x16, 0x17, 0x1e, - 0x1f, 0x46, 0x47, 0x4e, 0x4f, 0x58, 0x5a, 0x5c, - 0x5e, 0x7e, 0x7f, 0xb5, 0xc5, 0xd4, 0xd5, 0xdc, - 0xf0, 0xf1, 0xf5, 0x72, 0x73, 0x8f, 0x74, 0x75, - 0x26, 0x2e, 0x2f, 0xa7, 0xaf, 0xb7, 0xbf, 0xc7, - 0xcf, 0xd7, 0xdf, 0x9a, 0x00, 0x40, 0x97, 0x98, - 0x30, 0x8f, 0x1f, 0xce, 0xff, 0x4e, 0x4f, 0x5a, - 0x5b, 0x07, 0x08, 0x0f, 0x10, 0x27, 0x2f, 0xee, - 0xef, 0x6e, 0x6f, 0x37, 0x3d, 0x3f, 0x42, 0x45, - 0x53, 0x67, 0x75, 0xc8, 0xc9, 0xd0, 0xd1, 0xd8, - 0xd9, 0xe7, 0xfe, 0xff, -]; -#[rustfmt::skip] -const SINGLETONS1U: &[(u8, u8)] = &[ - (0x00, 6), - (0x01, 1), - (0x03, 1), - (0x04, 2), - (0x05, 7), - (0x07, 2), - (0x08, 8), - (0x09, 2), - (0x0a, 5), - (0x0b, 2), - (0x0e, 4), - (0x10, 1), - (0x11, 2), - (0x12, 5), - (0x13, 28), - (0x14, 1), - (0x15, 2), - (0x17, 2), - (0x19, 13), - (0x1c, 5), - (0x1d, 8), - (0x1f, 1), - (0x24, 1), - (0x6a, 4), - (0x6b, 2), - (0x6e, 2), - (0xaf, 3), - (0xb1, 2), - (0xbc, 2), - (0xcf, 2), - (0xd1, 2), - (0xd4, 12), - (0xd5, 9), - (0xd6, 2), - (0xd7, 2), - (0xda, 1), - (0xe0, 5), - (0xe1, 2), - (0xe6, 1), - (0xe7, 4), - (0xe8, 2), - (0xee, 32), - (0xf0, 4), - (0xf8, 2), - (0xfa, 5), - (0xfb, 1), -]; -#[rustfmt::skip] -const SINGLETONS1L: &[u8] = &[ - 0x0c, 0x27, 0x3b, 0x3e, 0x4e, 0x4f, 0x8f, 0x9e, - 0x9e, 0x9f, 0x7b, 0x8b, 0x93, 0x96, 0xa2, 0xb2, - 0xba, 0x86, 0xb1, 0x06, 0x07, 0x09, 0x36, 0x3d, - 0x3e, 0x56, 0xf3, 0xd0, 0xd1, 0x04, 0x14, 0x18, - 0x36, 0x37, 0x56, 0x57, 0x7f, 0xaa, 0xae, 0xaf, - 0xbd, 0x35, 0xe0, 0x12, 0x87, 0x89, 0x8e, 0x9e, - 0x04, 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, - 0x3a, 0x45, 0x46, 0x49, 0x4a, 0x4e, 0x4f, 0x64, - 0x65, 0x8a, 0x8c, 0x8d, 0x8f, 0xb6, 0xc1, 0xc3, - 0xc4, 0xc6, 0xcb, 0xd6, 0x5c, 0xb6, 0xb7, 0x1b, - 0x1c, 0x07, 0x08, 0x0a, 0x0b, 0x14, 0x17, 0x36, - 0x39, 0x3a, 0xa8, 0xa9, 0xd8, 0xd9, 0x09, 0x37, - 0x90, 0x91, 0xa8, 0x07, 0x0a, 0x3b, 0x3e, 0x66, - 0x69, 0x8f, 0x92, 0x11, 0x6f, 0x5f, 0xbf, 0xee, - 0xef, 0x5a, 0x62, 0xb9, 0xba, 0xf4, 0xfc, 0xff, - 0x53, 0x54, 0x9a, 0x9b, 0x2e, 0x2f, 0x27, 0x28, - 0x55, 0x9d, 0xa0, 0xa1, 0xa3, 0xa4, 0xa7, 0xa8, - 0xad, 0xba, 0xbc, 0xc4, 0x06, 0x0b, 0x0c, 0x15, - 0x1d, 0x3a, 0x3f, 0x45, 0x51, 0xa6, 0xa7, 0xcc, - 0xcd, 0xa0, 0x07, 0x19, 0x1a, 0x22, 0x25, 0x3e, - 0x3f, 0xdf, 0xe7, 0xec, 0xef, 0xff, 0xc5, 0xc6, - 0x04, 0x20, 0x23, 0x25, 0x26, 0x28, 0x33, 0x38, - 0x3a, 0x48, 0x4a, 0x4c, 0x50, 0x53, 0x55, 0x56, - 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x63, 0x65, 0x66, - 0x6b, 0x73, 0x78, 0x7d, 0x7f, 0x8a, 0xa4, 0xaa, - 0xaf, 0xb0, 0xc0, 0xd0, 0xae, 0xaf, 0x6e, 0x6f, - 0xc7, 0xdd, 0xde, 0x93, -]; -#[rustfmt::skip] -const NORMAL0: &[u8] = &[ - 0x00, 0x20, - 0x5f, 0x22, - 0x82, 0xdf, 0x04, - 0x82, 0x44, 0x08, - 0x1b, 0x04, - 0x06, 0x11, - 0x81, 0xac, 0x0e, - 0x80, 0xab, 0x05, - 0x20, 0x07, - 0x81, 0x1c, 0x03, - 0x19, 0x08, - 0x01, 0x04, - 0x2f, 0x04, - 0x34, 0x04, - 0x07, 0x03, - 0x01, 0x07, - 0x06, 0x07, - 0x11, 0x0a, - 0x50, 0x0f, - 0x12, 0x07, - 0x55, 0x07, - 0x03, 0x04, - 0x1c, 0x0a, - 0x09, 0x03, - 0x08, 0x03, - 0x07, 0x03, - 0x02, 0x03, - 0x03, 0x03, - 0x0c, 0x04, - 0x05, 0x03, - 0x0b, 0x06, - 0x01, 0x0e, - 0x15, 0x05, - 0x4e, 0x07, - 0x1b, 0x07, - 0x57, 0x07, - 0x02, 0x05, - 0x18, 0x0c, - 0x50, 0x04, - 0x43, 0x03, - 0x2d, 0x03, - 0x01, 0x04, - 0x11, 0x06, - 0x0f, 0x0c, - 0x3a, 0x04, - 0x1d, 0x25, - 0x5f, 0x20, - 0x6d, 0x04, - 0x6a, 0x25, - 0x80, 0xc8, 0x05, - 0x82, 0xb0, 0x03, - 0x1a, 0x06, - 0x82, 0xfd, 0x03, - 0x59, 0x07, - 0x16, 0x09, - 0x18, 0x09, - 0x14, 0x0c, - 0x14, 0x0c, - 0x6a, 0x06, - 0x0a, 0x06, - 0x1a, 0x06, - 0x59, 0x07, - 0x2b, 0x05, - 0x46, 0x0a, - 0x2c, 0x04, - 0x0c, 0x04, - 0x01, 0x03, - 0x31, 0x0b, - 0x2c, 0x04, - 0x1a, 0x06, - 0x0b, 0x03, - 0x80, 0xac, 0x06, - 0x0a, 0x06, - 0x4c, 0x14, - 0x80, 0xf4, 0x08, - 0x3c, 0x03, - 0x0f, 0x03, - 0x3e, 0x05, - 0x38, 0x08, - 0x2b, 0x05, - 0x82, 0xff, 0x11, - 0x18, 0x08, - 0x2f, 0x11, - 0x2d, 0x03, - 0x22, 0x0e, - 0x21, 0x0f, - 0x80, 0x8c, 0x04, - 0x82, 0x9a, 0x16, - 0x0b, 0x15, - 0x88, 0x94, 0x05, - 0x2f, 0x05, - 0x3b, 0x07, - 0x02, 0x0e, - 0x18, 0x09, - 0x80, 0xbe, 0x22, - 0x74, 0x0c, - 0x80, 0xd6, 0x1a, - 0x81, 0x10, 0x05, - 0x80, 0xe1, 0x09, - 0xf2, 0x9e, 0x03, - 0x37, 0x09, - 0x81, 0x5c, 0x14, - 0x80, 0xb8, 0x08, - 0x80, 0xdd, 0x14, - 0x3c, 0x03, - 0x0a, 0x06, - 0x38, 0x08, - 0x46, 0x08, - 0x0c, 0x06, - 0x74, 0x0b, - 0x1e, 0x03, - 0x5a, 0x04, - 0x59, 0x09, - 0x80, 0x83, 0x18, - 0x1c, 0x0a, - 0x16, 0x09, - 0x4c, 0x04, - 0x80, 0x8a, 0x06, - 0xab, 0xa4, 0x0c, - 0x17, 0x04, - 0x31, 0xa1, 0x04, - 0x81, 0xda, 0x26, - 0x07, 0x0c, - 0x05, 0x05, - 0x82, 0xb3, 0x20, - 0x2a, 0x06, - 0x4c, 0x04, - 0x80, 0x8d, 0x04, - 0x80, 0xbe, 0x03, - 0x1b, 0x03, - 0x0f, 0x0d, -]; -#[rustfmt::skip] -const NORMAL1: &[u8] = &[ - 0x5e, 0x22, - 0x7b, 0x05, - 0x03, 0x04, - 0x2d, 0x03, - 0x66, 0x03, - 0x01, 0x2f, - 0x2e, 0x80, 0x82, - 0x1d, 0x03, - 0x31, 0x0f, - 0x1c, 0x04, - 0x24, 0x09, - 0x1e, 0x05, - 0x2b, 0x05, - 0x44, 0x04, - 0x0e, 0x2a, - 0x80, 0xaa, 0x06, - 0x24, 0x04, - 0x24, 0x04, - 0x28, 0x08, - 0x34, 0x0b, - 0x4e, 0x03, - 0x34, 0x0c, - 0x81, 0x37, 0x09, - 0x16, 0x0a, - 0x08, 0x18, - 0x3b, 0x45, - 0x39, 0x03, - 0x63, 0x08, - 0x09, 0x30, - 0x16, 0x05, - 0x21, 0x03, - 0x1b, 0x05, - 0x1b, 0x26, - 0x38, 0x04, - 0x4b, 0x05, - 0x2f, 0x04, - 0x0a, 0x07, - 0x09, 0x07, - 0x40, 0x20, - 0x27, 0x04, - 0x0c, 0x09, - 0x36, 0x03, - 0x3a, 0x05, - 0x1a, 0x07, - 0x04, 0x0c, - 0x07, 0x50, - 0x49, 0x37, - 0x33, 0x0d, - 0x33, 0x07, - 0x2e, 0x08, - 0x0a, 0x06, - 0x26, 0x03, - 0x1d, 0x08, - 0x02, 0x80, 0xd0, - 0x52, 0x10, - 0x06, 0x08, - 0x09, 0x21, - 0x2e, 0x08, - 0x2a, 0x16, - 0x1a, 0x26, - 0x1c, 0x14, - 0x17, 0x09, - 0x4e, 0x04, - 0x24, 0x09, - 0x44, 0x0d, - 0x19, 0x07, - 0x0a, 0x06, - 0x48, 0x08, - 0x27, 0x09, - 0x75, 0x0b, - 0x42, 0x3e, - 0x2a, 0x06, - 0x3b, 0x05, - 0x0a, 0x06, - 0x51, 0x06, - 0x01, 0x05, - 0x10, 0x03, - 0x05, 0x0b, - 0x59, 0x08, - 0x02, 0x1d, - 0x62, 0x1e, - 0x48, 0x08, - 0x0a, 0x80, 0xa6, - 0x5e, 0x22, - 0x45, 0x0b, - 0x0a, 0x06, - 0x0d, 0x13, - 0x3a, 0x06, - 0x0a, 0x06, - 0x14, 0x1c, - 0x2c, 0x04, - 0x17, 0x80, 0xb9, - 0x3c, 0x64, - 0x53, 0x0c, - 0x48, 0x09, - 0x0a, 0x46, - 0x45, 0x1b, - 0x48, 0x08, - 0x53, 0x0d, - 0x49, 0x07, - 0x0a, 0x56, - 0x08, 0x58, - 0x22, 0x0e, - 0x0a, 0x06, - 0x46, 0x0a, - 0x1d, 0x03, - 0x47, 0x49, - 0x37, 0x03, - 0x0e, 0x08, - 0x0a, 0x06, - 0x39, 0x07, - 0x0a, 0x06, - 0x2c, 0x04, - 0x0a, 0x80, 0xf6, - 0x19, 0x07, - 0x3b, 0x03, - 0x1d, 0x55, - 0x01, 0x0f, - 0x32, 0x0d, - 0x83, 0x9b, 0x66, - 0x75, 0x0b, - 0x80, 0xc4, 0x8a, 0x4c, - 0x63, 0x0d, - 0x84, 0x30, 0x10, - 0x16, 0x0a, - 0x8f, 0x9b, 0x05, - 0x82, 0x47, 0x9a, 0xb9, - 0x3a, 0x86, 0xc6, - 0x82, 0x39, 0x07, - 0x2a, 0x04, - 0x5c, 0x06, - 0x26, 0x0a, - 0x46, 0x0a, - 0x28, 0x05, - 0x13, 0x81, 0xb0, - 0x3a, 0x80, 0xc6, - 0x5b, 0x05, - 0x34, 0x2c, - 0x4b, 0x04, - 0x39, 0x07, - 0x11, 0x40, - 0x05, 0x0b, - 0x07, 0x09, - 0x9c, 0xd6, 0x29, - 0x20, 0x61, - 0x73, 0xa1, 0xfd, - 0x81, 0x33, 0x0f, - 0x01, 0x1d, - 0x06, 0x0e, - 0x04, 0x08, - 0x81, 0x8c, 0x89, 0x04, - 0x6b, 0x05, - 0x0d, 0x03, - 0x09, 0x07, - 0x10, 0x8f, 0x60, - 0x80, 0xfd, 0x03, - 0x81, 0xb4, 0x06, - 0x17, 0x0f, - 0x11, 0x0f, - 0x47, 0x09, - 0x74, 0x3c, - 0x80, 0xf6, 0x0a, - 0x73, 0x08, - 0x70, 0x15, - 0x46, 0x7a, - 0x14, 0x0c, - 0x14, 0x0c, - 0x57, 0x09, - 0x19, 0x80, 0x87, - 0x81, 0x47, 0x03, - 0x85, 0x42, 0x0f, - 0x15, 0x84, 0x50, - 0x1f, 0x06, - 0x06, 0x80, 0xd5, - 0x2b, 0x05, - 0x3e, 0x21, - 0x01, 0x70, - 0x2d, 0x03, - 0x1a, 0x04, - 0x02, 0x81, 0x40, - 0x1f, 0x11, - 0x3a, 0x05, - 0x01, 0x81, 0xd0, - 0x2a, 0x80, 0xd6, - 0x2b, 0x04, - 0x01, 0x80, 0xc0, - 0x36, 0x08, - 0x02, 0x80, 0xe0, - 0x80, 0xf7, 0x29, - 0x4c, 0x04, - 0x0a, 0x04, - 0x02, 0x83, 0x11, - 0x44, 0x4c, - 0x3d, 0x80, 0xc2, - 0x3c, 0x06, - 0x01, 0x04, - 0x55, 0x05, - 0x1b, 0x34, - 0x02, 0x81, 0x0e, - 0x2c, 0x04, - 0x64, 0x0c, - 0x56, 0x0a, - 0x80, 0xae, 0x38, - 0x1d, 0x0d, - 0x2c, 0x04, - 0x09, 0x07, - 0x02, 0x0e, - 0x06, 0x80, 0x9a, - 0x83, 0xd9, 0x03, - 0x11, 0x03, - 0x0d, 0x03, - 0x80, 0xda, 0x06, - 0x0c, 0x04, - 0x01, 0x0f, - 0x0c, 0x04, - 0x38, 0x08, - 0x0a, 0x06, - 0x28, 0x08, - 0x2c, 0x04, - 0x02, 0x0e, - 0x09, 0x27, - 0x81, 0x58, 0x08, - 0x1d, 0x03, - 0x0b, 0x03, - 0x3b, 0x04, - 0x1e, 0x04, - 0x0a, 0x07, - 0x80, 0xfb, 0x84, 0x05, -]; diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs index 9df020ced674b..2c768e0622762 100644 --- a/library/core/src/unicode/unicode_data.rs +++ b/library/core/src/unicode/unicode_data.rs @@ -1,17 +1,19 @@ //! This file is generated by `./x run src/tools/unicode-table-generator`; do not edit manually! -// Alphabetic : 1723 bytes, 147369 codepoints in 759 ranges (U+0000AA - U+03347A) using skiplist -// Case_Ignorable : 1063 bytes, 2789 codepoints in 459 ranges (U+0000A8 - U+0E01F0) using skiplist -// Grapheme_Extend : 899 bytes, 2232 codepoints in 383 ranges (U+000300 - U+0E01F0) using skiplist -// Lowercase : 943 bytes, 2569 codepoints in 676 ranges (U+0000AA - U+01E944) using bitset -// Lt : 33 bytes, 31 codepoints in 10 ranges (U+0001C5 - U+001FFD) using skiplist -// N : 463 bytes, 1914 codepoints in 145 ranges (U+0000B2 - U+01FBFA) using skiplist -// Uppercase : 799 bytes, 1980 codepoints in 659 ranges (U+0000C0 - U+01F18A) using bitset -// White_Space : 256 bytes, 19 codepoints in 8 ranges (U+000085 - U+003001) using cascading -// to_lower : 1112 bytes, 1462 codepoints in 185 ranges (U+0000C0 - U+01E921) using 2-level LUT -// to_upper : 1998 bytes, 1554 codepoints in 299 ranges (U+0000B5 - U+01E943) using 2-level LUT -// to_title : 340 bytes, 135 codepoints in 49 ranges (U+0000DF - U+00FB17) using 2-level LUT -// to_casefold : 32 bytes, 174 codepoints in 5 ranges (U+000131 - U+00ABBF) using 2-level LUT -// Total : 9661 bytes +// Alphabetic : 1723 bytes, 147369 codepoints in 759 ranges (U+0000AA - U+03347A) using skiplist +// Case_Ignorable : 1063 bytes, 2789 codepoints in 459 ranges (U+0000A8 - U+0E01F0) using skiplist +// Cf : 87 bytes, 170 codepoints in 21 ranges (U+0000AD - U+0E0080) using skiplist +// Cn_Planes_0_3 : 1677 bytes, 94165 codepoints in 730 ranges (U+000378 - U+03FFFE) using skiplist +// Grapheme_Extend : 899 bytes, 2232 codepoints in 383 ranges (U+000300 - U+0E01F0) using skiplist +// Lowercase : 943 bytes, 2569 codepoints in 676 ranges (U+0000AA - U+01E944) using bitset +// Lt : 33 bytes, 31 codepoints in 10 ranges (U+0001C5 - U+001FFD) using skiplist +// N : 463 bytes, 1914 codepoints in 145 ranges (U+0000B2 - U+01FBFA) using skiplist +// Uppercase : 799 bytes, 1980 codepoints in 659 ranges (U+0000C0 - U+01F18A) using bitset +// White_Space : 256 bytes, 19 codepoints in 8 ranges (U+000085 - U+003001) using cascading +// to_lower : 1112 bytes, 1462 codepoints in 185 ranges (U+0000C0 - U+01E921) using 2-level LUT +// to_upper : 1998 bytes, 1554 codepoints in 299 ranges (U+0000B5 - U+01E943) using 2-level LUT +// to_title : 340 bytes, 135 codepoints in 49 ranges (U+0000DF - U+00FB17) using 2-level LUT +// to_casefold : 32 bytes, 174 codepoints in 5 ranges (U+000131 - U+00ABBF) using 2-level LUT +// Total : 11425 bytes #[inline(always)] const fn bitset_search< @@ -338,6 +340,155 @@ pub mod case_ignorable { } } +#[rustfmt::skip] +pub mod cf { + use super::ShortOffsetRunHeader; + + static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; 11] = [ + ShortOffsetRunHeader::new(0, 1536), ShortOffsetRunHeader::new(3, 2192), + ShortOffsetRunHeader::new(11, 6158), ShortOffsetRunHeader::new(15, 8203), + ShortOffsetRunHeader::new(17, 65279), ShortOffsetRunHeader::new(25, 69821), + ShortOffsetRunHeader::new(29, 78896), ShortOffsetRunHeader::new(33, 113824), + ShortOffsetRunHeader::new(35, 119155), ShortOffsetRunHeader::new(37, 917505), + ShortOffsetRunHeader::new(39, 2031744), + ]; + static OFFSETS: [u8; 43] = [ + 173, 1, 0, 6, 22, 1, 192, 1, 49, 1, 0, 2, 80, 1, 0, 1, 0, 5, 26, 5, 49, 5, 1, 10, 0, 1, + 249, 3, 0, 1, 15, 1, 0, 16, 0, 4, 0, 8, 0, 1, 30, 96, 0, + ]; + #[inline] + pub fn lookup(c: char) -> bool { + debug_assert!(!c.is_ascii()); + (c as u32) >= 0xad && lookup_slow(c) + } + + #[inline(never)] + fn lookup_slow(c: char) -> bool { + const { + assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > char::MAX as u32); + let mut i = 0; + while i < SHORT_OFFSET_RUNS.len() { + assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len()); + i += 1; + } + } + // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX` + // and the start indices of all elements in `SHORT_OFFSET_RUNS` are smaller than `OFFSETS.len()`. + unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) } + } +} + +#[rustfmt::skip] +pub mod cn_planes_0_3 { + use super::ShortOffsetRunHeader; + + static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; 54] = [ + ShortOffsetRunHeader::new(0, 888), ShortOffsetRunHeader::new(1, 1328), + ShortOffsetRunHeader::new(11, 1806), ShortOffsetRunHeader::new(25, 4681), + ShortOffsetRunHeader::new(325, 5789), ShortOffsetRunHeader::new(365, 7958), + ShortOffsetRunHeader::new(445, 9258), ShortOffsetRunHeader::new(491, 11124), + ShortOffsetRunHeader::new(495, 11508), ShortOffsetRunHeader::new(497, 42125), + ShortOffsetRunHeader::new(549, 42540), ShortOffsetRunHeader::new(553, 55204), + ShortOffsetRunHeader::new(605, 64110), ShortOffsetRunHeader::new(611, 64976), + ShortOffsetRunHeader::new(629, 67383), ShortOffsetRunHeader::new(735, 74650), + ShortOffsetRunHeader::new(1067, 77712), ShortOffsetRunHeader::new(1074, 78934), + ShortOffsetRunHeader::new(1077, 82939), ShortOffsetRunHeader::new(1079, 83527), + ShortOffsetRunHeader::new(1081, 90368), ShortOffsetRunHeader::new(1082, 92160), + ShortOffsetRunHeader::new(1084, 92729), ShortOffsetRunHeader::new(1085, 93504), + ShortOffsetRunHeader::new(1108, 101590), ShortOffsetRunHeader::new(1127, 110576), + ShortOffsetRunHeader::new(1132, 110883), ShortOffsetRunHeader::new(1139, 111356), + ShortOffsetRunHeader::new(1149, 113664), ShortOffsetRunHeader::new(1150, 117760), + ShortOffsetRunHeader::new(1160, 118452), ShortOffsetRunHeader::new(1163, 120486), + ShortOffsetRunHeader::new(1227, 120780), ShortOffsetRunHeader::new(1229, 121484), + ShortOffsetRunHeader::new(1231, 122624), ShortOffsetRunHeader::new(1236, 123536), + ShortOffsetRunHeader::new(1262, 124112), ShortOffsetRunHeader::new(1268, 126065), + ShortOffsetRunHeader::new(1298, 126976), ShortOffsetRunHeader::new(1370, 128729), + ShortOffsetRunHeader::new(1395, 129624), ShortOffsetRunHeader::new(1423, 131072), + ShortOffsetRunHeader::new(1444, 173792), ShortOffsetRunHeader::new(1445, 178206), + ShortOffsetRunHeader::new(1447, 183982), ShortOffsetRunHeader::new(1449, 191457), + ShortOffsetRunHeader::new(1451, 192094), ShortOffsetRunHeader::new(1453, 194560), + ShortOffsetRunHeader::new(1454, 195102), ShortOffsetRunHeader::new(1455, 196608), + ShortOffsetRunHeader::new(1456, 201547), ShortOffsetRunHeader::new(1457, 210042), + ShortOffsetRunHeader::new(1459, 262142), ShortOffsetRunHeader::new(1460, 1376254), + ]; + static OFFSETS: [u8; 1461] = [ + 0, 2, 6, 4, 7, 1, 1, 1, 20, 1, 0, 1, 38, 2, 50, 2, 3, 1, 55, 8, 27, 4, 6, 11, 0, 1, 60, 2, + 101, 14, 59, 2, 49, 2, 15, 1, 28, 2, 1, 1, 11, 5, 34, 5, 237, 1, 8, 2, 2, 2, 22, 1, 7, 1, 1, + 3, 4, 2, 9, 2, 2, 2, 4, 8, 1, 4, 2, 1, 5, 2, 25, 2, 3, 1, 6, 4, 2, 2, 22, 1, 7, 1, 2, 1, 2, + 1, 2, 2, 1, 1, 5, 4, 2, 2, 3, 3, 1, 7, 4, 1, 1, 7, 17, 10, 3, 1, 9, 1, 3, 1, 22, 1, 7, 1, 2, + 1, 5, 2, 10, 1, 3, 1, 3, 2, 1, 15, 4, 2, 12, 7, 7, 1, 3, 1, 8, 2, 2, 2, 22, 1, 7, 1, 2, 1, + 5, 2, 9, 2, 2, 2, 3, 7, 3, 4, 2, 1, 5, 2, 18, 10, 2, 1, 6, 3, 3, 1, 4, 3, 2, 1, 1, 1, 2, 3, + 2, 3, 3, 3, 12, 4, 5, 3, 3, 1, 4, 2, 1, 6, 1, 14, 21, 5, 13, 1, 3, 1, 23, 1, 16, 2, 9, 1, 3, + 1, 4, 7, 2, 1, 3, 1, 2, 2, 4, 2, 10, 7, 22, 1, 3, 1, 23, 1, 10, 1, 5, 2, 9, 1, 3, 1, 4, 7, + 2, 5, 3, 1, 4, 2, 10, 1, 3, 12, 13, 1, 3, 1, 51, 1, 3, 1, 6, 4, 16, 2, 26, 1, 3, 1, 18, 3, + 24, 1, 9, 1, 1, 2, 7, 3, 1, 4, 6, 1, 1, 1, 8, 6, 10, 2, 3, 12, 58, 4, 29, 37, 2, 1, 1, 1, 5, + 1, 24, 1, 1, 1, 23, 2, 5, 1, 1, 1, 7, 1, 10, 2, 4, 32, 72, 1, 36, 4, 39, 1, 36, 1, 15, 1, + 13, 37, 198, 1, 1, 5, 1, 2, 0, 1, 4, 2, 7, 1, 1, 1, 4, 2, 41, 1, 4, 2, 33, 1, 4, 2, 7, 1, 1, + 1, 4, 2, 15, 1, 57, 1, 4, 2, 67, 2, 32, 3, 26, 6, 86, 2, 6, 2, 0, 3, 89, 7, 22, 9, 24, 9, + 20, 12, 13, 1, 3, 1, 2, 12, 94, 2, 10, 6, 10, 6, 26, 6, 89, 7, 43, 5, 70, 10, 31, 1, 12, 4, + 12, 4, 1, 3, 42, 2, 5, 11, 44, 4, 26, 6, 11, 3, 62, 2, 65, 1, 29, 2, 11, 6, 10, 6, 14, 2, + 46, 2, 12, 20, 77, 1, 166, 8, 60, 3, 15, 3, 62, 5, 43, 2, 11, 8, 43, 5, 0, 2, 6, 2, 38, 2, + 6, 2, 8, 1, 1, 1, 1, 1, 1, 1, 31, 2, 53, 1, 15, 1, 14, 2, 6, 1, 19, 2, 3, 1, 9, 1, 101, 1, + 12, 2, 27, 1, 13, 3, 34, 14, 33, 15, 140, 4, 0, 22, 11, 21, 0, 2, 0, 5, 45, 1, 1, 5, 1, 2, + 56, 7, 2, 14, 24, 9, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 126, 34, 26, 1, 89, 12, + 214, 26, 80, 1, 86, 2, 103, 5, 43, 1, 94, 1, 86, 9, 48, 1, 0, 3, 55, 9, 0, 20, 184, 8, 221, + 20, 60, 3, 10, 6, 56, 8, 70, 8, 12, 6, 116, 11, 30, 3, 78, 1, 11, 4, 33, 1, 55, 9, 14, 2, + 10, 2, 103, 24, 28, 10, 6, 2, 6, 2, 6, 9, 7, 1, 7, 1, 60, 4, 126, 2, 10, 6, 0, 12, 23, 4, + 49, 4, 0, 2, 106, 38, 7, 12, 5, 5, 26, 1, 5, 1, 1, 1, 2, 1, 2, 1, 0, 32, 42, 6, 51, 1, 19, + 1, 4, 4, 5, 1, 135, 2, 1, 1, 190, 3, 6, 2, 6, 2, 6, 2, 3, 3, 7, 1, 7, 10, 5, 2, 12, 1, 26, + 1, 19, 1, 2, 1, 15, 2, 14, 34, 123, 5, 3, 4, 45, 3, 88, 1, 13, 3, 1, 47, 46, 130, 29, 3, 49, + 15, 28, 4, 36, 9, 30, 5, 43, 5, 30, 1, 37, 4, 14, 42, 158, 2, 10, 6, 36, 4, 36, 4, 40, 8, + 52, 11, 12, 1, 15, 1, 7, 1, 2, 1, 11, 1, 15, 1, 7, 1, 2, 3, 52, 12, 0, 9, 22, 10, 8, 24, 6, + 1, 42, 1, 9, 69, 6, 2, 1, 1, 44, 1, 2, 3, 1, 2, 23, 1, 72, 8, 9, 48, 19, 1, 2, 5, 33, 3, 27, + 5, 27, 38, 56, 4, 20, 2, 50, 1, 2, 5, 8, 1, 3, 1, 29, 2, 3, 4, 10, 7, 9, 7, 64, 32, 39, 4, + 12, 9, 54, 3, 29, 2, 27, 5, 26, 7, 4, 12, 7, 80, 73, 55, 51, 13, 51, 7, 46, 8, 10, 6, 38, 3, + 29, 8, 2, 208, 31, 1, 42, 1, 3, 2, 2, 16, 6, 8, 9, 33, 46, 8, 42, 22, 26, 38, 28, 20, 23, 9, + 78, 4, 36, 9, 68, 10, 1, 2, 25, 7, 10, 6, 53, 1, 18, 8, 39, 9, 96, 1, 20, 11, 18, 1, 47, 62, + 7, 1, 1, 1, 4, 1, 15, 1, 11, 6, 59, 5, 10, 6, 4, 1, 8, 2, 2, 2, 22, 1, 7, 1, 2, 1, 5, 1, 10, + 2, 2, 2, 3, 2, 1, 6, 1, 5, 7, 2, 7, 3, 5, 11, 10, 1, 1, 2, 1, 1, 38, 1, 10, 1, 1, 2, 1, 1, + 4, 1, 10, 1, 2, 8, 2, 29, 92, 1, 5, 30, 72, 8, 10, 166, 54, 2, 38, 34, 69, 11, 10, 6, 13, + 19, 58, 6, 10, 6, 20, 28, 27, 2, 15, 4, 23, 185, 60, 100, 83, 12, 8, 2, 1, 2, 8, 1, 2, 1, + 30, 1, 2, 2, 12, 9, 10, 70, 8, 2, 46, 2, 11, 27, 72, 8, 83, 13, 73, 7, 10, 86, 8, 88, 34, + 14, 10, 6, 9, 1, 45, 1, 14, 10, 29, 3, 32, 2, 22, 1, 14, 73, 7, 1, 2, 1, 44, 3, 1, 1, 2, 1, + 9, 8, 10, 6, 6, 1, 2, 1, 37, 1, 2, 1, 6, 7, 10, 6, 44, 4, 10, 246, 25, 7, 17, 1, 41, 3, 29, + 85, 1, 15, 50, 13, 0, 102, 111, 1, 5, 11, 196, 0, 99, 13, 0, 10, 0, 5, 0, 0, 58, 0, 0, 7, + 31, 1, 10, 4, 81, 1, 10, 6, 30, 2, 6, 10, 70, 10, 10, 1, 7, 1, 21, 5, 19, 0, 58, 198, 91, 5, + 25, 2, 25, 44, 75, 4, 57, 7, 17, 64, 5, 11, 7, 9, 0, 41, 32, 97, 115, 0, 4, 1, 7, 1, 2, 1, + 0, 15, 1, 29, 3, 2, 1, 14, 4, 8, 0, 0, 107, 5, 13, 3, 9, 7, 10, 2, 8, 0, 253, 3, 0, 6, 23, + 15, 17, 15, 46, 2, 23, 9, 116, 60, 246, 10, 39, 2, 194, 21, 70, 122, 20, 12, 20, 12, 87, 9, + 25, 135, 85, 1, 71, 1, 2, 2, 1, 2, 2, 2, 4, 1, 12, 1, 1, 1, 7, 1, 65, 1, 4, 2, 8, 1, 7, 1, + 28, 1, 4, 1, 5, 1, 1, 3, 7, 1, 0, 2, 0, 2, 0, 15, 5, 1, 15, 0, 31, 6, 6, 213, 7, 1, 17, 2, + 7, 1, 2, 1, 5, 5, 62, 33, 1, 112, 45, 3, 14, 2, 10, 4, 2, 0, 31, 17, 58, 5, 1, 0, 42, 214, + 43, 4, 1, 192, 31, 1, 22, 8, 2, 224, 7, 1, 4, 1, 2, 1, 15, 1, 197, 2, 16, 41, 76, 4, 10, 4, + 2, 0, 68, 76, 61, 194, 4, 1, 27, 1, 2, 1, 1, 2, 1, 1, 10, 1, 4, 1, 1, 1, 1, 6, 1, 4, 1, 1, + 1, 1, 1, 1, 3, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 4, 1, 7, 1, 4, 1, 4, + 1, 1, 1, 10, 1, 17, 5, 3, 1, 5, 1, 17, 52, 2, 0, 44, 4, 100, 12, 15, 2, 15, 1, 15, 1, 37, + 10, 174, 56, 29, 13, 44, 4, 9, 7, 2, 14, 6, 154, 0, 3, 17, 3, 13, 3, 218, 6, 12, 4, 1, 15, + 12, 4, 56, 8, 10, 6, 40, 8, 30, 2, 12, 4, 2, 14, 9, 39, 0, 8, 14, 2, 13, 3, 11, 3, 57, 1, 1, + 4, 16, 2, 12, 4, 10, 7, 147, 1, 103, 0, 0, 32, 0, 2, 0, 2, 0, 15, 0, 0, 0, 0, 0, 5, 0, 0, 0, + ]; + #[inline] + pub fn lookup(c: char) -> bool { + debug_assert!(!c.is_ascii()); + (c as u32) >= 0x378 && lookup_slow(c) + } + + #[inline(never)] + fn lookup_slow(c: char) -> bool { + const { + assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > char::MAX as u32); + let mut i = 0; + while i < SHORT_OFFSET_RUNS.len() { + assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len()); + i += 1; + } + } + // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX` + // and the start indices of all elements in `SHORT_OFFSET_RUNS` are smaller than `OFFSETS.len()`. + unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) } + } +} + #[rustfmt::skip] pub mod grapheme_extend { use super::ShortOffsetRunHeader; diff --git a/library/coretests/tests/unicode.rs b/library/coretests/tests/unicode.rs index 05cea23fd4781..1199049ab26b0 100644 --- a/library/coretests/tests/unicode.rs +++ b/library/coretests/tests/unicode.rs @@ -1,3 +1,4 @@ +use core::iter::Step; use core::unicode::unicode_data; use std::ops::RangeInclusive; @@ -19,7 +20,7 @@ fn test_boolean_property(ranges: &[RangeInclusive], lookup: fn(char) -> bo for c in range.clone() { assert!(lookup(c), "{c:?}"); } - start = char::from_u32(*range.end() as u32 + 1).unwrap(); + start = Step::forward(*range.end(), 1); } for c in start..=char::MAX { assert!(!lookup(c), "{c:?}"); @@ -60,9 +61,14 @@ fn case_ignorable() { #[test] #[cfg_attr(miri, ignore)] // Miri is too slow -fn lt() { - test_boolean_property(test_data::LT, unicode_data::lt::lookup); - test_boolean_property(test_data::LT, char::is_titlecase); +fn cf() { + test_boolean_property(test_data::CF, unicode_data::cf::lookup); +} + +#[test] +#[cfg_attr(miri, ignore)] // Miri is too slow +fn cn_planes_0_3() { + test_boolean_property(test_data::CN_PLANES_0_3, unicode_data::cn_planes_0_3::lookup); } #[test] @@ -78,6 +84,13 @@ fn lowercase() { test_boolean_property(test_data::LOWERCASE, char::is_lowercase); } +#[test] +#[cfg_attr(miri, ignore)] // Miri is too slow +fn lt() { + test_boolean_property(test_data::LT, unicode_data::lt::lookup); + test_boolean_property(test_data::LT, char::is_titlecase); +} + #[test] #[cfg_attr(miri, ignore)] // Miri is too slow fn n() { diff --git a/library/coretests/tests/unicode/test_data.rs b/library/coretests/tests/unicode/test_data.rs index 77b976c489c9b..4c0efca66c020 100644 --- a/library/coretests/tests/unicode/test_data.rs +++ b/library/coretests/tests/unicode/test_data.rs @@ -392,6 +392,252 @@ pub(super) static CASE_IGNORABLE: &[RangeInclusive; 459] = &[ '\u{e0100}'..='\u{e01ef}', ]; +#[rustfmt::skip] +pub(super) static CF: &[RangeInclusive; 21] = &[ + '\u{ad}'..='\u{ad}', '\u{600}'..='\u{605}', '\u{61c}'..='\u{61c}', '\u{6dd}'..='\u{6dd}', + '\u{70f}'..='\u{70f}', '\u{890}'..='\u{891}', '\u{8e2}'..='\u{8e2}', + '\u{180e}'..='\u{180e}', '\u{200b}'..='\u{200f}', '\u{202a}'..='\u{202e}', + '\u{2060}'..='\u{2064}', '\u{2066}'..='\u{206f}', '\u{feff}'..='\u{feff}', + '\u{fff9}'..='\u{fffb}', '\u{110bd}'..='\u{110bd}', '\u{110cd}'..='\u{110cd}', + '\u{13430}'..='\u{1343f}', '\u{1bca0}'..='\u{1bca3}', '\u{1d173}'..='\u{1d17a}', + '\u{e0001}'..='\u{e0001}', '\u{e0020}'..='\u{e007f}', +]; + +#[rustfmt::skip] +pub(super) static CN_PLANES_0_3: &[RangeInclusive; 730] = &[ + '\u{378}'..='\u{379}', '\u{380}'..='\u{383}', '\u{38b}'..='\u{38b}', '\u{38d}'..='\u{38d}', + '\u{3a2}'..='\u{3a2}', '\u{530}'..='\u{530}', '\u{557}'..='\u{558}', '\u{58b}'..='\u{58c}', + '\u{590}'..='\u{590}', '\u{5c8}'..='\u{5cf}', '\u{5eb}'..='\u{5ee}', '\u{5f5}'..='\u{5ff}', + '\u{70e}'..='\u{70e}', '\u{74b}'..='\u{74c}', '\u{7b2}'..='\u{7bf}', '\u{7fb}'..='\u{7fc}', + '\u{82e}'..='\u{82f}', '\u{83f}'..='\u{83f}', '\u{85c}'..='\u{85d}', '\u{85f}'..='\u{85f}', + '\u{86b}'..='\u{86f}', '\u{892}'..='\u{896}', '\u{984}'..='\u{984}', '\u{98d}'..='\u{98e}', + '\u{991}'..='\u{992}', '\u{9a9}'..='\u{9a9}', '\u{9b1}'..='\u{9b1}', '\u{9b3}'..='\u{9b5}', + '\u{9ba}'..='\u{9bb}', '\u{9c5}'..='\u{9c6}', '\u{9c9}'..='\u{9ca}', '\u{9cf}'..='\u{9d6}', + '\u{9d8}'..='\u{9db}', '\u{9de}'..='\u{9de}', '\u{9e4}'..='\u{9e5}', '\u{9ff}'..='\u{a00}', + '\u{a04}'..='\u{a04}', '\u{a0b}'..='\u{a0e}', '\u{a11}'..='\u{a12}', '\u{a29}'..='\u{a29}', + '\u{a31}'..='\u{a31}', '\u{a34}'..='\u{a34}', '\u{a37}'..='\u{a37}', '\u{a3a}'..='\u{a3b}', + '\u{a3d}'..='\u{a3d}', '\u{a43}'..='\u{a46}', '\u{a49}'..='\u{a4a}', '\u{a4e}'..='\u{a50}', + '\u{a52}'..='\u{a58}', '\u{a5d}'..='\u{a5d}', '\u{a5f}'..='\u{a65}', '\u{a77}'..='\u{a80}', + '\u{a84}'..='\u{a84}', '\u{a8e}'..='\u{a8e}', '\u{a92}'..='\u{a92}', '\u{aa9}'..='\u{aa9}', + '\u{ab1}'..='\u{ab1}', '\u{ab4}'..='\u{ab4}', '\u{aba}'..='\u{abb}', '\u{ac6}'..='\u{ac6}', + '\u{aca}'..='\u{aca}', '\u{ace}'..='\u{acf}', '\u{ad1}'..='\u{adf}', '\u{ae4}'..='\u{ae5}', + '\u{af2}'..='\u{af8}', '\u{b00}'..='\u{b00}', '\u{b04}'..='\u{b04}', '\u{b0d}'..='\u{b0e}', + '\u{b11}'..='\u{b12}', '\u{b29}'..='\u{b29}', '\u{b31}'..='\u{b31}', '\u{b34}'..='\u{b34}', + '\u{b3a}'..='\u{b3b}', '\u{b45}'..='\u{b46}', '\u{b49}'..='\u{b4a}', '\u{b4e}'..='\u{b54}', + '\u{b58}'..='\u{b5b}', '\u{b5e}'..='\u{b5e}', '\u{b64}'..='\u{b65}', '\u{b78}'..='\u{b81}', + '\u{b84}'..='\u{b84}', '\u{b8b}'..='\u{b8d}', '\u{b91}'..='\u{b91}', '\u{b96}'..='\u{b98}', + '\u{b9b}'..='\u{b9b}', '\u{b9d}'..='\u{b9d}', '\u{ba0}'..='\u{ba2}', '\u{ba5}'..='\u{ba7}', + '\u{bab}'..='\u{bad}', '\u{bba}'..='\u{bbd}', '\u{bc3}'..='\u{bc5}', '\u{bc9}'..='\u{bc9}', + '\u{bce}'..='\u{bcf}', '\u{bd1}'..='\u{bd6}', '\u{bd8}'..='\u{be5}', '\u{bfb}'..='\u{bff}', + '\u{c0d}'..='\u{c0d}', '\u{c11}'..='\u{c11}', '\u{c29}'..='\u{c29}', '\u{c3a}'..='\u{c3b}', + '\u{c45}'..='\u{c45}', '\u{c49}'..='\u{c49}', '\u{c4e}'..='\u{c54}', '\u{c57}'..='\u{c57}', + '\u{c5b}'..='\u{c5b}', '\u{c5e}'..='\u{c5f}', '\u{c64}'..='\u{c65}', '\u{c70}'..='\u{c76}', + '\u{c8d}'..='\u{c8d}', '\u{c91}'..='\u{c91}', '\u{ca9}'..='\u{ca9}', '\u{cb4}'..='\u{cb4}', + '\u{cba}'..='\u{cbb}', '\u{cc5}'..='\u{cc5}', '\u{cc9}'..='\u{cc9}', '\u{cce}'..='\u{cd4}', + '\u{cd7}'..='\u{cdb}', '\u{cdf}'..='\u{cdf}', '\u{ce4}'..='\u{ce5}', '\u{cf0}'..='\u{cf0}', + '\u{cf4}'..='\u{cff}', '\u{d0d}'..='\u{d0d}', '\u{d11}'..='\u{d11}', '\u{d45}'..='\u{d45}', + '\u{d49}'..='\u{d49}', '\u{d50}'..='\u{d53}', '\u{d64}'..='\u{d65}', '\u{d80}'..='\u{d80}', + '\u{d84}'..='\u{d84}', '\u{d97}'..='\u{d99}', '\u{db2}'..='\u{db2}', '\u{dbc}'..='\u{dbc}', + '\u{dbe}'..='\u{dbf}', '\u{dc7}'..='\u{dc9}', '\u{dcb}'..='\u{dce}', '\u{dd5}'..='\u{dd5}', + '\u{dd7}'..='\u{dd7}', '\u{de0}'..='\u{de5}', '\u{df0}'..='\u{df1}', '\u{df5}'..='\u{e00}', + '\u{e3b}'..='\u{e3e}', '\u{e5c}'..='\u{e80}', '\u{e83}'..='\u{e83}', '\u{e85}'..='\u{e85}', + '\u{e8b}'..='\u{e8b}', '\u{ea4}'..='\u{ea4}', '\u{ea6}'..='\u{ea6}', '\u{ebe}'..='\u{ebf}', + '\u{ec5}'..='\u{ec5}', '\u{ec7}'..='\u{ec7}', '\u{ecf}'..='\u{ecf}', '\u{eda}'..='\u{edb}', + '\u{ee0}'..='\u{eff}', '\u{f48}'..='\u{f48}', '\u{f6d}'..='\u{f70}', '\u{f98}'..='\u{f98}', + '\u{fbd}'..='\u{fbd}', '\u{fcd}'..='\u{fcd}', '\u{fdb}'..='\u{fff}', + '\u{10c6}'..='\u{10c6}', '\u{10c8}'..='\u{10cc}', '\u{10ce}'..='\u{10cf}', + '\u{1249}'..='\u{1249}', '\u{124e}'..='\u{124f}', '\u{1257}'..='\u{1257}', + '\u{1259}'..='\u{1259}', '\u{125e}'..='\u{125f}', '\u{1289}'..='\u{1289}', + '\u{128e}'..='\u{128f}', '\u{12b1}'..='\u{12b1}', '\u{12b6}'..='\u{12b7}', + '\u{12bf}'..='\u{12bf}', '\u{12c1}'..='\u{12c1}', '\u{12c6}'..='\u{12c7}', + '\u{12d7}'..='\u{12d7}', '\u{1311}'..='\u{1311}', '\u{1316}'..='\u{1317}', + '\u{135b}'..='\u{135c}', '\u{137d}'..='\u{137f}', '\u{139a}'..='\u{139f}', + '\u{13f6}'..='\u{13f7}', '\u{13fe}'..='\u{13ff}', '\u{169d}'..='\u{169f}', + '\u{16f9}'..='\u{16ff}', '\u{1716}'..='\u{171e}', '\u{1737}'..='\u{173f}', + '\u{1754}'..='\u{175f}', '\u{176d}'..='\u{176d}', '\u{1771}'..='\u{1771}', + '\u{1774}'..='\u{177f}', '\u{17de}'..='\u{17df}', '\u{17ea}'..='\u{17ef}', + '\u{17fa}'..='\u{17ff}', '\u{181a}'..='\u{181f}', '\u{1879}'..='\u{187f}', + '\u{18ab}'..='\u{18af}', '\u{18f6}'..='\u{18ff}', '\u{191f}'..='\u{191f}', + '\u{192c}'..='\u{192f}', '\u{193c}'..='\u{193f}', '\u{1941}'..='\u{1943}', + '\u{196e}'..='\u{196f}', '\u{1975}'..='\u{197f}', '\u{19ac}'..='\u{19af}', + '\u{19ca}'..='\u{19cf}', '\u{19db}'..='\u{19dd}', '\u{1a1c}'..='\u{1a1d}', + '\u{1a5f}'..='\u{1a5f}', '\u{1a7d}'..='\u{1a7e}', '\u{1a8a}'..='\u{1a8f}', + '\u{1a9a}'..='\u{1a9f}', '\u{1aae}'..='\u{1aaf}', '\u{1ade}'..='\u{1adf}', + '\u{1aec}'..='\u{1aff}', '\u{1b4d}'..='\u{1b4d}', '\u{1bf4}'..='\u{1bfb}', + '\u{1c38}'..='\u{1c3a}', '\u{1c4a}'..='\u{1c4c}', '\u{1c8b}'..='\u{1c8f}', + '\u{1cbb}'..='\u{1cbc}', '\u{1cc8}'..='\u{1ccf}', '\u{1cfb}'..='\u{1cff}', + '\u{1f16}'..='\u{1f17}', '\u{1f1e}'..='\u{1f1f}', '\u{1f46}'..='\u{1f47}', + '\u{1f4e}'..='\u{1f4f}', '\u{1f58}'..='\u{1f58}', '\u{1f5a}'..='\u{1f5a}', + '\u{1f5c}'..='\u{1f5c}', '\u{1f5e}'..='\u{1f5e}', '\u{1f7e}'..='\u{1f7f}', + '\u{1fb5}'..='\u{1fb5}', '\u{1fc5}'..='\u{1fc5}', '\u{1fd4}'..='\u{1fd5}', + '\u{1fdc}'..='\u{1fdc}', '\u{1ff0}'..='\u{1ff1}', '\u{1ff5}'..='\u{1ff5}', + '\u{1fff}'..='\u{1fff}', '\u{2065}'..='\u{2065}', '\u{2072}'..='\u{2073}', + '\u{208f}'..='\u{208f}', '\u{209d}'..='\u{209f}', '\u{20c2}'..='\u{20cf}', + '\u{20f1}'..='\u{20ff}', '\u{218c}'..='\u{218f}', '\u{242a}'..='\u{243f}', + '\u{244b}'..='\u{245f}', '\u{2b74}'..='\u{2b75}', '\u{2cf4}'..='\u{2cf8}', + '\u{2d26}'..='\u{2d26}', '\u{2d28}'..='\u{2d2c}', '\u{2d2e}'..='\u{2d2f}', + '\u{2d68}'..='\u{2d6e}', '\u{2d71}'..='\u{2d7e}', '\u{2d97}'..='\u{2d9f}', + '\u{2da7}'..='\u{2da7}', '\u{2daf}'..='\u{2daf}', '\u{2db7}'..='\u{2db7}', + '\u{2dbf}'..='\u{2dbf}', '\u{2dc7}'..='\u{2dc7}', '\u{2dcf}'..='\u{2dcf}', + '\u{2dd7}'..='\u{2dd7}', '\u{2ddf}'..='\u{2ddf}', '\u{2e5e}'..='\u{2e7f}', + '\u{2e9a}'..='\u{2e9a}', '\u{2ef4}'..='\u{2eff}', '\u{2fd6}'..='\u{2fef}', + '\u{3040}'..='\u{3040}', '\u{3097}'..='\u{3098}', '\u{3100}'..='\u{3104}', + '\u{3130}'..='\u{3130}', '\u{318f}'..='\u{318f}', '\u{31e6}'..='\u{31ee}', + '\u{321f}'..='\u{321f}', '\u{a48d}'..='\u{a48f}', '\u{a4c7}'..='\u{a4cf}', + '\u{a62c}'..='\u{a63f}', '\u{a6f8}'..='\u{a6ff}', '\u{a7dd}'..='\u{a7f0}', + '\u{a82d}'..='\u{a82f}', '\u{a83a}'..='\u{a83f}', '\u{a878}'..='\u{a87f}', + '\u{a8c6}'..='\u{a8cd}', '\u{a8da}'..='\u{a8df}', '\u{a954}'..='\u{a95e}', + '\u{a97d}'..='\u{a97f}', '\u{a9ce}'..='\u{a9ce}', '\u{a9da}'..='\u{a9dd}', + '\u{a9ff}'..='\u{a9ff}', '\u{aa37}'..='\u{aa3f}', '\u{aa4e}'..='\u{aa4f}', + '\u{aa5a}'..='\u{aa5b}', '\u{aac3}'..='\u{aada}', '\u{aaf7}'..='\u{ab00}', + '\u{ab07}'..='\u{ab08}', '\u{ab0f}'..='\u{ab10}', '\u{ab17}'..='\u{ab1f}', + '\u{ab27}'..='\u{ab27}', '\u{ab2f}'..='\u{ab2f}', '\u{ab6c}'..='\u{ab6f}', + '\u{abee}'..='\u{abef}', '\u{abfa}'..='\u{abff}', '\u{d7a4}'..='\u{d7af}', + '\u{d7c7}'..='\u{d7ca}', '\u{d7fc}'..='\u{d7ff}', '\u{fa6e}'..='\u{fa6f}', + '\u{fada}'..='\u{faff}', '\u{fb07}'..='\u{fb12}', '\u{fb18}'..='\u{fb1c}', + '\u{fb37}'..='\u{fb37}', '\u{fb3d}'..='\u{fb3d}', '\u{fb3f}'..='\u{fb3f}', + '\u{fb42}'..='\u{fb42}', '\u{fb45}'..='\u{fb45}', '\u{fdd0}'..='\u{fdef}', + '\u{fe1a}'..='\u{fe1f}', '\u{fe53}'..='\u{fe53}', '\u{fe67}'..='\u{fe67}', + '\u{fe6c}'..='\u{fe6f}', '\u{fe75}'..='\u{fe75}', '\u{fefd}'..='\u{fefe}', + '\u{ff00}'..='\u{ff00}', '\u{ffbf}'..='\u{ffc1}', '\u{ffc8}'..='\u{ffc9}', + '\u{ffd0}'..='\u{ffd1}', '\u{ffd8}'..='\u{ffd9}', '\u{ffdd}'..='\u{ffdf}', + '\u{ffe7}'..='\u{ffe7}', '\u{ffef}'..='\u{fff8}', '\u{fffe}'..='\u{ffff}', + '\u{1000c}'..='\u{1000c}', '\u{10027}'..='\u{10027}', '\u{1003b}'..='\u{1003b}', + '\u{1003e}'..='\u{1003e}', '\u{1004e}'..='\u{1004f}', '\u{1005e}'..='\u{1007f}', + '\u{100fb}'..='\u{100ff}', '\u{10103}'..='\u{10106}', '\u{10134}'..='\u{10136}', + '\u{1018f}'..='\u{1018f}', '\u{1019d}'..='\u{1019f}', '\u{101a1}'..='\u{101cf}', + '\u{101fe}'..='\u{1027f}', '\u{1029d}'..='\u{1029f}', '\u{102d1}'..='\u{102df}', + '\u{102fc}'..='\u{102ff}', '\u{10324}'..='\u{1032c}', '\u{1034b}'..='\u{1034f}', + '\u{1037b}'..='\u{1037f}', '\u{1039e}'..='\u{1039e}', '\u{103c4}'..='\u{103c7}', + '\u{103d6}'..='\u{103ff}', '\u{1049e}'..='\u{1049f}', '\u{104aa}'..='\u{104af}', + '\u{104d4}'..='\u{104d7}', '\u{104fc}'..='\u{104ff}', '\u{10528}'..='\u{1052f}', + '\u{10564}'..='\u{1056e}', '\u{1057b}'..='\u{1057b}', '\u{1058b}'..='\u{1058b}', + '\u{10593}'..='\u{10593}', '\u{10596}'..='\u{10596}', '\u{105a2}'..='\u{105a2}', + '\u{105b2}'..='\u{105b2}', '\u{105ba}'..='\u{105ba}', '\u{105bd}'..='\u{105bf}', + '\u{105f4}'..='\u{105ff}', '\u{10737}'..='\u{1073f}', '\u{10756}'..='\u{1075f}', + '\u{10768}'..='\u{1077f}', '\u{10786}'..='\u{10786}', '\u{107b1}'..='\u{107b1}', + '\u{107bb}'..='\u{107ff}', '\u{10806}'..='\u{10807}', '\u{10809}'..='\u{10809}', + '\u{10836}'..='\u{10836}', '\u{10839}'..='\u{1083b}', '\u{1083d}'..='\u{1083e}', + '\u{10856}'..='\u{10856}', '\u{1089f}'..='\u{108a6}', '\u{108b0}'..='\u{108df}', + '\u{108f3}'..='\u{108f3}', '\u{108f6}'..='\u{108fa}', '\u{1091c}'..='\u{1091e}', + '\u{1093a}'..='\u{1093e}', '\u{1095a}'..='\u{1097f}', '\u{109b8}'..='\u{109bb}', + '\u{109d0}'..='\u{109d1}', '\u{10a04}'..='\u{10a04}', '\u{10a07}'..='\u{10a0b}', + '\u{10a14}'..='\u{10a14}', '\u{10a18}'..='\u{10a18}', '\u{10a36}'..='\u{10a37}', + '\u{10a3b}'..='\u{10a3e}', '\u{10a49}'..='\u{10a4f}', '\u{10a59}'..='\u{10a5f}', + '\u{10aa0}'..='\u{10abf}', '\u{10ae7}'..='\u{10aea}', '\u{10af7}'..='\u{10aff}', + '\u{10b36}'..='\u{10b38}', '\u{10b56}'..='\u{10b57}', '\u{10b73}'..='\u{10b77}', + '\u{10b92}'..='\u{10b98}', '\u{10b9d}'..='\u{10ba8}', '\u{10bb0}'..='\u{10bff}', + '\u{10c49}'..='\u{10c7f}', '\u{10cb3}'..='\u{10cbf}', '\u{10cf3}'..='\u{10cf9}', + '\u{10d28}'..='\u{10d2f}', '\u{10d3a}'..='\u{10d3f}', '\u{10d66}'..='\u{10d68}', + '\u{10d86}'..='\u{10d8d}', '\u{10d90}'..='\u{10e5f}', '\u{10e7f}'..='\u{10e7f}', + '\u{10eaa}'..='\u{10eaa}', '\u{10eae}'..='\u{10eaf}', '\u{10eb2}'..='\u{10ec1}', + '\u{10ec8}'..='\u{10ecf}', '\u{10ed9}'..='\u{10ef9}', '\u{10f28}'..='\u{10f2f}', + '\u{10f5a}'..='\u{10f6f}', '\u{10f8a}'..='\u{10faf}', '\u{10fcc}'..='\u{10fdf}', + '\u{10ff7}'..='\u{10fff}', '\u{1104e}'..='\u{11051}', '\u{11076}'..='\u{1107e}', + '\u{110c3}'..='\u{110cc}', '\u{110ce}'..='\u{110cf}', '\u{110e9}'..='\u{110ef}', + '\u{110fa}'..='\u{110ff}', '\u{11135}'..='\u{11135}', '\u{11148}'..='\u{1114f}', + '\u{11177}'..='\u{1117f}', '\u{111e0}'..='\u{111e0}', '\u{111f5}'..='\u{111ff}', + '\u{11212}'..='\u{11212}', '\u{11242}'..='\u{1127f}', '\u{11287}'..='\u{11287}', + '\u{11289}'..='\u{11289}', '\u{1128e}'..='\u{1128e}', '\u{1129e}'..='\u{1129e}', + '\u{112aa}'..='\u{112af}', '\u{112eb}'..='\u{112ef}', '\u{112fa}'..='\u{112ff}', + '\u{11304}'..='\u{11304}', '\u{1130d}'..='\u{1130e}', '\u{11311}'..='\u{11312}', + '\u{11329}'..='\u{11329}', '\u{11331}'..='\u{11331}', '\u{11334}'..='\u{11334}', + '\u{1133a}'..='\u{1133a}', '\u{11345}'..='\u{11346}', '\u{11349}'..='\u{1134a}', + '\u{1134e}'..='\u{1134f}', '\u{11351}'..='\u{11356}', '\u{11358}'..='\u{1135c}', + '\u{11364}'..='\u{11365}', '\u{1136d}'..='\u{1136f}', '\u{11375}'..='\u{1137f}', + '\u{1138a}'..='\u{1138a}', '\u{1138c}'..='\u{1138d}', '\u{1138f}'..='\u{1138f}', + '\u{113b6}'..='\u{113b6}', '\u{113c1}'..='\u{113c1}', '\u{113c3}'..='\u{113c4}', + '\u{113c6}'..='\u{113c6}', '\u{113cb}'..='\u{113cb}', '\u{113d6}'..='\u{113d6}', + '\u{113d9}'..='\u{113e0}', '\u{113e3}'..='\u{113ff}', '\u{1145c}'..='\u{1145c}', + '\u{11462}'..='\u{1147f}', '\u{114c8}'..='\u{114cf}', '\u{114da}'..='\u{1157f}', + '\u{115b6}'..='\u{115b7}', '\u{115de}'..='\u{115ff}', '\u{11645}'..='\u{1164f}', + '\u{1165a}'..='\u{1165f}', '\u{1166d}'..='\u{1167f}', '\u{116ba}'..='\u{116bf}', + '\u{116ca}'..='\u{116cf}', '\u{116e4}'..='\u{116ff}', '\u{1171b}'..='\u{1171c}', + '\u{1172c}'..='\u{1172f}', '\u{11747}'..='\u{117ff}', '\u{1183c}'..='\u{1189f}', + '\u{118f3}'..='\u{118fe}', '\u{11907}'..='\u{11908}', '\u{1190a}'..='\u{1190b}', + '\u{11914}'..='\u{11914}', '\u{11917}'..='\u{11917}', '\u{11936}'..='\u{11936}', + '\u{11939}'..='\u{1193a}', '\u{11947}'..='\u{1194f}', '\u{1195a}'..='\u{1199f}', + '\u{119a8}'..='\u{119a9}', '\u{119d8}'..='\u{119d9}', '\u{119e5}'..='\u{119ff}', + '\u{11a48}'..='\u{11a4f}', '\u{11aa3}'..='\u{11aaf}', '\u{11af9}'..='\u{11aff}', + '\u{11b0a}'..='\u{11b5f}', '\u{11b68}'..='\u{11bbf}', '\u{11be2}'..='\u{11bef}', + '\u{11bfa}'..='\u{11bff}', '\u{11c09}'..='\u{11c09}', '\u{11c37}'..='\u{11c37}', + '\u{11c46}'..='\u{11c4f}', '\u{11c6d}'..='\u{11c6f}', '\u{11c90}'..='\u{11c91}', + '\u{11ca8}'..='\u{11ca8}', '\u{11cb7}'..='\u{11cff}', '\u{11d07}'..='\u{11d07}', + '\u{11d0a}'..='\u{11d0a}', '\u{11d37}'..='\u{11d39}', '\u{11d3b}'..='\u{11d3b}', + '\u{11d3e}'..='\u{11d3e}', '\u{11d48}'..='\u{11d4f}', '\u{11d5a}'..='\u{11d5f}', + '\u{11d66}'..='\u{11d66}', '\u{11d69}'..='\u{11d69}', '\u{11d8f}'..='\u{11d8f}', + '\u{11d92}'..='\u{11d92}', '\u{11d99}'..='\u{11d9f}', '\u{11daa}'..='\u{11daf}', + '\u{11ddc}'..='\u{11ddf}', '\u{11dea}'..='\u{11edf}', '\u{11ef9}'..='\u{11eff}', + '\u{11f11}'..='\u{11f11}', '\u{11f3b}'..='\u{11f3d}', '\u{11f5b}'..='\u{11faf}', + '\u{11fb1}'..='\u{11fbf}', '\u{11ff2}'..='\u{11ffe}', '\u{1239a}'..='\u{123ff}', + '\u{1246f}'..='\u{1246f}', '\u{12475}'..='\u{1247f}', '\u{12544}'..='\u{12f8f}', + '\u{12ff3}'..='\u{12fff}', '\u{13456}'..='\u{1345f}', '\u{143fb}'..='\u{143ff}', + '\u{14647}'..='\u{160ff}', '\u{1613a}'..='\u{167ff}', '\u{16a39}'..='\u{16a3f}', + '\u{16a5f}'..='\u{16a5f}', '\u{16a6a}'..='\u{16a6d}', '\u{16abf}'..='\u{16abf}', + '\u{16aca}'..='\u{16acf}', '\u{16aee}'..='\u{16aef}', '\u{16af6}'..='\u{16aff}', + '\u{16b46}'..='\u{16b4f}', '\u{16b5a}'..='\u{16b5a}', '\u{16b62}'..='\u{16b62}', + '\u{16b78}'..='\u{16b7c}', '\u{16b90}'..='\u{16d3f}', '\u{16d7a}'..='\u{16e3f}', + '\u{16e9b}'..='\u{16e9f}', '\u{16eb9}'..='\u{16eba}', '\u{16ed4}'..='\u{16eff}', + '\u{16f4b}'..='\u{16f4e}', '\u{16f88}'..='\u{16f8e}', '\u{16fa0}'..='\u{16fdf}', + '\u{16fe5}'..='\u{16fef}', '\u{16ff7}'..='\u{16fff}', '\u{18cd6}'..='\u{18cfe}', + '\u{18d1f}'..='\u{18d7f}', '\u{18df3}'..='\u{1afef}', '\u{1aff4}'..='\u{1aff4}', + '\u{1affc}'..='\u{1affc}', '\u{1afff}'..='\u{1afff}', '\u{1b123}'..='\u{1b131}', + '\u{1b133}'..='\u{1b14f}', '\u{1b153}'..='\u{1b154}', '\u{1b156}'..='\u{1b163}', + '\u{1b168}'..='\u{1b16f}', '\u{1b2fc}'..='\u{1bbff}', '\u{1bc6b}'..='\u{1bc6f}', + '\u{1bc7d}'..='\u{1bc7f}', '\u{1bc89}'..='\u{1bc8f}', '\u{1bc9a}'..='\u{1bc9b}', + '\u{1bca4}'..='\u{1cbff}', '\u{1ccfd}'..='\u{1ccff}', '\u{1ceb4}'..='\u{1ceb9}', + '\u{1ced1}'..='\u{1cedf}', '\u{1cef1}'..='\u{1ceff}', '\u{1cf2e}'..='\u{1cf2f}', + '\u{1cf47}'..='\u{1cf4f}', '\u{1cfc4}'..='\u{1cfff}', '\u{1d0f6}'..='\u{1d0ff}', + '\u{1d127}'..='\u{1d128}', '\u{1d1eb}'..='\u{1d1ff}', '\u{1d246}'..='\u{1d2bf}', + '\u{1d2d4}'..='\u{1d2df}', '\u{1d2f4}'..='\u{1d2ff}', '\u{1d357}'..='\u{1d35f}', + '\u{1d379}'..='\u{1d3ff}', '\u{1d455}'..='\u{1d455}', '\u{1d49d}'..='\u{1d49d}', + '\u{1d4a0}'..='\u{1d4a1}', '\u{1d4a3}'..='\u{1d4a4}', '\u{1d4a7}'..='\u{1d4a8}', + '\u{1d4ad}'..='\u{1d4ad}', '\u{1d4ba}'..='\u{1d4ba}', '\u{1d4bc}'..='\u{1d4bc}', + '\u{1d4c4}'..='\u{1d4c4}', '\u{1d506}'..='\u{1d506}', '\u{1d50b}'..='\u{1d50c}', + '\u{1d515}'..='\u{1d515}', '\u{1d51d}'..='\u{1d51d}', '\u{1d53a}'..='\u{1d53a}', + '\u{1d53f}'..='\u{1d53f}', '\u{1d545}'..='\u{1d545}', '\u{1d547}'..='\u{1d549}', + '\u{1d551}'..='\u{1d551}', '\u{1d6a6}'..='\u{1d6a7}', '\u{1d7cc}'..='\u{1d7cd}', + '\u{1da8c}'..='\u{1da9a}', '\u{1daa0}'..='\u{1daa0}', '\u{1dab0}'..='\u{1deff}', + '\u{1df1f}'..='\u{1df24}', '\u{1df2b}'..='\u{1dfff}', '\u{1e007}'..='\u{1e007}', + '\u{1e019}'..='\u{1e01a}', '\u{1e022}'..='\u{1e022}', '\u{1e025}'..='\u{1e025}', + '\u{1e02b}'..='\u{1e02f}', '\u{1e06e}'..='\u{1e08e}', '\u{1e090}'..='\u{1e0ff}', + '\u{1e12d}'..='\u{1e12f}', '\u{1e13e}'..='\u{1e13f}', '\u{1e14a}'..='\u{1e14d}', + '\u{1e150}'..='\u{1e28f}', '\u{1e2af}'..='\u{1e2bf}', '\u{1e2fa}'..='\u{1e2fe}', + '\u{1e300}'..='\u{1e4cf}', '\u{1e4fa}'..='\u{1e5cf}', '\u{1e5fb}'..='\u{1e5fe}', + '\u{1e600}'..='\u{1e6bf}', '\u{1e6df}'..='\u{1e6df}', '\u{1e6f6}'..='\u{1e6fd}', + '\u{1e700}'..='\u{1e7df}', '\u{1e7e7}'..='\u{1e7e7}', '\u{1e7ec}'..='\u{1e7ec}', + '\u{1e7ef}'..='\u{1e7ef}', '\u{1e7ff}'..='\u{1e7ff}', '\u{1e8c5}'..='\u{1e8c6}', + '\u{1e8d7}'..='\u{1e8ff}', '\u{1e94c}'..='\u{1e94f}', '\u{1e95a}'..='\u{1e95d}', + '\u{1e960}'..='\u{1ec70}', '\u{1ecb5}'..='\u{1ed00}', '\u{1ed3e}'..='\u{1edff}', + '\u{1ee04}'..='\u{1ee04}', '\u{1ee20}'..='\u{1ee20}', '\u{1ee23}'..='\u{1ee23}', + '\u{1ee25}'..='\u{1ee26}', '\u{1ee28}'..='\u{1ee28}', '\u{1ee33}'..='\u{1ee33}', + '\u{1ee38}'..='\u{1ee38}', '\u{1ee3a}'..='\u{1ee3a}', '\u{1ee3c}'..='\u{1ee41}', + '\u{1ee43}'..='\u{1ee46}', '\u{1ee48}'..='\u{1ee48}', '\u{1ee4a}'..='\u{1ee4a}', + '\u{1ee4c}'..='\u{1ee4c}', '\u{1ee50}'..='\u{1ee50}', '\u{1ee53}'..='\u{1ee53}', + '\u{1ee55}'..='\u{1ee56}', '\u{1ee58}'..='\u{1ee58}', '\u{1ee5a}'..='\u{1ee5a}', + '\u{1ee5c}'..='\u{1ee5c}', '\u{1ee5e}'..='\u{1ee5e}', '\u{1ee60}'..='\u{1ee60}', + '\u{1ee63}'..='\u{1ee63}', '\u{1ee65}'..='\u{1ee66}', '\u{1ee6b}'..='\u{1ee6b}', + '\u{1ee73}'..='\u{1ee73}', '\u{1ee78}'..='\u{1ee78}', '\u{1ee7d}'..='\u{1ee7d}', + '\u{1ee7f}'..='\u{1ee7f}', '\u{1ee8a}'..='\u{1ee8a}', '\u{1ee9c}'..='\u{1eea0}', + '\u{1eea4}'..='\u{1eea4}', '\u{1eeaa}'..='\u{1eeaa}', '\u{1eebc}'..='\u{1eeef}', + '\u{1eef2}'..='\u{1efff}', '\u{1f02c}'..='\u{1f02f}', '\u{1f094}'..='\u{1f09f}', + '\u{1f0af}'..='\u{1f0b0}', '\u{1f0c0}'..='\u{1f0c0}', '\u{1f0d0}'..='\u{1f0d0}', + '\u{1f0f6}'..='\u{1f0ff}', '\u{1f1ae}'..='\u{1f1e5}', '\u{1f203}'..='\u{1f20f}', + '\u{1f23c}'..='\u{1f23f}', '\u{1f249}'..='\u{1f24f}', '\u{1f252}'..='\u{1f25f}', + '\u{1f266}'..='\u{1f2ff}', '\u{1f6d9}'..='\u{1f6db}', '\u{1f6ed}'..='\u{1f6ef}', + '\u{1f6fd}'..='\u{1f6ff}', '\u{1f7da}'..='\u{1f7df}', '\u{1f7ec}'..='\u{1f7ef}', + '\u{1f7f1}'..='\u{1f7ff}', '\u{1f80c}'..='\u{1f80f}', '\u{1f848}'..='\u{1f84f}', + '\u{1f85a}'..='\u{1f85f}', '\u{1f888}'..='\u{1f88f}', '\u{1f8ae}'..='\u{1f8af}', + '\u{1f8bc}'..='\u{1f8bf}', '\u{1f8c2}'..='\u{1f8cf}', '\u{1f8d9}'..='\u{1f8ff}', + '\u{1fa58}'..='\u{1fa5f}', '\u{1fa6e}'..='\u{1fa6f}', '\u{1fa7d}'..='\u{1fa7f}', + '\u{1fa8b}'..='\u{1fa8d}', '\u{1fac7}'..='\u{1fac7}', '\u{1fac9}'..='\u{1facc}', + '\u{1fadd}'..='\u{1fade}', '\u{1faeb}'..='\u{1faee}', '\u{1faf9}'..='\u{1faff}', + '\u{1fb93}'..='\u{1fb93}', '\u{1fbfb}'..='\u{1ffff}', '\u{2a6e0}'..='\u{2a6ff}', + '\u{2b81e}'..='\u{2b81f}', '\u{2ceae}'..='\u{2ceaf}', '\u{2ebe1}'..='\u{2ebef}', + '\u{2ee5e}'..='\u{2f7ff}', '\u{2fa1e}'..='\u{2ffff}', '\u{3134b}'..='\u{3134f}', + '\u{3347a}'..='\u{3fffd}', +]; + #[rustfmt::skip] pub(super) static GRAPHEME_EXTEND: &[RangeInclusive; 383] = &[ '\u{300}'..='\u{36f}', '\u{483}'..='\u{489}', '\u{591}'..='\u{5bd}', '\u{5bf}'..='\u{5bf}', diff --git a/license-metadata.json b/license-metadata.json index e8e13fa8d859c..b58329b2ccc19 100644 --- a/license-metadata.json +++ b/license-metadata.json @@ -3,6 +3,28 @@ "children": [ { "children": [ + { + "children": [ + { + "license": { + "copyright": [ + "The Rust Project Developers (see https://thanks.rust-lang.org)" + ], + "spdx": "Apache-2.0 OR MIT" + }, + "name": "mod.rs", + "type": "file" + } + ], + "license": { + "copyright": [ + "1991-2024 Unicode, Inc" + ], + "spdx": "Unicode-3.0" + }, + "name": "library/core/src/unicode", + "type": "directory" + }, { "children": [ { @@ -178,16 +200,6 @@ "name": "library/backtrace", "type": "directory" }, - { - "license": { - "copyright": [ - "1991-2024 Unicode, Inc" - ], - "spdx": "Unicode-3.0" - }, - "name": "library/core/src/unicode/unicode_data.rs", - "type": "file" - }, { "children": [], "license": { diff --git a/src/tools/unicode-table-generator/src/main.rs b/src/tools/unicode-table-generator/src/main.rs index a55cd2f657a6d..ea7feedb78b9a 100644 --- a/src/tools/unicode-table-generator/src/main.rs +++ b/src/tools/unicode-table-generator/src/main.rs @@ -71,7 +71,7 @@ //! index of that offset is utilized as the answer to whether we're in the set //! or not. -use std::collections::BTreeMap; +use std::collections::{BTreeMap, BTreeSet}; use std::fmt::Write; use std::ops::Range; @@ -89,14 +89,18 @@ use fmt_helpers::CharEscape; use raw_emitter::{RawEmitter, emit_codepoints, emit_whitespace}; static PROPERTIES: &[&str] = &[ + // tidy-alphabetical-start "Alphabetic", - "Lowercase", - "Uppercase", "Case_Ignorable", + "Cf", + "Cn_Planes_0_3", "Grapheme_Extend", - "White_Space", - "N", + "Lowercase", "Lt", + "N", + "Uppercase", + "White_Space", + // tidy-alphabetical-end ]; struct UnicodeData { @@ -142,6 +146,9 @@ fn load_data() -> UnicodeData { } } + // Unassigned characters are not listed in `UnicodeData.txt`, + // so get a list of all the assigned ones + let mut assigned_chars = BTreeSet::new(); let [mut to_lower, mut to_upper, mut to_title, mut to_casefold] = [const { BTreeMap::new() }; 4]; for row in ucd_parse::UnicodeDataExpander::new( @@ -152,6 +159,11 @@ fn load_data() -> UnicodeData { } else { row.general_category.as_str() }; + + if !matches!(general_category, "Cs" | "Cn") { + assigned_chars.insert(row.codepoint.value()); + } + if let Some(name) = PROPERTIES.iter().find(|prop| **prop == general_category) { properties .entry(*name) @@ -176,6 +188,25 @@ fn load_data() -> UnicodeData { } } + // Find all unassigned chars in the first 4 planes + for c in '\0'..='\u{3FFFD}' { + let cp = Codepoint::from_u32(c.into()).unwrap(); + if !assigned_chars.contains(&cp.value()) { + properties.entry("Cn_Planes_0_3").or_insert_with(Vec::new).push(Codepoints::Single(cp)); + } + } + + // For now, we hardcode the assigned/unassigned status of characters + // U+3FFFE and above. The assertion below must be kept in sync + // with the `is_unassigned()` method in `library/core/char/methods.rs`. + for c in '\u{3FFFE}'..=char::MAX { + assert_eq!( + assigned_chars.contains(&u32::from(c)), + matches!(c, '\u{E0001}' | '\u{E0020}'..='\u{E007F}' | '\u{E0100}'..='\u{E01EF}' | '\u{F0000}'..='\u{FFFFD}' | '\u{100000}'..='\u{10FFFD}'), + "{c:?}", + ); + } + for row in ucd_parse::parse::<_, ucd_parse::SpecialCaseMapping>(&UNICODE_DIRECTORY).unwrap() { if !row.conditions.is_empty() { // Skip conditional case mappings @@ -324,7 +355,7 @@ fn main() { modules.push((property.to_lowercase().to_string(), emitter.file)); table_file.push_str(&format!( - "// {:16}: {:5} bytes, {:6} codepoints in {:3} ranges (U+{:06X} - U+{:06X}) using {}\n", + "// {:28}: {:5} bytes, {:6} codepoints in {:3} ranges (U+{:06X} - U+{:06X}) using {}\n", property, emitter.bytes_used, datapoints, @@ -339,10 +370,10 @@ fn main() { for (name, (desc, size)) in ["to_lower", "to_upper", "to_title", "to_casefold"].iter().zip(sizes) { - table_file.push_str(&format!("// {:16}: {:5} bytes, {desc}\n", name, size,)); + table_file.push_str(&format!("// {:28}: {:5} bytes, {desc}\n", name, size,)); total_bytes += size; } - table_file.push_str(&format!("// {:16}: {:5} bytes\n", "Total", total_bytes)); + table_file.push_str(&format!("// {:28}: {:5} bytes\n", "Total", total_bytes)); // Include the range search function table_file.push('\n'); From 4db9ff5d1730c07290e45fce3595360f83badbca Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Sun, 26 Apr 2026 18:38:40 -0400 Subject: [PATCH 30/59] Consider all `Default_Ignorable_Code_Point`s unprintable These characters may be hidden/invisible otherwise. --- library/core/src/char/methods.rs | 32 +++++++++++++++ library/core/src/unicode/mod.rs | 1 + library/core/src/unicode/unicode_data.rs | 41 ++++++++++++++++++- library/coretests/tests/unicode.rs | 9 ++++ library/coretests/tests/unicode/test_data.rs | 10 +++++ src/tools/unicode-table-generator/src/main.rs | 1 + 6 files changed, 93 insertions(+), 1 deletion(-) diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index b4569610babe5..3dc167b40ca27 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -493,6 +493,7 @@ impl char { || self.is_private_use() || self.is_whitespace() || args.escape_grapheme_extender && self.is_grapheme_extender() + || self.is_default_ignorable() || self.is_format_control() || self.is_unassigned() => { @@ -1226,6 +1227,37 @@ impl char { } } + /// Returns `true` if this `char` has the `Default_Ignorable_Code_Point` property. + /// These characters [should be displayed as invisible in fallback rendering](https://www.unicode.org/faq/unsup_char#3). + /// + /// `Default_Ignorable_Code_Point` is [described] in Chapter 5 (Implementation Guidelines) of the Unicode Standard, + /// and [specified] in the Unicode Character Database [`DerivedCoreProperties.txt`]. + /// + /// [described]: https://www.unicode.org/versions/latest/core-spec/chapter-5/#G40120 + /// [specified]: https://www.unicode.org/reports/tr44/#Default_Ignorable_Code_Point + /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt + /// + /// # Examples + /// + /// Basic usage: + /// + /// ```ignore(private) + /// assert!('\u{AD}'.is_default_ignorable()); // SOFT HYPHEN + /// assert!('\u{115F}'.is_default_ignorable()); // HANGUL CHOSEONG FILLER + /// assert!('\u{200B}'.is_default_ignorable()); // ZERO WIDTH SPACE + /// assert!('\u{E0041}'.is_default_ignorable()); // TAG LATIN CAPITAL LETTER A + /// assert!(!'۝'.is_default_ignorable()); // ARABIC END OF AYAH + /// assert!(!'𓐲'.is_default_ignorable()); // EGYPTIAN HIEROGLYPH INSERT AT TOP START + /// assert!(!' '.is_default_ignorable()); + /// assert!(!'\n'.is_default_ignorable()); + /// assert!(!'\0'.is_default_ignorable()); + /// assert!(!'q'.is_default_ignorable()); + #[must_use] + #[inline] + fn is_default_ignorable(self) -> bool { + self > '\u{AC}' && unicode::Default_Ignorable_Code_Point(self) + } + /// Returns `true` if this `char` has the `Grapheme_Extend` property. /// /// `Grapheme_Extend` is [described] in Chapter 3 (Conformance) of the Unicode Standard, diff --git a/library/core/src/unicode/mod.rs b/library/core/src/unicode/mod.rs index 61acb08487057..1648795facd40 100644 --- a/library/core/src/unicode/mod.rs +++ b/library/core/src/unicode/mod.rs @@ -11,6 +11,7 @@ pub(crate) use unicode_data::alphabetic::lookup as Alphabetic; pub(crate) use unicode_data::case_ignorable::lookup as Case_Ignorable; pub(crate) use unicode_data::cf::lookup as Cf; pub(crate) use unicode_data::cn_planes_0_3::lookup as Cn_planes_0_3; +pub(crate) use unicode_data::default_ignorable_code_point::lookup as Default_Ignorable_Code_Point; pub(crate) use unicode_data::grapheme_extend::lookup as Grapheme_Extend; pub(crate) use unicode_data::lowercase::lookup as Lowercase; pub(crate) use unicode_data::lt::lookup as Lt; diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs index 2c768e0622762..ca3a276b89d90 100644 --- a/library/core/src/unicode/unicode_data.rs +++ b/library/core/src/unicode/unicode_data.rs @@ -3,6 +3,7 @@ // Case_Ignorable : 1063 bytes, 2789 codepoints in 459 ranges (U+0000A8 - U+0E01F0) using skiplist // Cf : 87 bytes, 170 codepoints in 21 ranges (U+0000AD - U+0E0080) using skiplist // Cn_Planes_0_3 : 1677 bytes, 94165 codepoints in 730 ranges (U+000378 - U+03FFFE) using skiplist +// Default_Ignorable_Code_Point: 83 bytes, 4174 codepoints in 17 ranges (U+0000AD - U+0E1000) using skiplist // Grapheme_Extend : 899 bytes, 2232 codepoints in 383 ranges (U+000300 - U+0E01F0) using skiplist // Lowercase : 943 bytes, 2569 codepoints in 676 ranges (U+0000AA - U+01E944) using bitset // Lt : 33 bytes, 31 codepoints in 10 ranges (U+0001C5 - U+001FFD) using skiplist @@ -13,7 +14,7 @@ // to_upper : 1998 bytes, 1554 codepoints in 299 ranges (U+0000B5 - U+01E943) using 2-level LUT // to_title : 340 bytes, 135 codepoints in 49 ranges (U+0000DF - U+00FB17) using 2-level LUT // to_casefold : 32 bytes, 174 codepoints in 5 ranges (U+000131 - U+00ABBF) using 2-level LUT -// Total : 11425 bytes +// Total : 11508 bytes #[inline(always)] const fn bitset_search< @@ -489,6 +490,44 @@ pub mod cn_planes_0_3 { } } +#[rustfmt::skip] +pub mod default_ignorable_code_point { + use super::ShortOffsetRunHeader; + + static SHORT_OFFSET_RUNS: [ShortOffsetRunHeader; 12] = [ + ShortOffsetRunHeader::new(0, 847), ShortOffsetRunHeader::new(3, 1564), + ShortOffsetRunHeader::new(5, 4447), ShortOffsetRunHeader::new(7, 6068), + ShortOffsetRunHeader::new(9, 8203), ShortOffsetRunHeader::new(13, 12644), + ShortOffsetRunHeader::new(19, 65024), ShortOffsetRunHeader::new(21, 113824), + ShortOffsetRunHeader::new(29, 119155), ShortOffsetRunHeader::new(31, 917504), + ShortOffsetRunHeader::new(33, 921600), ShortOffsetRunHeader::new(34, 2035712), + ]; + static OFFSETS: [u8; 35] = [ + 173, 1, 0, 1, 0, 1, 0, 2, 0, 2, 85, 5, 0, 5, 26, 5, 49, 16, 0, 1, 0, 16, 239, 1, 160, 1, + 79, 9, 0, 4, 0, 8, 0, 0, 0, + ]; + #[inline] + pub fn lookup(c: char) -> bool { + debug_assert!(!c.is_ascii()); + (c as u32) >= 0xad && lookup_slow(c) + } + + #[inline(never)] + fn lookup_slow(c: char) -> bool { + const { + assert!(SHORT_OFFSET_RUNS.last().unwrap().0 > char::MAX as u32); + let mut i = 0; + while i < SHORT_OFFSET_RUNS.len() { + assert!(SHORT_OFFSET_RUNS[i].start_index() < OFFSETS.len()); + i += 1; + } + } + // SAFETY: We just ensured the last element of `SHORT_OFFSET_RUNS` is greater than `std::char::MAX` + // and the start indices of all elements in `SHORT_OFFSET_RUNS` are smaller than `OFFSETS.len()`. + unsafe { super::skip_search(c, &SHORT_OFFSET_RUNS, &OFFSETS) } + } +} + #[rustfmt::skip] pub mod grapheme_extend { use super::ShortOffsetRunHeader; diff --git a/library/coretests/tests/unicode.rs b/library/coretests/tests/unicode.rs index 1199049ab26b0..548f38cb53932 100644 --- a/library/coretests/tests/unicode.rs +++ b/library/coretests/tests/unicode.rs @@ -71,6 +71,15 @@ fn cn_planes_0_3() { test_boolean_property(test_data::CN_PLANES_0_3, unicode_data::cn_planes_0_3::lookup); } +#[test] +#[cfg_attr(miri, ignore)] // Miri is too slow +fn default_ignorable_code_point() { + test_boolean_property( + test_data::DEFAULT_IGNORABLE_CODE_POINT, + unicode_data::default_ignorable_code_point::lookup, + ); +} + #[test] #[cfg_attr(miri, ignore)] // Miri is too slow fn grapheme_extend() { diff --git a/library/coretests/tests/unicode/test_data.rs b/library/coretests/tests/unicode/test_data.rs index 4c0efca66c020..088eb08043fa4 100644 --- a/library/coretests/tests/unicode/test_data.rs +++ b/library/coretests/tests/unicode/test_data.rs @@ -638,6 +638,16 @@ pub(super) static CN_PLANES_0_3: &[RangeInclusive; 730] = &[ '\u{3347a}'..='\u{3fffd}', ]; +#[rustfmt::skip] +pub(super) static DEFAULT_IGNORABLE_CODE_POINT: &[RangeInclusive; 17] = &[ + '\u{ad}'..='\u{ad}', '\u{34f}'..='\u{34f}', '\u{61c}'..='\u{61c}', '\u{115f}'..='\u{1160}', + '\u{17b4}'..='\u{17b5}', '\u{180b}'..='\u{180f}', '\u{200b}'..='\u{200f}', + '\u{202a}'..='\u{202e}', '\u{2060}'..='\u{206f}', '\u{3164}'..='\u{3164}', + '\u{fe00}'..='\u{fe0f}', '\u{feff}'..='\u{feff}', '\u{ffa0}'..='\u{ffa0}', + '\u{fff0}'..='\u{fff8}', '\u{1bca0}'..='\u{1bca3}', '\u{1d173}'..='\u{1d17a}', + '\u{e0000}'..='\u{e0fff}', +]; + #[rustfmt::skip] pub(super) static GRAPHEME_EXTEND: &[RangeInclusive; 383] = &[ '\u{300}'..='\u{36f}', '\u{483}'..='\u{489}', '\u{591}'..='\u{5bd}', '\u{5bf}'..='\u{5bf}', diff --git a/src/tools/unicode-table-generator/src/main.rs b/src/tools/unicode-table-generator/src/main.rs index ea7feedb78b9a..8f7fa4cc56606 100644 --- a/src/tools/unicode-table-generator/src/main.rs +++ b/src/tools/unicode-table-generator/src/main.rs @@ -94,6 +94,7 @@ static PROPERTIES: &[&str] = &[ "Case_Ignorable", "Cf", "Cn_Planes_0_3", + "Default_Ignorable_Code_Point", "Grapheme_Extend", "Lowercase", "Lt", From 1e125ceba9a27466b10ed5584b8b0d0a3abc2b19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=9D=E5=80=89=E6=B0=B4=E5=B8=8C?= Date: Fri, 15 May 2026 02:38:50 +0800 Subject: [PATCH 31/59] Support defaults for static EIIs --- .../rustc_builtin_macros/src/diagnostics.rs | 8 -- compiler/rustc_builtin_macros/src/eii.rs | 83 +++++++++++-------- .../eii/static/auxiliary/decl_with_default.rs | 5 ++ .../static/auxiliary/impl_default_override.rs | 8 ++ tests/ui/eii/static/default.rs | 15 ++++ tests/ui/eii/static/default.run.stdout | 1 + tests/ui/eii/static/default_cross_crate.rs | 13 +++ .../eii/static/default_cross_crate.run.stdout | 1 + .../static/default_cross_crate_explicit.rs | 15 ++++ .../default_cross_crate_explicit.run.stdout | 1 + tests/ui/eii/static/default_explicit.rs | 19 +++++ .../ui/eii/static/default_explicit.run.stdout | 1 + 12 files changed, 127 insertions(+), 43 deletions(-) create mode 100644 tests/ui/eii/static/auxiliary/decl_with_default.rs create mode 100644 tests/ui/eii/static/auxiliary/impl_default_override.rs create mode 100644 tests/ui/eii/static/default.rs create mode 100644 tests/ui/eii/static/default.run.stdout create mode 100644 tests/ui/eii/static/default_cross_crate.rs create mode 100644 tests/ui/eii/static/default_cross_crate.run.stdout create mode 100644 tests/ui/eii/static/default_cross_crate_explicit.rs create mode 100644 tests/ui/eii/static/default_cross_crate_explicit.run.stdout create mode 100644 tests/ui/eii/static/default_explicit.rs create mode 100644 tests/ui/eii/static/default_explicit.run.stdout diff --git a/compiler/rustc_builtin_macros/src/diagnostics.rs b/compiler/rustc_builtin_macros/src/diagnostics.rs index 929c88402b1aa..afd9aea3efe0c 100644 --- a/compiler/rustc_builtin_macros/src/diagnostics.rs +++ b/compiler/rustc_builtin_macros/src/diagnostics.rs @@ -1134,14 +1134,6 @@ pub(crate) struct EiiStaticMultipleImplementations { pub span: Span, } -#[derive(Diagnostic)] -#[diag("`#[{$name}]` cannot be used on statics with a value")] -pub(crate) struct EiiStaticDefault { - #[primary_span] - pub span: Span, - pub name: String, -} - #[derive(Diagnostic)] #[diag("`#[{$name}]` requires the name as an explicit argument when used on a static")] pub(crate) struct EiiStaticArgumentRequired { diff --git a/compiler/rustc_builtin_macros/src/eii.rs b/compiler/rustc_builtin_macros/src/eii.rs index 9bb34cdd642a0..b482867582227 100644 --- a/compiler/rustc_builtin_macros/src/eii.rs +++ b/compiler/rustc_builtin_macros/src/eii.rs @@ -13,7 +13,7 @@ use crate::diagnostics::{ EiiAttributeNotSupported, EiiExternTargetExpectedList, EiiExternTargetExpectedMacro, EiiExternTargetExpectedUnsafe, EiiMacroExpectedMaxOneArgument, EiiOnlyOnce, EiiSharedMacroInStatementPosition, EiiSharedMacroTarget, EiiStaticArgumentRequired, - EiiStaticDefault, EiiStaticMultipleImplementations, EiiStaticMutable, + EiiStaticMultipleImplementations, EiiStaticMutable, }; /// ```rust @@ -86,14 +86,6 @@ fn eii_( let (item_span, foreign_item_name) = match kind { ItemKind::Fn(func) => (func.sig.span, func.ident), ItemKind::Static(stat) => { - // Statics with a default are not supported yet - if let Some(stat_body) = &stat.expr { - ecx.dcx().emit_err(EiiStaticDefault { - span: stat_body.span, - name: path_to_string(&meta_item.path), - }); - return vec![]; - } // Statics must have an explicit name for the eii if meta_item.is_word() { ecx.dcx().emit_err(EiiStaticArgumentRequired { @@ -139,19 +131,17 @@ fn eii_( let mut module_items = Vec::new(); - if let ItemKind::Fn(func) = kind - && func.body.is_some() - { - module_items.push(generate_default_func_impl( - ecx, - &func, - impl_unsafe, - macro_name, - eii_attr_span, - item_span, - foreign_item_name, - default_func_attrs, - )) + if let Some(default_impl) = generate_default_impl( + ecx, + kind, + impl_unsafe, + macro_name, + eii_attr_span, + item_span, + foreign_item_name, + default_func_attrs, + ) { + module_items.push(default_impl); } module_items.push(generate_foreign_item( @@ -266,18 +256,31 @@ fn filter_attrs_for_multiple_eii_attr( .collect() } -fn generate_default_func_impl( +fn generate_default_impl( ecx: &mut ExtCtxt<'_>, - func: &ast::Fn, + item_kind: &ItemKind, impl_unsafe: bool, macro_name: Ident, eii_attr_span: Span, item_span: Span, foreign_item_name: Ident, attrs: ThinVec, -) -> Box { - let mut default_func = func.clone(); - default_func.eii_impls.push(EiiImpl { +) -> Option> { + match item_kind { + ItemKind::Fn(func) => { + if func.body.is_none() { + return None; + } + } + ItemKind::Static(stat) => { + if stat.expr.is_none() { + return None; + } + } + _ => unreachable!("Target was checked earlier"), + }; + + let eii_impl = EiiImpl { node_id: DUMMY_NODE_ID, inner_span: macro_name.span, eii_macro_path: ast::Path::from_ident(macro_name), @@ -297,7 +300,18 @@ fn generate_default_func_impl( ), impl_unsafe, }), - }); + }; + + let mut item_kind = item_kind.clone(); + match &mut item_kind { + ItemKind::Fn(func) => { + func.eii_impls.push(eii_impl); + } + ItemKind::Static(stat) => { + stat.eii_impls.push(eii_impl); + } + _ => unreachable!("Target was checked earlier"), + }; let anon_mod = |span: Span, stmts: ThinVec| { let unit = ecx.ty(item_span, ast::TyKind::Tup(ThinVec::new())); @@ -311,15 +325,12 @@ fn generate_default_func_impl( }; // const _: () = { - // + // // } - anon_mod( + Some(anon_mod( item_span, - thin_vec![ecx.stmt_item( - item_span, - ecx.item(item_span, attrs, ItemKind::Fn(Box::new(default_func))) - ),], - ) + thin_vec![ecx.stmt_item(item_span, ecx.item(item_span, attrs, item_kind))], + )) } /// Generates a foreign item, like @@ -405,6 +416,8 @@ fn generate_foreign_static(mut stat: Box) -> ast::ForeignItemKi stat.safety = ast::Safety::Safe(stat.ident.span); } + stat.expr = None; + ast::ForeignItemKind::Static(stat) } diff --git a/tests/ui/eii/static/auxiliary/decl_with_default.rs b/tests/ui/eii/static/auxiliary/decl_with_default.rs new file mode 100644 index 0000000000000..ba87b35deb457 --- /dev/null +++ b/tests/ui/eii/static/auxiliary/decl_with_default.rs @@ -0,0 +1,5 @@ +#![crate_type = "rlib"] +#![feature(extern_item_impls)] + +#[eii(eii1)] +pub static DECL1: u64 = 5; diff --git a/tests/ui/eii/static/auxiliary/impl_default_override.rs b/tests/ui/eii/static/auxiliary/impl_default_override.rs new file mode 100644 index 0000000000000..d70a137fbc459 --- /dev/null +++ b/tests/ui/eii/static/auxiliary/impl_default_override.rs @@ -0,0 +1,8 @@ +//@ aux-build: decl_with_default.rs +#![crate_type = "rlib"] +#![feature(extern_item_impls)] + +extern crate decl_with_default as decl; + +#[decl::eii1] +pub static EII1_IMPL: u64 = 10; diff --git a/tests/ui/eii/static/default.rs b/tests/ui/eii/static/default.rs new file mode 100644 index 0000000000000..02307432e2f81 --- /dev/null +++ b/tests/ui/eii/static/default.rs @@ -0,0 +1,15 @@ +//@ run-pass +//@ check-run-results +//@ ignore-backends: gcc +// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 +//@ ignore-windows +// Tests static EIIs with default implementations. + +#![feature(extern_item_impls)] + +#[eii(eii1)] +pub static DECL1: u64 = 5; + +fn main() { + println!("{DECL1}"); +} diff --git a/tests/ui/eii/static/default.run.stdout b/tests/ui/eii/static/default.run.stdout new file mode 100644 index 0000000000000..7ed6ff82de6bc --- /dev/null +++ b/tests/ui/eii/static/default.run.stdout @@ -0,0 +1 @@ +5 diff --git a/tests/ui/eii/static/default_cross_crate.rs b/tests/ui/eii/static/default_cross_crate.rs new file mode 100644 index 0000000000000..4d6df4b7ee717 --- /dev/null +++ b/tests/ui/eii/static/default_cross_crate.rs @@ -0,0 +1,13 @@ +//@ aux-build: decl_with_default.rs +//@ run-pass +//@ check-run-results +//@ ignore-backends: gcc +// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 +//@ ignore-windows +// Tests that a static EII default can be used from another crate. + +extern crate decl_with_default; + +fn main() { + println!("{}", decl_with_default::DECL1); +} diff --git a/tests/ui/eii/static/default_cross_crate.run.stdout b/tests/ui/eii/static/default_cross_crate.run.stdout new file mode 100644 index 0000000000000..7ed6ff82de6bc --- /dev/null +++ b/tests/ui/eii/static/default_cross_crate.run.stdout @@ -0,0 +1 @@ +5 diff --git a/tests/ui/eii/static/default_cross_crate_explicit.rs b/tests/ui/eii/static/default_cross_crate_explicit.rs new file mode 100644 index 0000000000000..c3139f45d19c5 --- /dev/null +++ b/tests/ui/eii/static/default_cross_crate_explicit.rs @@ -0,0 +1,15 @@ +//@ aux-build: decl_with_default.rs +//@ aux-build: impl_default_override.rs +//@ run-pass +//@ check-run-results +//@ ignore-backends: gcc +// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 +//@ ignore-windows +// Tests that an explicit static EII implementation overrides a cross-crate default. + +extern crate decl_with_default; +extern crate impl_default_override; + +fn main() { + println!("{}", decl_with_default::DECL1); +} diff --git a/tests/ui/eii/static/default_cross_crate_explicit.run.stdout b/tests/ui/eii/static/default_cross_crate_explicit.run.stdout new file mode 100644 index 0000000000000..f599e28b8ab0d --- /dev/null +++ b/tests/ui/eii/static/default_cross_crate_explicit.run.stdout @@ -0,0 +1 @@ +10 diff --git a/tests/ui/eii/static/default_explicit.rs b/tests/ui/eii/static/default_explicit.rs new file mode 100644 index 0000000000000..b18da35c3debe --- /dev/null +++ b/tests/ui/eii/static/default_explicit.rs @@ -0,0 +1,19 @@ +//@ run-pass +//@ check-run-results +//@ ignore-backends: gcc +// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 +//@ ignore-windows +// Tests that an explicit static EII implementation overrides a local default. + +#![feature(extern_item_impls)] +#![allow(dead_code)] + +#[eii(eii1)] +pub static DECL1: u64 = 5; + +#[eii1] +pub static EII1_IMPL: u64 = 10; + +fn main() { + println!("{DECL1}"); +} diff --git a/tests/ui/eii/static/default_explicit.run.stdout b/tests/ui/eii/static/default_explicit.run.stdout new file mode 100644 index 0000000000000..f599e28b8ab0d --- /dev/null +++ b/tests/ui/eii/static/default_explicit.run.stdout @@ -0,0 +1 @@ +10 From 3669c24e497d1adffe3d27a6a1530ebbfbb1fd77 Mon Sep 17 00:00:00 2001 From: Dnreikronos Date: Tue, 9 Jun 2026 11:48:37 -0300 Subject: [PATCH 32/59] Allow escaping self types in ExistentialTraitRef::with_self_ty WF-checking can reach ExistentialTraitRef::with_self_ty with a dyn principal that still carries escaping bound vars, e.g. a dyn nested in a for<'a> bound, which tripped the debug assertion forbidding escaping self types and ICEd when compiling itertools. Building such a trait ref is fine: escaping bound vars are caught where it is actually used. Remove the assertion rather than working around it, which lets the WF visitor pass the type through unchanged and drops the placeholder-self-type detour. --- compiler/rustc_trait_selection/src/traits/wf.rs | 17 +---------------- compiler/rustc_type_ir/src/predicate.rs | 3 --- .../wf/wf-dyn-in-hrtb-bound-const-mismatch.rs | 10 +++++----- .../ui/wf/wf-dyn-in-hrtb-bound-issue-157122.rs | 14 +++++++------- 4 files changed, 13 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index e226c553e6f98..a2143a7462a84 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -974,22 +974,7 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { // go through an anon const still have their types checked. // // See also: https://rustc-dev-guide.rust-lang.org/const-generics.html - // - // We only use this trait ref to read off its `ConstArgHasType` clauses, - // which constrain the trait's own const arguments and never mention the - // `Self` type. The `with_self_ty` assertion forbids an escaping self type - // (those vars would be captured by the trait-ref binder), and `t` can carry - // escaping bound vars here because WF-checking walks through higher-ranked - // binders without instantiating them (e.g. a `dyn Trait` nested in a - // `for<'a>` bound). Since the self type is irrelevant to the clauses we - // keep, fall back to the dummy self type in that case rather than skipping - // the check entirely. - let self_ty = if t.has_escaping_bound_vars() { - tcx.types.trait_object_dummy_self - } else { - t - }; - let args = principal.skip_binder().with_self_ty(tcx, self_ty).args; + let args = principal.skip_binder().with_self_ty(self.tcx(), t).args; let obligations = self.nominal_obligations(principal_def_id, args).into_iter().filter(|o| { let kind = o.predicate.kind().skip_binder(); diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index 30264943459f7..5142ae8ef4b67 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -443,9 +443,6 @@ impl ExistentialTraitRef { /// Therefore, you must specify *some* self type to perform the conversion. /// A common choice is the trait object type itself or some kind of dummy type. pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> TraitRef { - // otherwise the escaping vars would be captured by the binder - debug_assert!(!self_ty.has_escaping_bound_vars()); - TraitRef::new(interner, self.def_id, [self_ty.into()].into_iter().chain(self.args.iter())) } } diff --git a/tests/ui/wf/wf-dyn-in-hrtb-bound-const-mismatch.rs b/tests/ui/wf/wf-dyn-in-hrtb-bound-const-mismatch.rs index db3e36224367d..a0808f820aa38 100644 --- a/tests/ui/wf/wf-dyn-in-hrtb-bound-const-mismatch.rs +++ b/tests/ui/wf/wf-dyn-in-hrtb-bound-const-mismatch.rs @@ -1,11 +1,11 @@ // Companion to #157122 / `wf-dyn-in-hrtb-bound-issue-157122.rs`. // -// That test fixes an ICE in `WfPredicates::visit_ty` where a `dyn Trait` nested +// That test covers an ICE in `WfPredicates::visit_ty` where a `dyn Trait` nested // inside a `for<'a>` binder reached `ExistentialTraitRef::with_self_ty` with an -// escaping self type. The fix substitutes a placeholder self type for that case -// instead of skipping the block. Skipping would have been a silent regression: -// the block emits the `ConstArgHasType` obligation that type-checks a `dyn`'s -// const argument, so dropping it makes an ill-typed const argument compile. +// escaping self type. The fix removes the offending `debug_assert!` rather than +// skipping the block. Skipping would have been a silent regression: the block +// emits the `ConstArgHasType` obligation that type-checks a `dyn`'s const +// argument, so dropping it makes an ill-typed const argument compile. // // Here `B` has type `bool` but `HasConst` expects `const N: usize`, and the // `dyn HasConst<'a, B>` carries the escaping late-bound `'a`. This must still be diff --git a/tests/ui/wf/wf-dyn-in-hrtb-bound-issue-157122.rs b/tests/ui/wf/wf-dyn-in-hrtb-bound-issue-157122.rs index 8fca3828efeb1..6254a2cb1100b 100644 --- a/tests/ui/wf/wf-dyn-in-hrtb-bound-issue-157122.rs +++ b/tests/ui/wf/wf-dyn-in-hrtb-bound-issue-157122.rs @@ -6,13 +6,13 @@ // without instantiating them, so a `dyn Trait` nested inside a `for<'a>` binder // reaches the `ty::Dynamic` arm of `WfPredicates::visit_ty` while still carrying // escaping bound vars. Building the principal trait ref there via -// `ExistentialTraitRef::with_self_ty` fed that escaping self type straight into -// `debug_assert!(!self_ty.has_escaping_bound_vars())`, causing an ICE. We now -// substitute a placeholder self type for the escaping case (the self type is -// irrelevant to the `ConstArgHasType` clauses this code reads off), so the -// assertion holds and the const-argument check is still performed -- see -// `wf-dyn-in-hrtb-bound-const-mismatch.rs` for the latter. Distilled from -// `itertools`'s `FormatWith` `Display` impl. +// `ExistentialTraitRef::with_self_ty` passed that escaping self type to a +// `debug_assert!(!self_ty.has_escaping_bound_vars())`, which ICEs once the +// assertion is enabled. Creating a trait ref with an escaping self type is fine +// -- escaping bound vars are caught where they are actually used -- so the +// assertion was removed rather than worked around. The `ConstArgHasType` check +// this arm reads off still runs; see `wf-dyn-in-hrtb-bound-const-mismatch.rs`. +// Distilled from `itertools`'s `FormatWith` `Display` impl. use std::fmt; From e069f47a7a27bcf856bf944190623281ff7b575d Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 8 Jun 2026 16:59:40 +0200 Subject: [PATCH 33/59] Add a regression test --- .../reflection/reflection_methods_in_runtime_code.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tests/ui/reflection/reflection_methods_in_runtime_code.rs diff --git a/tests/ui/reflection/reflection_methods_in_runtime_code.rs b/tests/ui/reflection/reflection_methods_in_runtime_code.rs new file mode 100644 index 0000000000000..d2795d7c80622 --- /dev/null +++ b/tests/ui/reflection/reflection_methods_in_runtime_code.rs @@ -0,0 +1,10 @@ +//@run-fail + +#![feature(type_info)] + +trait Trait {} + +fn main() { + // Test the (lack of) usability of comptime fns in runtime code. + std::any::TypeId::of::<[u8; usize::MAX]>().trait_info_of::(); +} From 947a5b6af5b92cd4beb4dae969a19532611dbc56 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 8 Jun 2026 12:21:58 +0200 Subject: [PATCH 34/59] Mark `trait_info_of` as comptime and adjust the compiler to handle it --- compiler/rustc_metadata/src/rmeta/encoder.rs | 3 +++ compiler/rustc_middle/src/ty/mod.rs | 8 ++++++++ .../rustc_mir_transform/src/cross_crate_inline.rs | 8 +++++++- .../rustc_mir_transform/src/deduce_param_attrs.rs | 7 +++++++ compiler/rustc_mir_transform/src/lib.rs | 13 ++++++++++++- library/core/src/any.rs | 8 ++++---- library/core/src/intrinsics/mod.rs | 3 ++- .../reflection_methods_in_runtime_code.rs | 3 +-- .../reflection_methods_in_runtime_code.stderr | 8 ++++++++ 9 files changed, 52 insertions(+), 9 deletions(-) create mode 100644 tests/ui/reflection/reflection_methods_in_runtime_code.stderr diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 1483de572c341..b02df1a72fd65 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1122,6 +1122,9 @@ fn should_encode_mir( && reachable_set.contains(&def_id) && (tcx.generics_of(def_id).requires_monomorphization(tcx) || tcx.cross_crate_inlinable(def_id))); + // Comptime fns do not have optimized MIR at all. + let opt = + opt && !matches!(tcx.constness(def_id), hir::Constness::Const { always: true }); // The function has a `const` modifier or is in a `const trait`. let is_const_fn = tcx.is_const_fn(def_id.to_def_id()); (is_const_fn, opt) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index ac82cf1981032..ab2cca01134e2 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1789,6 +1789,14 @@ impl<'tcx> TyCtxt<'tcx> { | DefKind::Ctor(..) | DefKind::AnonConst | DefKind::InlineConst => self.mir_for_ctfe(def), + DefKind::Fn | DefKind::AssocFn + if matches!( + self.constness(def), + hir::Constness::Const { always: true } + ) => + { + self.mir_for_ctfe(def) + } // If the caller wants `mir_for_ctfe` of a function they should not be using // `instance_mir`, so we'll assume const fn also wants the optimized version. _ => self.optimized_mir(def), diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs index 5d3827e70ffb1..13b3304fda8f2 100644 --- a/compiler/rustc_mir_transform/src/cross_crate_inline.rs +++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs @@ -1,7 +1,7 @@ use rustc_hir::attrs::InlineAttr; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; -use rustc_hir::find_attr; +use rustc_hir::{self as hir, find_attr}; use rustc_middle::bug; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; @@ -43,6 +43,12 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { return true; } + if let hir::Constness::Const { always: true } = tcx.constness(def_id) { + // Comptime functions only exist during const eval and can never be passed + // to codegen. The const eval MIR pipeline also doesn't inline anything at all. + return false; + } + // Obey source annotations first; this is important because it means we can use // #[inline(never)] to force code generation. match codegen_fn_attrs.inline { diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs index cd6395eb2e8e8..bcd43bc40d8bc 100644 --- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs +++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs @@ -9,6 +9,7 @@ //! after `optimized_mir`! We check for things that are *not* guaranteed to be preserved by MIR //! transforms, such as which local variables happen to be mutated. +use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_index::IndexVec; use rustc_middle::middle::deduced_param_attrs::{DeducedParamAttrs, UsageSummary}; @@ -205,6 +206,12 @@ pub(super) fn deduced_param_attrs<'tcx>( return &[]; } + if let hir::Constness::Const { always: true } = tcx.constness(def_id) { + // Comptime functions only exist during const eval and can never be passed + // to codegen. + return &[]; + } + // Grab the optimized MIR. Analyze it to determine which arguments have been mutated. let body: &Body<'tcx> = tcx.optimized_mir(def_id); // Arguments spread at ABI level are currently unsupported. diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index bbf190ce1a3e0..9d6803bc53e5a 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -511,7 +511,18 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> { }; let mut body = remap_mir_for_const_eval_select(tcx, body, hir::Constness::Const { always }); - pm::run_passes(tcx, &mut body, &[&ctfe_limit::CtfeLimit], None, pm::Optimizations::Allowed); + // FIXME(reflection): probably need to look at this for comptime closures + let passes: &[&dyn MirPass<'_>] = if matches!(tcx.def_kind(def), DefKind::Fn | DefKind::AssocFn) + && matches!(tcx.constness(def), hir::Constness::Const { always: true }) + { + // Need to generate mentioned items, as all functions are expected to have them, but for const + // fns we just look at the optimized MIR, which generates it. For comptime fns, there is no + // optimized MIR. + &[&ctfe_limit::CtfeLimit, &mentioned_items::MentionedItems] + } else { + &[&ctfe_limit::CtfeLimit] + }; + pm::run_passes(tcx, &mut body, passes, None, pm::Optimizations::Allowed); body } diff --git a/library/core/src/any.rs b/library/core/src/any.rs index 862f01ecbedb1..6c8cb114b9ef1 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -785,9 +785,8 @@ impl TypeId { /// ``` #[unstable(feature = "type_info", issue = "146922")] #[rustc_const_unstable(feature = "type_info", issue = "146922")] - pub const fn trait_info_of< - T: ptr::Pointee> + ?Sized + 'static, - >( + #[rustc_comptime] + pub fn trait_info_of> + ?Sized + 'static>( self, ) -> Option> { // SAFETY: The vtable was obtained for `T`, so it is guaranteed to be `DynMetadata`. @@ -812,7 +811,8 @@ impl TypeId { /// ``` #[unstable(feature = "type_info", issue = "146922")] #[rustc_const_unstable(feature = "type_info", issue = "146922")] - pub const fn trait_info_of_trait_type_id( + #[rustc_comptime] + pub fn trait_info_of_trait_type_id( self, trait_represented_by_type_id: TypeId, ) -> Option> { diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 78d7314c58110..7875ef3eb09ab 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -2874,11 +2874,12 @@ pub const unsafe fn size_of_val(ptr: *const T) -> usize; pub const unsafe fn align_of_val(ptr: *const T) -> usize; #[rustc_intrinsic] +#[rustc_comptime] #[unstable(feature = "core_intrinsics", issue = "none")] /// Check if a type represented by a `TypeId` implements a trait represented by a `TypeId`. /// It can only be called at compile time, the backends do /// not implement it. If it implements the trait the dyn metadata gets returned for vtable access. -pub const fn type_id_vtable( +pub fn type_id_vtable( _id: crate::any::TypeId, _trait: crate::any::TypeId, ) -> Option> { diff --git a/tests/ui/reflection/reflection_methods_in_runtime_code.rs b/tests/ui/reflection/reflection_methods_in_runtime_code.rs index d2795d7c80622..4204fb3ad16f4 100644 --- a/tests/ui/reflection/reflection_methods_in_runtime_code.rs +++ b/tests/ui/reflection/reflection_methods_in_runtime_code.rs @@ -1,5 +1,3 @@ -//@run-fail - #![feature(type_info)] trait Trait {} @@ -7,4 +5,5 @@ trait Trait {} fn main() { // Test the (lack of) usability of comptime fns in runtime code. std::any::TypeId::of::<[u8; usize::MAX]>().trait_info_of::(); + //~^ ERROR: comptime fns can only be called at compile time } diff --git a/tests/ui/reflection/reflection_methods_in_runtime_code.stderr b/tests/ui/reflection/reflection_methods_in_runtime_code.stderr new file mode 100644 index 0000000000000..ff83c50754254 --- /dev/null +++ b/tests/ui/reflection/reflection_methods_in_runtime_code.stderr @@ -0,0 +1,8 @@ +error: comptime fns can only be called at compile time + --> $DIR/reflection_methods_in_runtime_code.rs:7:5 + | +LL | std::any::TypeId::of::<[u8; usize::MAX]>().trait_info_of::(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + From b3c6e82dea5a7923a8c308b41fb28f21fb7a348f Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 8 Jun 2026 17:21:09 +0200 Subject: [PATCH 35/59] Mark more reflection things as comptime --- library/core/src/intrinsics/mod.rs | 18 ++++++++++++------ library/core/src/mem/type_info.rs | 15 ++++++++++----- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 7875ef3eb09ab..c96c2344a8cb4 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -2923,7 +2923,8 @@ pub const fn type_name() -> &'static str; #[rustc_nounwind] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_intrinsic] -pub const fn type_id() -> crate::any::TypeId; +#[rustc_comptime] +pub fn type_id() -> crate::any::TypeId; /// Tests (at compile-time) if two [`crate::any::TypeId`] instances identify the /// same type. This is necessary because at const-eval time the actual discriminating @@ -2945,7 +2946,8 @@ pub const fn type_id_eq(a: crate::any::TypeId, b: crate::any::TypeId) -> bool { /// The more user-friendly version of this intrinsic is [`core::any::TypeId::size`]. #[rustc_intrinsic] #[unstable(feature = "core_intrinsics", issue = "none")] -pub const fn size_of_type_id(_id: crate::any::TypeId) -> Option { +#[rustc_comptime] +pub fn size_of_type_id(_id: crate::any::TypeId) -> Option { panic!("`TypeId::size` can only be called at compile-time") } @@ -2954,7 +2956,8 @@ pub const fn size_of_type_id(_id: crate::any::TypeId) -> Option { /// The more user-friendly version of this intrinsic is [`core::any::TypeId::variants`]. #[rustc_intrinsic] #[unstable(feature = "core_intrinsics", issue = "none")] -pub const fn type_id_variants(_id: crate::any::TypeId) -> usize { +#[rustc_comptime] +pub fn type_id_variants(_id: crate::any::TypeId) -> usize { panic!("`TypeId::variants` can only be called at compile-time") } @@ -2963,7 +2966,8 @@ pub const fn type_id_variants(_id: crate::any::TypeId) -> usize { /// The more user-friendly version of this intrinsic is [`core::any::TypeId::fields`]. #[rustc_intrinsic] #[unstable(feature = "core_intrinsics", issue = "none")] -pub const fn type_id_fields(_id: crate::any::TypeId, _variant_index: usize) -> usize { +#[rustc_comptime] +pub fn type_id_fields(_id: crate::any::TypeId, _variant_index: usize) -> usize { panic!("`TypeId::fields` can only be called at compile-time") } @@ -2974,7 +2978,8 @@ pub const fn type_id_fields(_id: crate::any::TypeId, _variant_index: usize) -> u /// [`FieldRepresentingType`]: crate::field::FieldRepresentingType #[rustc_intrinsic] #[unstable(feature = "core_intrinsics", issue = "none")] -pub const fn type_id_field_representing_type( +#[rustc_comptime] +pub fn type_id_field_representing_type( _id: crate::any::TypeId, _variant_index: usize, _field_index: usize, @@ -2989,7 +2994,8 @@ pub const fn type_id_field_representing_type( /// [`FieldRepresentingType`]: crate::field::FieldRepresentingType #[rustc_intrinsic] #[unstable(feature = "core_intrinsics", issue = "none")] -pub const fn field_representing_type_actual_type_id( +#[rustc_comptime] +pub fn field_representing_type_actual_type_id( _frt_type_id: crate::any::TypeId, ) -> crate::any::TypeId { panic!("`FieldId::type_id` can only be called at compile-time") diff --git a/library/core/src/mem/type_info.rs b/library/core/src/mem/type_info.rs index 8e7e51caad1f1..9ec36561839b5 100644 --- a/library/core/src/mem/type_info.rs +++ b/library/core/src/mem/type_info.rs @@ -374,7 +374,8 @@ impl TypeId { /// ``` #[unstable(feature = "type_info", issue = "146922")] #[rustc_const_unstable(feature = "type_info", issue = "146922")] - pub const fn size(self) -> Option { + #[rustc_comptime] + pub fn size(self) -> Option { intrinsics::size_of_type_id(self) } @@ -399,7 +400,8 @@ impl TypeId { /// ``` #[unstable(feature = "type_info", issue = "146922")] #[rustc_const_unstable(feature = "type_info", issue = "146922")] - pub const fn variants(self) -> usize { + #[rustc_comptime] + pub fn variants(self) -> usize { intrinsics::type_id_variants(self) } @@ -461,7 +463,8 @@ impl TypeId { /// ``` #[unstable(feature = "type_info", issue = "146922")] #[rustc_const_unstable(feature = "type_info", issue = "146922")] - pub const fn fields(self, variant_index: usize) -> usize { + #[rustc_comptime] + pub fn fields(self, variant_index: usize) -> usize { intrinsics::type_id_fields(self, variant_index) } @@ -527,7 +530,8 @@ impl TypeId { /// ``` #[unstable(feature = "type_info", issue = "146922")] #[rustc_const_unstable(feature = "type_info", issue = "146922")] - pub const fn field(self, variant_index: usize, field_index: usize) -> FieldId { + #[rustc_comptime] + pub fn field(self, variant_index: usize, field_index: usize) -> FieldId { FieldId { frt_type_id: intrinsics::type_id_field_representing_type( self, @@ -571,7 +575,8 @@ impl FieldId { /// ``` #[unstable(feature = "type_info", issue = "146922")] #[rustc_const_unstable(feature = "type_info", issue = "146922")] - pub const fn type_id(self) -> TypeId { + #[rustc_comptime] + pub fn type_id(self) -> TypeId { intrinsics::field_representing_type_actual_type_id(self.frt_type_id) } } From 5bc21b1f584c2b525edf308acaedb77bbf9a0921 Mon Sep 17 00:00:00 2001 From: William Zeng Date: Tue, 9 Jun 2026 18:03:46 -0400 Subject: [PATCH 36/59] Fix parser error recovery for 'dyn' in Rust 2015 --- compiler/rustc_parse/src/parser/ty.rs | 2 +- .../ui/parser/dyn-2015-identifier.fail.stderr | 80 +++++++++++++++++++ tests/ui/parser/dyn-2015-identifier.rs | 28 +++++++ tests/ui/parser/dyn-trait-compatibility.rs | 16 ---- .../ui/parser/dyn-trait-compatibility.stderr | 54 ------------- 5 files changed, 109 insertions(+), 71 deletions(-) create mode 100644 tests/ui/parser/dyn-2015-identifier.fail.stderr create mode 100644 tests/ui/parser/dyn-2015-identifier.rs delete mode 100644 tests/ui/parser/dyn-trait-compatibility.rs delete mode 100644 tests/ui/parser/dyn-trait-compatibility.stderr diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index b5151cf20ab02..8a881c6f8b568 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -1092,7 +1092,7 @@ impl<'a> Parser<'a> { && (self.token.can_begin_type() || (self.token.is_reserved_ident() && !self.token.is_keyword(kw::Where)))) { - if self.token.is_keyword(kw::Dyn) { + if self.token.is_keyword(kw::Dyn) && self.token.span.edition().at_least_rust_2018() { // Account for `&dyn Trait + dyn Other`. self.bump(); self.dcx().emit_err(InvalidDynKeyword { diff --git a/tests/ui/parser/dyn-2015-identifier.fail.stderr b/tests/ui/parser/dyn-2015-identifier.fail.stderr new file mode 100644 index 0000000000000..da82a9f2d067f --- /dev/null +++ b/tests/ui/parser/dyn-2015-identifier.fail.stderr @@ -0,0 +1,80 @@ +error[E0425]: cannot find type `dyn` in this scope + --> $DIR/dyn-2015-identifier.rs:7:11 + | +LL | type A0 = dyn; + | ^^^ not found in this scope + +error[E0425]: cannot find type `dyn` in this scope + --> $DIR/dyn-2015-identifier.rs:13:11 + | +LL | type A2 = dyn; + | ^^^ not found in this scope + +error[E0425]: cannot find type `dyn` in this scope + --> $DIR/dyn-2015-identifier.rs:13:15 + | +LL | type A2 = dyn; + | ^^^ not found in this scope + +error[E0425]: cannot find type `dyn` in this scope + --> $DIR/dyn-2015-identifier.rs:13:20 + | +LL | type A2 = dyn; + | ^^^ not found in this scope + +error[E0425]: cannot find type `dyn` in this scope + --> $DIR/dyn-2015-identifier.rs:18:11 + | +LL | type A3 = dyn<::dyn>; + | ^^^ not found in this scope + +error[E0405]: cannot find trait `dyn` in this scope + --> $DIR/dyn-2015-identifier.rs:18:23 + | +LL | type A3 = dyn<::dyn>; + | ^^^ not found in this scope + +error[E0425]: cannot find type `dyn` in this scope + --> $DIR/dyn-2015-identifier.rs:18:16 + | +LL | type A3 = dyn<::dyn>; + | ^^^ not found in this scope + +error[E0405]: cannot find trait `dyn` in this scope + --> $DIR/dyn-2015-identifier.rs:24:11 + | +LL | type A4 = dyn + dyn; + | ^^^ not found in this scope + +error[E0405]: cannot find trait `dyn` in this scope + --> $DIR/dyn-2015-identifier.rs:24:17 + | +LL | type A4 = dyn + dyn; + | ^^^ not found in this scope + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/dyn-2015-identifier.rs:24:11 + | +LL | type A4 = dyn + dyn; + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `#[warn(bare_trait_objects)]` (part of `#[warn(rust_2021_compatibility)]`) on by default +help: if this is a dyn-compatible trait, use `dyn` + | +LL | type A4 = dyn dyn + dyn; + | +++ + +error[E0433]: cannot find module or crate `dyn` in this scope + --> $DIR/dyn-2015-identifier.rs:10:11 + | +LL | type A1 = dyn::dyn; + | ^^^ use of unresolved module or unlinked crate `dyn` + | + = help: you might be missing a crate named `dyn` + +error: aborting due to 10 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0405, E0425, E0433. +For more information about an error, try `rustc --explain E0405`. diff --git a/tests/ui/parser/dyn-2015-identifier.rs b/tests/ui/parser/dyn-2015-identifier.rs new file mode 100644 index 0000000000000..3bac8d2b631dc --- /dev/null +++ b/tests/ui/parser/dyn-2015-identifier.rs @@ -0,0 +1,28 @@ +//@ edition: 2015 +//@ compile-flags: --crate-type=lib +//@ revisions: pass fail +//@[pass] check-pass +#![cfg(fail)] + +type A0 = dyn; +//[fail]~^ ERROR cannot find type `dyn` in this scope + +type A1 = dyn::dyn; +//[fail]~^ ERROR cannot find module or crate `dyn` in this scope + +type A2 = dyn; +//[fail]~^ ERROR cannot find type `dyn` in this scope +//[fail]~| ERROR cannot find type `dyn` in this scope +//[fail]~| ERROR cannot find type `dyn` in this scope + +type A3 = dyn<::dyn>; +//[fail]~^ ERROR cannot find type `dyn` in this scope +//[fail]~| ERROR cannot find type `dyn` in this scope +//[fail]~| ERROR cannot find trait `dyn` in this scope + +// issue: +type A4 = dyn + dyn; +//[fail]~^ ERROR cannot find trait `dyn` in this scope +//[fail]~| ERROR cannot find trait `dyn` in this scope +//[fail]~| WARN trait objects without an explicit `dyn` are deprecated +//[fail]~| WARN this is accepted in the current edition diff --git a/tests/ui/parser/dyn-trait-compatibility.rs b/tests/ui/parser/dyn-trait-compatibility.rs deleted file mode 100644 index dd01b6e19d05a..0000000000000 --- a/tests/ui/parser/dyn-trait-compatibility.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ edition: 2015 - -type A0 = dyn; -//~^ ERROR cannot find type `dyn` in this scope -type A1 = dyn::dyn; -//~^ ERROR cannot find module or crate `dyn` in this scope -type A2 = dyn; -//~^ ERROR cannot find type `dyn` in this scope -//~| ERROR cannot find type `dyn` in this scope -//~| ERROR cannot find type `dyn` in this scope -type A3 = dyn<::dyn>; -//~^ ERROR cannot find type `dyn` in this scope -//~| ERROR cannot find type `dyn` in this scope -//~| ERROR cannot find trait `dyn` in this scope - -fn main() {} diff --git a/tests/ui/parser/dyn-trait-compatibility.stderr b/tests/ui/parser/dyn-trait-compatibility.stderr deleted file mode 100644 index 233b22123d31c..0000000000000 --- a/tests/ui/parser/dyn-trait-compatibility.stderr +++ /dev/null @@ -1,54 +0,0 @@ -error[E0425]: cannot find type `dyn` in this scope - --> $DIR/dyn-trait-compatibility.rs:3:11 - | -LL | type A0 = dyn; - | ^^^ not found in this scope - -error[E0425]: cannot find type `dyn` in this scope - --> $DIR/dyn-trait-compatibility.rs:7:11 - | -LL | type A2 = dyn; - | ^^^ not found in this scope - -error[E0425]: cannot find type `dyn` in this scope - --> $DIR/dyn-trait-compatibility.rs:7:15 - | -LL | type A2 = dyn; - | ^^^ not found in this scope - -error[E0425]: cannot find type `dyn` in this scope - --> $DIR/dyn-trait-compatibility.rs:7:20 - | -LL | type A2 = dyn; - | ^^^ not found in this scope - -error[E0425]: cannot find type `dyn` in this scope - --> $DIR/dyn-trait-compatibility.rs:11:11 - | -LL | type A3 = dyn<::dyn>; - | ^^^ not found in this scope - -error[E0405]: cannot find trait `dyn` in this scope - --> $DIR/dyn-trait-compatibility.rs:11:23 - | -LL | type A3 = dyn<::dyn>; - | ^^^ not found in this scope - -error[E0425]: cannot find type `dyn` in this scope - --> $DIR/dyn-trait-compatibility.rs:11:16 - | -LL | type A3 = dyn<::dyn>; - | ^^^ not found in this scope - -error[E0433]: cannot find module or crate `dyn` in this scope - --> $DIR/dyn-trait-compatibility.rs:5:11 - | -LL | type A1 = dyn::dyn; - | ^^^ use of unresolved module or unlinked crate `dyn` - | - = help: you might be missing a crate named `dyn` - -error: aborting due to 8 previous errors - -Some errors have detailed explanations: E0405, E0425, E0433. -For more information about an error, try `rustc --explain E0405`. From c010b251a2a7579ddb6a2f9a93c58086147d73b8 Mon Sep 17 00:00:00 2001 From: Mahdi Ali-Raihan Date: Wed, 3 Jun 2026 00:53:20 -0400 Subject: [PATCH 37/59] Implement or_try_* methods on BTreeMap Entry API --- .../alloc/src/collections/btree/map/entry.rs | 76 +++++++++++++++++-- library/alloctests/lib.rs | 1 + library/std/src/collections/hash/map.rs | 10 +-- library/std/src/lib.rs | 1 + 4 files changed, 78 insertions(+), 10 deletions(-) diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs index b99fbb5e84bd6..1c2ad5c568e6a 100644 --- a/library/alloc/src/collections/btree/map/entry.rs +++ b/library/alloc/src/collections/btree/map/entry.rs @@ -165,9 +165,42 @@ impl<'a, K: Ord, V, A: Allocator + Clone> Entry<'a, K, V, A> { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn or_insert_with V>(self, default: F) -> &'a mut V { + self.or_try_insert_with(|| Result::<_, !>::Ok(default())).unwrap() + } + + /// Ensures a value is in the entry by inserting the result of a fallible default function + /// if empty, and returns a mutable reference to the value in the entry. + /// + /// This method works identically to [`or_insert_with`] except that the default function + /// should return a `Result` and, in the case of an error, the error is propagated. + /// + /// [`or_insert_with`]: Self::or_insert_with + /// + /// # Examples + /// + /// ``` + /// #![feature(try_entry)] + /// # fn main() -> Result<(), std::num::ParseIntError> { + /// use std::collections::BTreeMap; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// let value = "42"; + /// + /// map.entry("poneyland").or_try_insert_with(|| value.parse())?; + /// + /// assert_eq!(map["poneyland"], 42); + /// # Ok(()) + /// # } + /// ``` + #[inline] + #[unstable(feature = "try_entry", issue = "157354")] + pub fn or_try_insert_with Result, E>( + self, + default: F, + ) -> Result<&'a mut V, E> { match self { - Occupied(entry) => entry.into_mut(), - Vacant(entry) => entry.insert(default()), + Occupied(entry) => Ok(entry.into_mut()), + Vacant(entry) => Ok(entry.insert(default()?)), } } @@ -193,11 +226,44 @@ impl<'a, K: Ord, V, A: Allocator + Clone> Entry<'a, K, V, A> { #[inline] #[stable(feature = "or_insert_with_key", since = "1.50.0")] pub fn or_insert_with_key V>(self, default: F) -> &'a mut V { + self.or_try_insert_with_key(|k| Result::<_, !>::Ok(default(k))).into_ok() + } + + /// Ensures a value is in the entry by inserting, if empty, the result of the default function. + /// This method allows for generating key-derived values for insertion by providing the default + /// function a reference to the key that was moved during the `entry(key)` method call. + /// + /// This method works identically to [`or_insert_with_key`] except that the default function + /// should return a `Result` and, in the case of an error, the error is propagated. + /// + /// [`or_insert_with_key`]: Self::or_insert_with_key + /// + /// # Examples + /// + /// ``` + /// #![feature(try_entry)] + /// # fn main() -> Result<(), std::num::ParseIntError> { + /// use std::collections::BTreeMap; + /// + /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// + /// map.entry("42").or_try_insert_with_key(|key| key.parse())?; + /// + /// assert_eq!(map["42"], 42); + /// # Ok(()) + /// # } + /// ``` + #[inline] + #[unstable(feature = "try_entry", issue = "157354")] + pub fn or_try_insert_with_key Result, E>( + self, + default: F, + ) -> Result<&'a mut V, E> { match self { - Occupied(entry) => entry.into_mut(), + Occupied(entry) => Ok(entry.into_mut()), Vacant(entry) => { - let value = default(entry.key()); - entry.insert(value) + let value = default(entry.key())?; + Ok(entry.insert(value)) } } } diff --git a/library/alloctests/lib.rs b/library/alloctests/lib.rs index db643ccb7a4e6..590f559e0d524 100644 --- a/library/alloctests/lib.rs +++ b/library/alloctests/lib.rs @@ -51,6 +51,7 @@ #![feature(trusted_random_access)] #![feature(try_reserve_kind)] #![feature(try_trait_v2)] +#![feature(unwrap_infallible)] #![feature(wtf8_internals)] // tidy-alphabetical-end // diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 3eca5b6f974b6..af03ae9a35b1c 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -2552,7 +2552,7 @@ impl<'a, K, V, A: Allocator> Entry<'a, K, V, A> { /// # Examples /// /// ``` - /// # #![feature(try_entry)] + /// #![feature(try_entry)] /// # fn main() -> Result<(), std::num::ParseIntError> { /// use std::collections::HashMap; /// @@ -2566,7 +2566,7 @@ impl<'a, K, V, A: Allocator> Entry<'a, K, V, A> { /// # } /// ``` #[inline] - #[unstable(feature = "try_entry", issue = "none")] + #[unstable(feature = "try_entry", issue = "157354")] pub fn or_try_insert_with Result, E>( self, default: F, @@ -2598,7 +2598,7 @@ impl<'a, K, V, A: Allocator> Entry<'a, K, V, A> { #[inline] #[stable(feature = "or_insert_with_key", since = "1.50.0")] pub fn or_insert_with_key V>(self, default: F) -> &'a mut V { - self.or_try_insert_with_key(|k| Result::<_, !>::Ok(default(k))).unwrap() + self.or_try_insert_with_key(|k| Result::<_, !>::Ok(default(k))).into_ok() } /// Ensures a value is in the entry by inserting, if empty, the result of the default function. @@ -2613,7 +2613,7 @@ impl<'a, K, V, A: Allocator> Entry<'a, K, V, A> { /// # Examples /// /// ``` - /// # #![feature(try_entry)] + /// #![feature(try_entry)] /// # fn main() -> Result<(), std::num::ParseIntError> { /// use std::collections::HashMap; /// @@ -2626,7 +2626,7 @@ impl<'a, K, V, A: Allocator> Entry<'a, K, V, A> { /// # } /// ``` #[inline] - #[unstable(feature = "try_entry", issue = "none")] + #[unstable(feature = "try_entry", issue = "157354")] pub fn or_try_insert_with_key Result, E>( self, default: F, diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index addbb407083c7..a01d930ffdd72 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -312,6 +312,7 @@ #![feature(try_blocks)] #![feature(try_trait_v2)] #![feature(type_alias_impl_trait)] +#![feature(unwrap_infallible)] // tidy-alphabetical-end // // Library features (core): From 6324b4afbfa10120fa0488ce20ba34d810dd673c Mon Sep 17 00:00:00 2001 From: Daniel Smith Date: Mon, 8 Jun 2026 12:09:18 -0400 Subject: [PATCH 38/59] Add flush strategy to allow observing bytes before they are flushed. --- compiler/rustc_data_structures/src/marker.rs | 1 + .../src/persist/file_format.rs | 4 +-- .../rustc_incremental/src/persist/save.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 2 +- compiler/rustc_metadata/src/rmeta/mod.rs | 2 +- compiler/rustc_metadata/src/rmeta/table.rs | 2 +- compiler/rustc_middle/src/dep_graph/graph.rs | 4 +-- .../rustc_middle/src/dep_graph/serialized.rs | 10 ++++-- .../rustc_middle/src/query/on_disk_cache.rs | 4 +-- compiler/rustc_serialize/src/opaque.rs | 36 ++++++++++++++----- compiler/rustc_serialize/src/opaque/tests.rs | 36 +++++++++++++++++-- compiler/rustc_span/src/lib.rs | 2 +- 12 files changed, 81 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_data_structures/src/marker.rs b/compiler/rustc_data_structures/src/marker.rs index 997077ac4402e..2fe2a30c36751 100644 --- a/compiler/rustc_data_structures/src/marker.rs +++ b/compiler/rustc_data_structures/src/marker.rs @@ -64,6 +64,7 @@ already_send!( [std::io::Error][std::fs::File][std::panic::Location<'_>][rustc_arena::DroplessArena] [jobserver_crate::Client][jobserver_crate::HelperThread][crate::memmap::Mmap] [crate::profiling::SelfProfiler][crate::owned_slice::OwnedSlice] + [rustc_serialize::opaque::FileEncoder<'_>] ); #[cfg(target_has_atomic = "64")] diff --git a/compiler/rustc_incremental/src/persist/file_format.rs b/compiler/rustc_incremental/src/persist/file_format.rs index c47540fe385ba..eee40fbedf569 100644 --- a/compiler/rustc_incremental/src/persist/file_format.rs +++ b/compiler/rustc_incremental/src/persist/file_format.rs @@ -28,7 +28,7 @@ const FILE_MAGIC: &[u8] = b"RSIC"; /// Change this if the header format changes. const HEADER_FORMAT_VERSION: u16 = 0; -pub(crate) fn write_file_header(stream: &mut FileEncoder, sess: &Session) { +pub(crate) fn write_file_header(stream: &mut FileEncoder<'_>, sess: &Session) { stream.emit_raw_bytes(FILE_MAGIC); stream.emit_raw_bytes(&u16::to_le_bytes(HEADER_FORMAT_VERSION)); @@ -41,7 +41,7 @@ pub(crate) fn write_file_header(stream: &mut FileEncoder, sess: &Session) { pub(crate) fn save_in(sess: &Session, path_buf: PathBuf, name: &str, encode: F) where - F: FnOnce(FileEncoder) -> FileEncodeResult, + F: FnOnce(FileEncoder<'static>) -> FileEncodeResult, { debug!("save: storing data in {}", path_buf.display()); diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs index 69705f28aa114..8360b352a2643 100644 --- a/compiler/rustc_incremental/src/persist/save.rs +++ b/compiler/rustc_incremental/src/persist/save.rs @@ -131,7 +131,7 @@ pub fn save_work_product_index( }); } -fn encode_work_product_index(work_products: &WorkProductMap, encoder: &mut FileEncoder) { +fn encode_work_product_index(work_products: &WorkProductMap, encoder: &mut FileEncoder<'_>) { let serialized_products: Vec<_> = work_products .to_sorted_stable_ord() .into_iter() diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 1483de572c341..40223bab4452c 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -40,7 +40,7 @@ use crate::errors::{FailCreateFileEncoder, FailWriteFile}; use crate::rmeta::*; pub(super) struct EncodeContext<'a, 'tcx> { - opaque: opaque::FileEncoder, + opaque: opaque::FileEncoder<'a>, tcx: TyCtxt<'tcx>, feat: &'tcx rustc_feature::Features, tables: TableBuilders, diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 6a396faf914cc..7f2bdab177e90 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -364,7 +364,7 @@ macro_rules! define_tables { } impl TableBuilders { - fn encode(&self, buf: &mut FileEncoder) -> LazyTables { + fn encode(&self, buf: &mut FileEncoder<'_>) -> LazyTables { LazyTables { $($name1: self.$name1.encode(buf),)+ $($name2: self.$name2.encode(buf),)+ diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index e3f40e5b17323..119978d469855 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -487,7 +487,7 @@ impl> TableBui } } - pub(crate) fn encode(&self, buf: &mut FileEncoder) -> LazyTable { + pub(crate) fn encode(&self, buf: &mut FileEncoder<'_>) -> LazyTable { let pos = buf.position(); let width = self.width; diff --git a/compiler/rustc_middle/src/dep_graph/graph.rs b/compiler/rustc_middle/src/dep_graph/graph.rs index b5c32a1848aeb..e8d14336d1cf7 100644 --- a/compiler/rustc_middle/src/dep_graph/graph.rs +++ b/compiler/rustc_middle/src/dep_graph/graph.rs @@ -135,7 +135,7 @@ impl DepGraph { session: &Session, prev_graph: Arc, prev_work_products: WorkProductMap, - encoder: FileEncoder, + encoder: FileEncoder<'static>, ) -> DepGraph { let prev_graph_node_count = prev_graph.node_count(); @@ -1135,7 +1135,7 @@ impl CurrentDepGraph { fn new( session: &Session, prev_graph_node_count: usize, - encoder: FileEncoder, + encoder: FileEncoder<'static>, previous: Arc, ) -> Self { let mut stable_hasher = StableHasher::new(); diff --git a/compiler/rustc_middle/src/dep_graph/serialized.rs b/compiler/rustc_middle/src/dep_graph/serialized.rs index 6d7f8e37e6c0a..fe7ea207bbff7 100644 --- a/compiler/rustc_middle/src/dep_graph/serialized.rs +++ b/compiler/rustc_middle/src/dep_graph/serialized.rs @@ -564,13 +564,17 @@ struct LocalEncoderResult { struct EncoderState { next_node_index: AtomicU64, previous: Arc, - file: Lock>, + file: Lock>>, local: WorkerLocal>, stats: Option>>, } impl EncoderState { - fn new(encoder: FileEncoder, record_stats: bool, previous: Arc) -> Self { + fn new( + encoder: FileEncoder<'static>, + record_stats: bool, + previous: Arc, + ) -> Self { Self { previous, next_node_index: AtomicU64::new(0), @@ -861,7 +865,7 @@ pub(crate) struct GraphEncoder { impl GraphEncoder { pub(crate) fn new( sess: &Session, - encoder: FileEncoder, + encoder: FileEncoder<'static>, prev_node_count: usize, previous: Arc, ) -> Self { diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index f2d3154bf8950..3a47231426dac 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -201,7 +201,7 @@ impl OnDiskCache { /// Serialize the current-session data that will be loaded by [`OnDiskCache`] /// in a subsequent incremental compilation session. - pub fn serialize(tcx: TyCtxt<'_>, encoder: FileEncoder) -> FileEncodeResult { + pub fn serialize(tcx: TyCtxt<'_>, encoder: FileEncoder<'static>) -> FileEncodeResult { // Serializing the `DepGraph` should not modify it. tcx.dep_graph.with_ignore(|| { // Allocate `SourceFileIndex`es. @@ -779,7 +779,7 @@ impl_ref_decoder! {<'tcx> /// An encoder that can write to the incremental compilation cache. pub struct CacheEncoder<'a, 'tcx> { tcx: TyCtxt<'tcx>, - encoder: FileEncoder, + encoder: FileEncoder<'static>, type_shorthands: FxHashMap, usize>, predicate_shorthands: FxHashMap, usize>, interpret_allocs: FxIndexSet, diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs index 4242642c6643f..4a644d3bb6eac 100644 --- a/compiler/rustc_serialize/src/opaque.rs +++ b/compiler/rustc_serialize/src/opaque.rs @@ -29,7 +29,10 @@ const BUF_SIZE: usize = 64 * 1024; /// `Vec`. `FileEncoder` is better because its memory use is determined by the /// size of the buffer, rather than the full length of the encoded data, and /// because it doesn't need to reallocate memory along the way. -pub struct FileEncoder { +/// +/// The `'a` lifetime is the borrow of the optional flush strategy (see +/// `flush_strategy`); it is unused (`'static`) for encoders created without one. +pub struct FileEncoder<'a> { // The input buffer. For adequate performance, we need to be able to write // directly to the unwritten region of the buffer, without calling copy_from_slice. // Note that our buffer is always initialized so that we can do that direct access @@ -43,11 +46,12 @@ pub struct FileEncoder { // comment on `trait Encoder`. res: Result<(), io::Error>, path: PathBuf, + flush_strategy: Option<&'a mut (dyn FnMut(&[u8]) + Send)>, #[cfg(debug_assertions)] finished: bool, } -impl FileEncoder { +impl<'a> FileEncoder<'a> { pub fn new>(path: P) -> io::Result { // File::create opens the file for writing only. When -Zmeta-stats is enabled, the metadata // encoder rewinds the file to inspect what was written. So we need to always open the file @@ -62,11 +66,21 @@ impl FileEncoder { flushed: 0, file, res: Ok(()), + flush_strategy: None, #[cfg(debug_assertions)] finished: false, }) } + pub fn with_flush_strategy>( + path: P, + strategy: &'a mut (dyn FnMut(&[u8]) + Send), + ) -> io::Result { + let mut encoder = Self::new(path)?; + encoder.flush_strategy = Some(strategy); + Ok(encoder) + } + #[inline] pub fn position(&self) -> usize { // Tracking position this way instead of having a `self.position` field @@ -86,6 +100,9 @@ impl FileEncoder { self.res = self.file.write_all(&self.buf[..self.buffered]); } self.flushed += self.buffered; + if let Some(f) = &mut self.flush_strategy { + f(&self.buf[..self.buffered]); + } self.buffered = 0; } @@ -115,6 +132,9 @@ impl FileEncoder { } else { if self.res.is_ok() { self.res = self.file.write_all(buf); + if let Some(f) = &mut self.flush_strategy { + f(buf); + } } self.flushed += buf.len(); } @@ -200,7 +220,7 @@ impl FileEncoder { } #[cfg(debug_assertions)] -impl Drop for FileEncoder { +impl Drop for FileEncoder<'_> { fn drop(&mut self) { if !std::thread::panicking() { assert!(self.finished); @@ -217,7 +237,7 @@ macro_rules! write_leb128 { }; } -impl Encoder for FileEncoder { +impl Encoder for FileEncoder<'_> { write_leb128!(emit_usize, usize, write_usize_leb128); write_leb128!(emit_u128, u128, write_u128_leb128); write_leb128!(emit_u64, u64, write_u64_leb128); @@ -415,8 +435,8 @@ impl<'a> Decoder for MemDecoder<'a> { // Specialize encoding byte slices. This specialization also applies to encoding `Vec`s, etc., // since the default implementations call `encode` on their slices internally. -impl Encodable for [u8] { - fn encode(&self, e: &mut FileEncoder) { +impl Encodable> for [u8] { + fn encode(&self, e: &mut FileEncoder<'_>) { Encoder::emit_usize(e, self.len()); e.emit_raw_bytes(self); } @@ -438,9 +458,9 @@ impl IntEncodedWithFixedSize { pub const ENCODED_SIZE: usize = 8; } -impl Encodable for IntEncodedWithFixedSize { +impl Encodable> for IntEncodedWithFixedSize { #[inline] - fn encode(&self, e: &mut FileEncoder) { + fn encode(&self, e: &mut FileEncoder<'_>) { let start_pos = e.position(); e.write_array(self.0.to_le_bytes()); let end_pos = e.position(); diff --git a/compiler/rustc_serialize/src/opaque/tests.rs b/compiler/rustc_serialize/src/opaque/tests.rs index 11401d245951b..caaf51fdb7d02 100644 --- a/compiler/rustc_serialize/src/opaque/tests.rs +++ b/compiler/rustc_serialize/src/opaque/tests.rs @@ -3,7 +3,7 @@ use std::fs; use rustc_macros::{Decodable_NoContext, Encodable_NoContext}; -use crate::opaque::{FileEncoder, MemDecoder}; +use crate::opaque::{FileEncoder, MAGIC_END_BYTES, MemDecoder}; use crate::{Decodable, Encodable}; #[derive(PartialEq, Clone, Debug, Encodable_NoContext, Decodable_NoContext)] @@ -28,7 +28,7 @@ struct Struct { } fn check_round_trip< - T: Encodable + for<'a> Decodable> + PartialEq + Debug, + T: for<'a> Encodable> + for<'a> Decodable> + PartialEq + Debug, >( values: Vec, ) { @@ -293,3 +293,35 @@ fn test_cell() { let obj = B { foo: Cell::new(true), bar: RefCell::new(A { baz: 2 }) }; check_round_trip(vec![obj]); } + +#[test] +fn test_flush_strategy() { + let tmpfile = tempfile::NamedTempFile::new().unwrap(); + let tmpfile = tmpfile.path(); + + // Small write that is explicitly flushed, and then a chunk larger than BUF_SIZE (64 KiB). + // to hit `write_all_cold_path`. + let small: Vec = (0..100u32).map(|i| i as u8).collect(); + let big: Vec = (0..100_000u32).map(|i| i as u8).collect(); + + let mut expected: Vec = Vec::new(); + expected.extend(&small); + expected.extend(&big); + expected.extend(MAGIC_END_BYTES); + + let mut flushed: Vec = Vec::new(); + let mut strategy = |buf: &[u8]| { + flushed.extend(buf); + }; + let mut encoder = FileEncoder::with_flush_strategy(&tmpfile, &mut strategy).unwrap(); + + encoder.write_all(&small); + encoder.flush(); + encoder.write_all(&big); + encoder.finish().unwrap(); + + drop(encoder); + + assert_eq!(flushed, expected); + assert_eq!(flushed, fs::read(&tmpfile).unwrap()); +} diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 13dea1657339e..5015741f10c5f 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -1362,7 +1362,7 @@ pub trait SpanEncoder: Encoder { fn encode_def_id(&mut self, def_id: DefId); } -impl SpanEncoder for FileEncoder { +impl SpanEncoder for FileEncoder<'_> { fn encode_span(&mut self, span: Span) { let span = span.data(); span.lo.encode(self); From 0863e172376a5c80d1bef17c3590b8ce614f87d4 Mon Sep 17 00:00:00 2001 From: Jose Torres Date: Tue, 9 Jun 2026 22:22:55 -0400 Subject: [PATCH 39/59] refactor TypeRelativePath::AssocItem to use AliasTerm, remove alias_ty_kind_from_def_id and new_from_def_id --- .../src/hir_ty_lowering/mod.rs | 47 +++++++++---------- .../src/ty/context/impl_interner.rs | 15 ------ compiler/rustc_type_ir/src/interner.rs | 2 - compiler/rustc_type_ir/src/ty_kind.rs | 4 -- src/tools/clippy/clippy_utils/src/ty/mod.rs | 12 +++-- 5 files changed, 30 insertions(+), 50 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 943256ce07352..efadba92f2643 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -297,7 +297,7 @@ pub enum PermitVariants { #[derive(Debug, Clone, Copy)] enum TypeRelativePath<'tcx> { - AssocItem(DefId, GenericArgsRef<'tcx>), + AssocItem(ty::AliasTerm<'tcx>), Variant { adt: Ty<'tcx>, variant_did: DefId }, Ctor { ctor_def_id: DefId, args: GenericArgsRef<'tcx> }, } @@ -1356,15 +1356,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { span, LowerTypeRelativePathMode::Type(permit_variants), )? { - TypeRelativePath::AssocItem(def_id, args) => { - let alias_ty = ty::AliasTy::new_from_args( - tcx, - ty::AliasTyKind::new_from_def_id(tcx, def_id), - args, - ); - let ty = Ty::new_alias(tcx, alias_ty); + TypeRelativePath::AssocItem(alias_term) => { + let ty = alias_term.expect_ty().to_ty(tcx); let ty = self.check_param_uses_if_mcg(ty, span, false); - Ok((ty, tcx.def_kind(def_id), def_id)) + Ok((ty, tcx.def_kind(alias_term.def_id()), alias_term.def_id())) } TypeRelativePath::Variant { adt, variant_did } => { let adt = self.check_param_uses_if_mcg(adt, span, false); @@ -1396,16 +1391,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { span, LowerTypeRelativePathMode::Const, )? { - TypeRelativePath::AssocItem(def_id, args) => { - self.require_type_const_attribute(def_id, span)?; - let ct = Const::new_unevaluated( - tcx, - ty::UnevaluatedConst::new( - tcx, - ty::UnevaluatedConstKind::new_from_def_id(tcx, def_id), - args, - ), - ); + TypeRelativePath::AssocItem(alias_term) => { + self.require_type_const_attribute(alias_term.def_id(), span)?; + let ct = Const::new_unevaluated(tcx, alias_term.expect_ct()); let ct = self.check_param_uses_if_mcg(ct, span, false); Ok(ct) } @@ -1487,7 +1475,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } // FIXME(inherent_associated_types, #106719): Support self types other than ADTs. - if let Some((did, args)) = self.probe_inherent_assoc_item( + if let Some(alias_term) = self.probe_inherent_assoc_item( segment, adt_def.did(), self_ty, @@ -1495,7 +1483,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { span, mode.assoc_tag(), )? { - return Ok(TypeRelativePath::AssocItem(did, args)); + return Ok(TypeRelativePath::AssocItem(alias_term)); } } @@ -1529,7 +1517,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ); } - Ok(TypeRelativePath::AssocItem(item_def_id, args)) + Ok(TypeRelativePath::AssocItem(ty::AliasTerm::new_from_def_id(tcx, item_def_id, args))) } /// Resolve a [type-relative](hir::QPath::TypeRelative) (and type-level) path. @@ -1609,7 +1597,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { block: HirId, span: Span, assoc_tag: ty::AssocTag, - ) -> Result)>, ErrorGuaranteed> { + ) -> Result>, ErrorGuaranteed> { let tcx = self.tcx(); if !tcx.features().inherent_associated_types() { @@ -1692,7 +1680,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .chain(args.into_iter().skip(parent_args.len())), ); - Ok(Some((assoc_item, args))) + let kind = match assoc_tag { + ty::AssocTag::Type => ty::AliasTermKind::InherentTy { def_id: assoc_item }, + ty::AssocTag::Const => { + // drop once `InherentConst` accepts IAC-shaped args (issue #156181) + // without this, `new_from_args` errors (#155341). + self.require_type_const_attribute(assoc_item, span)?; + ty::AliasTermKind::InherentConst { def_id: assoc_item } + } + ty::AssocTag::Fn => unreachable!(), + }; + + Ok(Some(ty::AliasTerm::new_from_args(tcx, kind, args))) } /// Given name and kind search for the assoc item in the provided scope and check if it's accessible[^1]. diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs index e9eef9336e8ba..c6989ddd36199 100644 --- a/compiler/rustc_middle/src/ty/context/impl_interner.rs +++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs @@ -208,21 +208,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.adt_def(adt_def_id) } - fn alias_ty_kind_from_def_id(self, def_id: DefId) -> ty::AliasTyKind<'tcx> { - match self.def_kind(def_id) { - DefKind::AssocTy - if let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(def_id)) => - { - ty::Inherent { def_id } - } - DefKind::AssocTy => ty::Projection { def_id }, - - DefKind::OpaqueTy => ty::Opaque { def_id }, - DefKind::TyAlias => ty::Free { def_id }, - kind => bug!("unexpected DefKind in AliasTy: {kind:?}"), - } - } - fn unevaluated_const_kind_from_def_id( self, def_id: Self::DefId, diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 1e5ad0b00e7ef..5a98ff74cea42 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -244,8 +244,6 @@ pub trait Interner: type AdtDef: AdtDef; fn adt_def(self, adt_def_id: Self::AdtId) -> Self::AdtDef; - fn alias_ty_kind_from_def_id(self, def_id: Self::DefId) -> ty::AliasTyKind; - fn unevaluated_const_kind_from_def_id( self, def_id: Self::DefId, diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 2014ec094524f..784a91424156f 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -65,10 +65,6 @@ pub enum AliasTyKind { } impl AliasTyKind { - pub fn new_from_def_id(interner: I, def_id: I::DefId) -> Self { - interner.alias_ty_kind_from_def_id(def_id) - } - pub fn descr(self) -> &'static str { match self { AliasTyKind::Projection { .. } => "associated type", diff --git a/src/tools/clippy/clippy_utils/src/ty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/mod.rs index 056eb818c1ac3..a944e91db0c0e 100644 --- a/src/tools/clippy/clippy_utils/src/ty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/mod.rs @@ -1050,11 +1050,13 @@ pub fn make_projection<'tcx>( #[cfg(debug_assertions)] assert_generic_args_match(tcx, assoc_item.def_id, args); - Some(AliasTy::new_from_args( - tcx, - ty::AliasTyKind::new_from_def_id(tcx, assoc_item.def_id), - args, - )) + let kind = if let DefKind::Impl { of_trait: false } = tcx.def_kind(tcx.parent(assoc_item.def_id)) { + ty::AliasTyKind::Inherent { def_id: assoc_item.def_id } + } else { + ty::AliasTyKind::Projection { def_id: assoc_item.def_id } + }; + + Some(AliasTy::new_from_args(tcx, kind, args)) } helper( tcx, From 0b4a6f8463e4d513a8cf0317e1eb876fa0f42d34 Mon Sep 17 00:00:00 2001 From: Jose Torres Date: Tue, 9 Jun 2026 22:40:38 -0400 Subject: [PATCH 40/59] Remove unused is_type_const from hir::TraitItemKind --- compiler/rustc_ast_lowering/src/item.rs | 2 +- compiler/rustc_hir/src/hir.rs | 31 +++---------------- compiler/rustc_hir/src/intravisit.rs | 2 +- compiler/rustc_hir_analysis/src/collect.rs | 9 +++--- .../src/collect/resolve_bound_vars.rs | 2 +- .../rustc_hir_analysis/src/collect/type_of.rs | 2 +- .../rustc_hir_analysis/src/hir_wf_check.rs | 2 +- compiler/rustc_hir_pretty/src/lib.rs | 2 +- compiler/rustc_hir_typeck/src/lib.rs | 4 +-- compiler/rustc_mir_build/src/builder/mod.rs | 2 +- compiler/rustc_passes/src/reachable.rs | 6 ++-- compiler/rustc_ty_utils/src/assoc.rs | 4 +-- src/librustdoc/clean/mod.rs | 4 +-- .../clippy/clippy_lints/src/non_copy_const.rs | 4 +-- .../clippy/clippy_lints/src/types/mod.rs | 2 +- 15 files changed, 27 insertions(+), 51 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 336c644961ab6..9d7bc136eaebb 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1008,7 +1008,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } else { None }; - hir::TraitItemKind::Const(ty, rhs, rhs_kind.is_type_const().into()) + hir::TraitItemKind::Const(ty, rhs) }, ); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 4041556925aae..10cec6e4f8be6 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3319,7 +3319,7 @@ impl<'hir> TraitItem<'hir> { expect_methods_self_kind! { expect_const, (&'hir Ty<'hir>, Option>), - TraitItemKind::Const(ty, rhs, _), (ty, *rhs); + TraitItemKind::Const(ty, rhs), (ty, *rhs); expect_fn, (&FnSig<'hir>, &TraitFn<'hir>), TraitItemKind::Fn(ty, trfn), (ty, trfn); @@ -3339,32 +3339,11 @@ pub enum TraitFn<'hir> { Provided(BodyId), } -#[derive(Debug, Clone, Copy, PartialEq, Eq, StableHash)] -pub enum IsTypeConst { - No, - Yes, -} - -impl From for IsTypeConst { - fn from(value: bool) -> Self { - if value { Self::Yes } else { Self::No } - } -} - -impl From for bool { - fn from(value: IsTypeConst) -> Self { - matches!(value, IsTypeConst::Yes) - } -} - /// Represents a trait method or associated constant or type #[derive(Debug, Clone, Copy, StableHash)] pub enum TraitItemKind<'hir> { - // FIXME(mgca) eventually want to move the option that is around `ConstItemRhs<'hir>` - // into `ConstItemRhs`, much like `ast::ConstItemRhsKind`, but for now mark whether - // this node is a TypeConst with a flag. /// An associated constant with an optional value (otherwise `impl`s must contain a value). - Const(&'hir Ty<'hir>, Option>, IsTypeConst), + Const(&'hir Ty<'hir>, Option>), /// An associated function with an optional body. Fn(FnSig<'hir>, TraitFn<'hir>), /// An associated type with (possibly empty) bounds and optional concrete @@ -5009,7 +4988,7 @@ impl<'hir> OwnerNode<'hir> { | OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(_, TraitFn::Provided(body)) - | TraitItemKind::Const(_, Some(ConstItemRhs::Body(body)), _), + | TraitItemKind::Const(_, Some(ConstItemRhs::Body(body))), .. }) | OwnerNode::ImplItem(ImplItem { @@ -5236,7 +5215,7 @@ impl<'hir> Node<'hir> { _ => None, }, Node::TraitItem(it) => match it.kind { - TraitItemKind::Const(ty, _, _) => Some(ty), + TraitItemKind::Const(ty, _) => Some(ty), TraitItemKind::Type(_, ty) => ty, _ => None, }, @@ -5280,7 +5259,7 @@ impl<'hir> Node<'hir> { | Node::TraitItem(TraitItem { owner_id, kind: - TraitItemKind::Const(_, Some(ConstItemRhs::Body(body)), _) + TraitItemKind::Const(_, Some(ConstItemRhs::Body(body))) | TraitItemKind::Fn(_, TraitFn::Provided(body)), .. }) diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index b0c6a136ba29f..d5c5e8845f41b 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -1273,7 +1273,7 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>( try_visit!(visitor.visit_defaultness(&defaultness)); try_visit!(visitor.visit_id(hir_id)); match *kind { - TraitItemKind::Const(ref ty, default, _) => { + TraitItemKind::Const(ref ty, default) => { try_visit!(visitor.visit_ty_unambig(ty)); visit_opt!(visitor, visit_const_item_rhs, default); } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 8d39934988d29..35ab34c6c0e4d 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1673,8 +1673,7 @@ fn is_anon_const_rhs_of_const_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) let (Node::Item(hir::Item { kind: hir::ItemKind::Const(_, _, _, ct_rhs), .. }) | Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(_, ct_rhs), .. }) | Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Const(_, Some(ct_rhs), _), - .. + kind: hir::TraitItemKind::Const(_, Some(ct_rhs)), .. })) = grandparent_node else { return false; @@ -1718,9 +1717,9 @@ fn const_of_item<'tcx>( ) -> ty::EarlyBinder<'tcx, Const<'tcx>> { let ct_rhs = match tcx.hir_node_by_def_id(def_id) { hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(.., ct), .. }) => *ct, - hir::Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Const(_, ct, _), .. - }) => ct.expect("no default value for trait assoc const"), + hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Const(_, ct), .. }) => { + ct.expect("no default value for trait assoc const") + } hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(.., ct), .. }) => *ct, _ => { span_bug!(tcx.def_span(def_id), "`const_of_item` expected a const or assoc const item") diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 3ca085bc0897f..7c6f73e1f2bc7 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -860,7 +860,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { } }) } - Const(_, _, _) => self.visit_early(trait_item.hir_id(), trait_item.generics, |this| { + Const(_, _) => self.visit_early(trait_item.hir_id(), trait_item.generics, |this| { intravisit::walk_trait_item(this, trait_item) }), } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 3ac603fc715f3..4e3d77c95f615 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -62,7 +62,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ let args = ty::GenericArgs::identity_for_item(tcx, def_id); Ty::new_fn_def(tcx, def_id.to_def_id(), args) } - TraitItemKind::Const(ty, rhs, _) => rhs + TraitItemKind::Const(ty, rhs) => rhs .and_then(|rhs| { ty.is_suggestable_infer_ty().then(|| { infer_placeholder_type( diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index 87b52c57dc6a2..f2c25c8716783 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -139,7 +139,7 @@ pub(super) fn diagnostic_hir_wf_check<'tcx>( }, hir::Node::TraitItem(item) => match item.kind { hir::TraitItemKind::Type(_, ty) => ty.into_iter().collect(), - hir::TraitItemKind::Const(ty, _, _) => vec![ty], + hir::TraitItemKind::Const(ty, _) => vec![ty], ref item => bug!("Unexpected TraitItem {:?}", item), }, hir::Node::Item(item) => match item.kind { diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index b01821ab76cbf..ff892d44e447e 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -951,7 +951,7 @@ impl<'a> State<'a> { self.maybe_print_comment(ti.span.lo()); self.print_attrs(self.attrs(ti.hir_id())); match ti.kind { - hir::TraitItemKind::Const(ty, default, _) => { + hir::TraitItemKind::Const(ty, default) => { self.print_associated_const(ti.ident, ti.generics, ty, default); } hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(arg_idents)) => { diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 55a01ddfba779..b5ab51d593be3 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -286,9 +286,7 @@ fn extend_err_with_const_context( ) { match node { hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(ty, _), .. }) - | hir::Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Const(ty, _, _), .. - }) => { + | hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Const(ty, _), .. }) => { // Point at the `Type` in `const NAME: Type = value;`. err.span_label(ty.span, "expected because of the type of the associated constant"); } diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index d158f55a3111c..e9b86eef7277c 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -577,7 +577,7 @@ fn construct_const<'a, 'tcx>( }) | Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(ty, _), span, .. }) | Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Const(ty, Some(_), _), + kind: hir::TraitItemKind::Const(ty, Some(_)), span, .. }) => (*span, ty.span), diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index 6b5457daf4a27..fdae03ec49d9f 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -145,7 +145,7 @@ impl<'tcx> ReachableContext<'tcx> { _ => false, }, Node::TraitItem(trait_method) => match trait_method.kind { - hir::TraitItemKind::Const(_, ref default, _) => default.is_some(), + hir::TraitItemKind::Const(_, ref default) => default.is_some(), hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => true, hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_)) | hir::TraitItemKind::Type(..) => false, @@ -266,11 +266,11 @@ impl<'tcx> ReachableContext<'tcx> { } Node::TraitItem(trait_method) => { match trait_method.kind { - hir::TraitItemKind::Const(_, None, _) + hir::TraitItemKind::Const(_, None) | hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_)) => { // Keep going, nothing to get exported } - hir::TraitItemKind::Const(_, Some(rhs), _) => self.visit_const_item_rhs(rhs), + hir::TraitItemKind::Const(_, Some(rhs)) => self.visit_const_item_rhs(rhs), hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body_id)) => { self.visit_nested_body(body_id); } diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 12bf1c2e5dae7..58fadff1e6e5d 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -88,8 +88,8 @@ fn associated_item_from_trait_item( let owner_id = trait_item.owner_id; let name = trait_item.ident.name; let kind = match trait_item.kind { - hir::TraitItemKind::Const(_, _, is_type_const) => { - ty::AssocKind::Const { name, is_type_const: is_type_const.into() } + hir::TraitItemKind::Const(_, _) => { + ty::AssocKind::Const { name, is_type_const: tcx.is_type_const(owner_id.def_id) } } hir::TraitItemKind::Fn { .. } => { ty::AssocKind::Fn { name, has_self: fn_has_self_parameter(tcx, owner_id) } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 9dbff8aaf8c71..0c164ada82876 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1271,14 +1271,14 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext let local_did = trait_item.owner_id.to_def_id(); cx.with_param_env(local_did, |cx| { let inner = match trait_item.kind { - hir::TraitItemKind::Const(ty, Some(default), _) => { + hir::TraitItemKind::Const(ty, Some(default)) => { ProvidedAssocConstItem(Box::new(Constant { generics: enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx)), kind: clean_const_item_rhs(default, local_did), type_: clean_ty(ty, cx), })) } - hir::TraitItemKind::Const(ty, None, _) => { + hir::TraitItemKind::Const(ty, None) => { let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx)); RequiredAssocConstItem(generics, Box::new(clean_ty(ty, cx))) } diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index fabc1f5c74ee0..22d7d83d730d9 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -757,7 +757,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> { } fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) { - if let TraitItemKind::Const(_, ct_rhs_opt, _) = item.kind + if let TraitItemKind::Const(_, ct_rhs_opt) = item.kind && let ty = cx.tcx.type_of(item.owner_id).instantiate_identity().skip_norm_wip() && match self.is_ty_freeze(cx.tcx, cx.typing_env(), ty) { IsFreeze::No => true, @@ -958,7 +958,7 @@ fn get_const_hir_value<'tcx>( { match tcx.hir_node(tcx.local_def_id_to_hir_id(did)) { Node::ImplItem(item) if let ImplItemKind::Const(.., ct_rhs) = item.kind => (did, ct_rhs), - Node::TraitItem(item) if let TraitItemKind::Const(_, Some(ct_rhs), _) = item.kind => (did, ct_rhs), + Node::TraitItem(item) if let TraitItemKind::Const(_, Some(ct_rhs)) = item.kind => (did, ct_rhs), _ => return None, } }, diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs index 17f1adf6960f0..f6c6e3848a4c4 100644 --- a/src/tools/clippy/clippy_lints/src/types/mod.rs +++ b/src/tools/clippy/clippy_lints/src/types/mod.rs @@ -514,7 +514,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { }; match item.kind { - TraitItemKind::Const(ty, _, _) | TraitItemKind::Type(_, Some(ty)) => { + TraitItemKind::Const(ty, _) | TraitItemKind::Type(_, Some(ty)) => { self.check_ty(cx, ty, context); }, TraitItemKind::Fn(ref sig, trait_method) => { From 8ee1dfa887f0ab3b958fd26d81d9155b0b7c140c Mon Sep 17 00:00:00 2001 From: cezarbbb Date: Wed, 10 Jun 2026 11:04:36 +0800 Subject: [PATCH 41/59] Move symbol hiding code to a new file --- .../rustc_codegen_ssa/src/back/archive.rs | 157 +----------------- compiler/rustc_codegen_ssa/src/back/mod.rs | 1 + .../rustc_codegen_ssa/src/back/symbol_edit.rs | 156 +++++++++++++++++ 3 files changed, 160 insertions(+), 154 deletions(-) create mode 100644 compiler/rustc_codegen_ssa/src/back/symbol_edit.rs diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index 66f9c7f8e15eb..b5d5893941ef2 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -1,18 +1,16 @@ +use std::env; use std::error::Error; use std::ffi::OsString; use std::fs::{self, File}; use std::io::{self, BufWriter, Write}; use std::path::{Path, PathBuf}; -use std::{env, mem}; use ar_archive_writer::{ ArchiveKind, COFFShortExport, MachineTypes, NewArchiveMember, write_archive_to_stream, }; pub use ar_archive_writer::{DEFAULT_OBJECT_READER, ObjectReader}; use object::read::archive::{ArchiveFile, ArchiveKind as ObjectArchiveKind}; -use object::read::elf::Sym as _; -use object::read::macho::{FatArch, Nlist}; -use object::{Endianness, elf, macho}; +use object::read::macho::FatArch; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_data_structures::memmap::Mmap; use rustc_fs_util::TempDirBuilder; @@ -24,6 +22,7 @@ use tracing::trace; use super::metadata::{create_compressed_metadata_file, search_for_section}; use super::rmeta_link; +use super::symbol_edit::apply_hide; use crate::common; // Public for ArchiveBuilderBuilder::extract_bundled_libs pub use crate::errors::ExtractBundledLibsError; @@ -671,153 +670,3 @@ impl<'a> ArArchiveBuilder<'a> { fn io_error_context(context: &str, err: io::Error) -> io::Error { io::Error::new(io::ErrorKind::Other, format!("{context}: {err}")) } - -// We use the `object` crate for the read-only pass over ELF/Mach-O object files -// because its `Sym`/`Nlist` traits provide clean access to symbol properties without -// manual byte parsing. However, `object` does not expose mutable views into the data, -// so we cannot use it to modify symbol fields in place. Instead, the read-only pass -// collects byte-level patches (offset + new value), and the write pass -// (`apply_patches`) applies them to a copy of the byte buffer without any ELF/Mach-O -// parsing — similar to how linker relocations work. - -/// A byte-level patch collected in the read-only pass and applied in the write pass. -struct Patch { - offset: usize, - value: u8, -} - -/// Apply a list of byte patches to `data`, returning the (possibly modified) bytes. -fn apply_patches(data: &[u8], patches: &[Patch]) -> Vec { - let mut buf = data.to_vec(); - for p in patches { - buf[p.offset] = p.value; - } - buf -} - -// --------------------------------------------------------------------------- -// ELF hide – read-only pass uses `object` crate, write pass uses `Patch` list -// --------------------------------------------------------------------------- - -fn elf_hide_patches_impl<'data, Elf: object::read::elf::FileHeader>( - data: &'data [u8], - st_other_offset: usize, - exported: &FxHashSet, -) -> Option> -where - u64: From, -{ - let header = Elf::parse(data).ok()?; - let endian = header.endian().ok()?; - let sections = header.sections(endian, data).ok()?; - let symtab = sections.symbols(endian, data, elf::SHT_SYMTAB).ok()?; - - let data_ptr = data.as_ptr() as usize; - let strings = symtab.strings(); - let mut patches = Vec::new(); - - for sym in symtab.iter() { - let binding = sym.st_bind(); - if binding != elf::STB_GLOBAL && binding != elf::STB_WEAK { - continue; - } - if sym.is_undefined(endian) { - continue; - } - let Ok(name_bytes) = sym.name(endian, strings) else { continue }; - let Ok(name) = str::from_utf8(name_bytes) else { continue }; - if !exported.contains(name) { - let sym_addr = sym as *const Elf::Sym as usize; - let offset = sym_addr - data_ptr + st_other_offset; - let new_vis = (sym.st_other() & !0x03) | elf::STV_HIDDEN; - patches.push(Patch { offset, value: new_vis }); - } - } - - Some(patches) -} - -// --------------------------------------------------------------------------- -// Mach-O hide – same architecture: read-only pass via `object`, write via patches -// --------------------------------------------------------------------------- - -fn macho_hide_patches_impl<'data, Mach: object::read::macho::MachHeader>( - data: &'data [u8], - n_type_offset: usize, - exported: &FxHashSet, -) -> Option> { - let header = Mach::parse(data, 0).ok()?; - let endian = header.endian().ok()?; - let mut commands = header.load_commands(endian, data, 0).ok()?; - - let symtab_cmd = loop { - let cmd = commands.next().ok()??; - if let Some(st) = cmd.symtab().ok().flatten() { - break st; - } - }; - let symtab: object::read::macho::SymbolTable<'_, Mach, &_> = - symtab_cmd.symbols(endian, data).ok()?; - - let data_ptr = data.as_ptr() as usize; - let strings = symtab.strings(); - let mut patches = Vec::new(); - - for nlist in symtab.iter() { - if nlist.is_stab() { - continue; - } - if nlist.is_undefined() { - continue; - } - if nlist.n_type() & macho::N_EXT == 0 { - continue; - } - let Ok(name_bytes) = nlist.name(endian, strings) else { continue }; - let Ok(name) = str::from_utf8(name_bytes) else { continue }; - let name = name.strip_prefix('_').unwrap_or(name); - if !exported.contains(name) { - let nlist_addr = nlist as *const Mach::Nlist as usize; - let offset = nlist_addr - data_ptr + n_type_offset; - patches.push(Patch { offset, value: nlist.n_type() | macho::N_PEXT }); - } - } - - Some(patches) -} - -// --------------------------------------------------------------------------- -// Unified dispatch: top-level detection via `object::File::parse` -// --------------------------------------------------------------------------- - -fn hide_patches(data: &[u8], exported: &FxHashSet) -> Option> { - let file = object::File::parse(data).ok()?; - match file { - object::File::Elf64(_) => elf_hide_patches_impl::>( - data, - mem::offset_of!(elf::Sym64, st_other), - exported, - ), - object::File::Elf32(_) => elf_hide_patches_impl::>( - data, - mem::offset_of!(elf::Sym32, st_other), - exported, - ), - object::File::MachO64(_) => macho_hide_patches_impl::>( - data, - mem::offset_of!(macho::Nlist64, n_type), - exported, - ), - object::File::MachO32(_) => macho_hide_patches_impl::>( - data, - mem::offset_of!(macho::Nlist32, n_type), - exported, - ), - _ => None, - } -} - -fn apply_hide(data: &[u8], exported: &FxHashSet) -> Vec { - let patches = hide_patches(data, exported).unwrap_or_default(); - apply_patches(data, &patches) -} diff --git a/compiler/rustc_codegen_ssa/src/back/mod.rs b/compiler/rustc_codegen_ssa/src/back/mod.rs index 17f6faa942c49..0f5050a9d7a9a 100644 --- a/compiler/rustc_codegen_ssa/src/back/mod.rs +++ b/compiler/rustc_codegen_ssa/src/back/mod.rs @@ -11,6 +11,7 @@ pub mod lto; pub mod metadata; pub mod rmeta_link; pub(crate) mod rpath; +mod symbol_edit; pub mod symbol_export; pub mod write; diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_edit.rs b/compiler/rustc_codegen_ssa/src/back/symbol_edit.rs new file mode 100644 index 0000000000000..19ecb3d92d209 --- /dev/null +++ b/compiler/rustc_codegen_ssa/src/back/symbol_edit.rs @@ -0,0 +1,156 @@ +// We use the `object` crate for the read-only pass over ELF/Mach-O object files +// because its `Sym`/`Nlist` traits provide clean access to symbol properties without +// manual byte parsing. However, `object` does not expose mutable views into the data, +// so we cannot use it to modify symbol fields in place. Instead, the read-only pass +// collects byte-level patches (offset + new value), and the write pass +// (`apply_patches`) applies them to a copy of the byte buffer without any ELF/Mach-O +// parsing — similar to how linker relocations work. + +use std::mem; + +use object::read::elf::Sym as _; +use object::read::macho::Nlist; +use object::{Endianness, elf, macho}; +use rustc_data_structures::fx::FxHashSet; + +/// A byte-level patch collected in the read-only pass and applied in the write pass. +struct Patch { + offset: usize, + value: u8, +} + +/// Apply a list of byte patches to `data`, returning the (possibly modified) bytes. +fn apply_patches(data: &[u8], patches: &[Patch]) -> Vec { + let mut buf = data.to_vec(); + for p in patches { + buf[p.offset] = p.value; + } + buf +} + +// --------------------------------------------------------------------------- +// ELF hide – read-only pass uses `object` crate, write pass uses `Patch` list +// --------------------------------------------------------------------------- + +fn elf_hide_patches_impl<'data, Elf: object::read::elf::FileHeader>( + data: &'data [u8], + st_other_offset: usize, + exported: &FxHashSet, +) -> Option> +where + u64: From, +{ + let header = Elf::parse(data).ok()?; + let endian = header.endian().ok()?; + let sections = header.sections(endian, data).ok()?; + let symtab = sections.symbols(endian, data, elf::SHT_SYMTAB).ok()?; + + let data_ptr = data.as_ptr() as usize; + let strings = symtab.strings(); + let mut patches = Vec::new(); + + for sym in symtab.iter() { + let binding = sym.st_bind(); + if binding != elf::STB_GLOBAL && binding != elf::STB_WEAK { + continue; + } + if sym.is_undefined(endian) { + continue; + } + let Ok(name_bytes) = sym.name(endian, strings) else { continue }; + let Ok(name) = str::from_utf8(name_bytes) else { continue }; + if !exported.contains(name) { + let sym_addr = sym as *const Elf::Sym as usize; + let offset = sym_addr - data_ptr + st_other_offset; + let new_vis = (sym.st_other() & !0x03) | elf::STV_HIDDEN; + patches.push(Patch { offset, value: new_vis }); + } + } + + Some(patches) +} + +// --------------------------------------------------------------------------- +// Mach-O hide – same architecture: read-only pass via `object`, write via patches +// --------------------------------------------------------------------------- + +fn macho_hide_patches_impl<'data, Mach: object::read::macho::MachHeader>( + data: &'data [u8], + n_type_offset: usize, + exported: &FxHashSet, +) -> Option> { + let header = Mach::parse(data, 0).ok()?; + let endian = header.endian().ok()?; + let mut commands = header.load_commands(endian, data, 0).ok()?; + + let symtab_cmd = loop { + let cmd = commands.next().ok()??; + if let Some(st) = cmd.symtab().ok().flatten() { + break st; + } + }; + let symtab: object::read::macho::SymbolTable<'_, Mach, &_> = + symtab_cmd.symbols(endian, data).ok()?; + + let data_ptr = data.as_ptr() as usize; + let strings = symtab.strings(); + let mut patches = Vec::new(); + + for nlist in symtab.iter() { + if nlist.is_stab() { + continue; + } + if nlist.is_undefined() { + continue; + } + if nlist.n_type() & macho::N_EXT == 0 { + continue; + } + let Ok(name_bytes) = nlist.name(endian, strings) else { continue }; + let Ok(name) = str::from_utf8(name_bytes) else { continue }; + let name = name.strip_prefix('_').unwrap_or(name); + if !exported.contains(name) { + let nlist_addr = nlist as *const Mach::Nlist as usize; + let offset = nlist_addr - data_ptr + n_type_offset; + patches.push(Patch { offset, value: nlist.n_type() | macho::N_PEXT }); + } + } + + Some(patches) +} + +// --------------------------------------------------------------------------- +// Unified dispatch: top-level detection via `object::File::parse` +// --------------------------------------------------------------------------- + +fn hide_patches(data: &[u8], exported: &FxHashSet) -> Option> { + let file = object::File::parse(data).ok()?; + match file { + object::File::Elf64(_) => elf_hide_patches_impl::>( + data, + mem::offset_of!(elf::Sym64, st_other), + exported, + ), + object::File::Elf32(_) => elf_hide_patches_impl::>( + data, + mem::offset_of!(elf::Sym32, st_other), + exported, + ), + object::File::MachO64(_) => macho_hide_patches_impl::>( + data, + mem::offset_of!(macho::Nlist64, n_type), + exported, + ), + object::File::MachO32(_) => macho_hide_patches_impl::>( + data, + mem::offset_of!(macho::Nlist32, n_type), + exported, + ), + _ => None, + } +} + +pub(super) fn apply_hide(data: &[u8], exported: &FxHashSet) -> Vec { + let patches = hide_patches(data, exported).unwrap_or_default(); + apply_patches(data, &patches) +} From 2a5673f060d51b2a9a847c1fec594683edeebe99 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 9 Jun 2026 17:31:40 +0200 Subject: [PATCH 42/59] Rename `rustc_expand/src/errors.rs` into `rustc_expand/src/diagnostics.rs` --- compiler/rustc_expand/src/base.rs | 8 ++++---- compiler/rustc_expand/src/config.rs | 4 ++-- .../src/{errors.rs => diagnostics.rs} | 0 compiler/rustc_expand/src/expand.rs | 6 +++--- compiler/rustc_expand/src/lib.rs | 2 +- compiler/rustc_expand/src/mbe/macro_check.rs | 20 +++++++++---------- compiler/rustc_expand/src/mbe/macro_rules.rs | 14 ++++++------- compiler/rustc_expand/src/mbe/metavar_expr.rs | 15 ++++++++------ compiler/rustc_expand/src/mbe/quoted.rs | 8 ++++---- compiler/rustc_expand/src/mbe/transcribe.rs | 2 +- compiler/rustc_expand/src/module.rs | 2 +- compiler/rustc_expand/src/proc_macro.rs | 18 +++++++++-------- 12 files changed, 52 insertions(+), 47 deletions(-) rename compiler/rustc_expand/src/{errors.rs => diagnostics.rs} (100%) diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 9f474fbeb7650..30a77811bb389 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -32,7 +32,7 @@ use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw}; use smallvec::{SmallVec, smallvec}; use thin_vec::ThinVec; -use crate::errors; +use crate::diagnostics; use crate::expand::{self, AstFragment, Invocation}; use crate::mbe::macro_rules::ParserAnyMacro; use crate::module::DirOwnership; @@ -954,7 +954,7 @@ impl SyntaxExtension { let stability = find_attr!(attrs, Stability { stability, .. } => *stability); if let Some(sp) = find_attr!(attrs, RustcBodyStability{ span, .. } => *span) { - sess.dcx().emit_err(errors::MacroBodyStability { + sess.dcx().emit_err(diagnostics::MacroBodyStability { span: sp, head_span: sess.source_map().guess_head_span(span), }); @@ -1358,7 +1358,7 @@ impl<'a> ExtCtxt<'a> { pub fn trace_macros_diag(&mut self) { for (span, notes) in self.expansions.iter() { - let mut db = self.dcx().create_note(errors::TraceMacro { span: *span }); + let mut db = self.dcx().create_note(diagnostics::TraceMacro { span: *span }); for note in notes { db.note(note.clone()); } @@ -1401,7 +1401,7 @@ pub fn resolve_path(sess: &Session, path: impl Into, span: Span) -> PRe let callsite = span.source_callsite(); let source_map = sess.source_map(); let Some(mut base_path) = source_map.span_to_filename(callsite).into_local_path() else { - return Err(sess.dcx().create_err(errors::ResolveRelativePath { + return Err(sess.dcx().create_err(diagnostics::ResolveRelativePath { span, path: source_map .filename_for_diagnostics(&source_map.span_to_filename(callsite)) diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 2b914a2664fe5..1289f8ed63af6 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -31,7 +31,7 @@ use rustc_session::errors::feature_err; use rustc_span::{STDLIB_STABLE_CRATES, Span, Symbol, sym}; use tracing::instrument; -use crate::errors::{ +use crate::diagnostics::{ CrateNameInCfgAttr, CrateTypeInCfgAttr, FeatureNotAllowed, FeatureRemoved, FeatureRemovedReason, InvalidCfg, RemoveExprNotSupported, }; @@ -282,7 +282,7 @@ impl<'a> StripUnconfigured<'a> { rustc_lint_defs::builtin::UNUSED_ATTRIBUTES, cfg_attr.span, ast::CRATE_NODE_ID, - crate::errors::CfgAttrNoAttributes, + crate::diagnostics::CfgAttrNoAttributes, ); } diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/diagnostics.rs similarity index 100% rename from compiler/rustc_expand/src/errors.rs rename to compiler/rustc_expand/src/diagnostics.rs diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index ac16dbc2fa387..c1cd0ef16c443 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -38,7 +38,7 @@ use smallvec::SmallVec; use crate::base::*; use crate::config::{StripUnconfigured, attr_into_trace}; -use crate::errors::{ +use crate::diagnostics::{ EmptyDelegationMac, GlobDelegationOutsideImpls, GlobDelegationTraitlessQpath, IncompleteParse, RecursionLimitReached, RemoveExprNotSupported, RemoveNodeNotSupported, UnsupportedKeyValue, WrongFragmentKind, @@ -2278,7 +2278,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { UNUSED_DOC_COMMENTS, current_span, self.cx.current_expansion.lint_node_id, - crate::errors::MacroCallUnusedDocComment { span: attr.span }, + crate::diagnostics::MacroCallUnusedDocComment { span: attr.span }, ); } else if rustc_attr_parsing::is_builtin_attr(attr) && !AttributeParser::is_parsed_attribute(&attr.path()) @@ -2288,7 +2288,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { UNUSED_ATTRIBUTES, attr.span, self.cx.current_expansion.lint_node_id, - crate::errors::UnusedBuiltinAttribute { + crate::diagnostics::UnusedBuiltinAttribute { attr_name, macro_name: pprust::path_to_string(&call.path), invoc_span: call.path.span, diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index 5068501a0e2d1..ec55f40b6c1e0 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -10,7 +10,7 @@ // tidy-alphabetical-end mod build; -mod errors; +mod diagnostics; mod mbe; mod placeholders; mod proc_macro_server; diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs index 0eae44a05e783..55645a5a66d04 100644 --- a/compiler/rustc_expand/src/mbe/macro_check.rs +++ b/compiler/rustc_expand/src/mbe/macro_check.rs @@ -114,7 +114,7 @@ use rustc_session::parse::ParseSess; use rustc_span::{ErrorGuaranteed, MacroRulesNormalizedIdent, Span, kw}; use smallvec::SmallVec; -use crate::errors; +use crate::diagnostics; use crate::mbe::{KleeneToken, TokenTree}; /// Stack represented as linked list. @@ -247,7 +247,7 @@ fn check_binders( psess, span, node_id, - errors::DuplicateMatcherBindingLint { span, prev: prev_info.span }, + diagnostics::DuplicateMatcherBindingLint { span, prev: prev_info.span }, ); } else if get_binder_info(macros, binders, name).is_none() { // 2. The meta-variable is free: This is a binder. @@ -266,11 +266,11 @@ fn check_binders( if let Some(prev_info) = get_binder_info(macros, binders, name) { // Duplicate binders at the top-level macro definition are errors. The lint is only // for nested macro definitions. - *guar = Some( - psess - .dcx() - .emit_err(errors::DuplicateMatcherBinding { span, prev: prev_info.span }), - ); + *guar = + Some(psess.dcx().emit_err(diagnostics::DuplicateMatcherBinding { + span, + prev: prev_info.span, + })); } else { binders.insert(name, BinderInfo { span, ops: ops.into() }); } @@ -578,7 +578,7 @@ fn check_ops_is_prefix( return; } } - buffer_lint(psess, span, node_id, errors::UnknownMacroVariable { name }); + buffer_lint(psess, span, node_id, diagnostics::UnknownMacroVariable { name }); } /// Returns whether `binder_ops` is a prefix of `occurrence_ops`. @@ -613,7 +613,7 @@ fn ops_is_prefix( psess, span, node_id, - errors::MetaVarStillRepeatingLint { label: binder.span, ident }, + diagnostics::MetaVarStillRepeatingLint { label: binder.span, ident }, ); return; } @@ -623,7 +623,7 @@ fn ops_is_prefix( psess, span, node_id, - errors::MetaVariableWrongOperator { + diagnostics::MetaVariableWrongOperator { binder: binder.span, occurrence: occurrence.span, }, diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 5bf50804ab1e8..1a1ef0f06963e 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -30,14 +30,14 @@ use rustc_span::hygiene::Transparency; use rustc_span::{Ident, Span, Symbol, kw, sym}; use tracing::{debug, instrument, trace, trace_span}; +use super::SequenceRepetition; use super::diagnostics::{FailedMacro, failed_to_match_macro}; use super::macro_parser::{NamedMatches, NamedParseResult}; -use super::{SequenceRepetition, diagnostics}; use crate::base::{ AttrProcMacro, BangProcMacro, DummyResult, ExpandResult, ExtCtxt, MacResult, MacroExpanderResult, SyntaxExtension, SyntaxExtensionKind, TTMacroExpander, }; -use crate::errors; +use crate::diagnostics; use crate::expand::{AstFragment, AstFragmentKind, ensure_complete_parse, parse_ast_fragment}; use crate::mbe::macro_check::check_meta_variables; use crate::mbe::macro_parser::{Error, ErrorReported, Failure, MatcherLoc, Success, TtParser}; @@ -81,7 +81,7 @@ impl<'a, 'b> ParserAnyMacro<'a, 'b> { let fragment = match parse_ast_fragment(parser, kind) { Ok(f) => f, Err(err) => { - let guar = diagnostics::emit_frag_parse_err( + let guar = super::diagnostics::emit_frag_parse_err( err, parser, snapshot, @@ -104,7 +104,7 @@ impl<'a, 'b> ParserAnyMacro<'a, 'b> { SEMICOLON_IN_EXPRESSIONS_FROM_MACROS, parser.token.span, lint_node_id, - errors::TrailingMacro { is_trailing: is_trailing_mac, name: macro_ident }, + diagnostics::TrailingMacro { is_trailing: is_trailing_mac, name: macro_ident }, ); } parser.bump(); @@ -903,9 +903,9 @@ fn check_args_parens(sess: &Session, rule_kw: Symbol, args: &tokenstream::TokenT if let tokenstream::TokenTree::Delimited(dspan, _, delim, _) = args && *delim != Delimiter::Parenthesis { - sess.dcx().emit_err(errors::MacroArgsBadDelim { + sess.dcx().emit_err(diagnostics::MacroArgsBadDelim { span: dspan.entire(), - sugg: errors::MacroArgsBadDelimSugg { open: dspan.open, close: dspan.close }, + sugg: diagnostics::MacroArgsBadDelimSugg { open: dspan.open, close: dspan.close }, rule_kw, }); } @@ -1539,7 +1539,7 @@ fn check_matcher_core<'tt>( RUST_2021_INCOMPATIBLE_OR_PATTERNS, span, ast::CRATE_NODE_ID, - errors::OrPatternsBackCompat { span, suggestion }, + diagnostics::OrPatternsBackCompat { span, suggestion }, ); } match is_in_follow(next_token, kind) { diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs index 70d796cda11c0..a02b84204cb39 100644 --- a/compiler/rustc_expand/src/mbe/metavar_expr.rs +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs @@ -7,7 +7,7 @@ use rustc_macros::{Decodable, Encodable}; use rustc_session::parse::ParseSess; use rustc_span::{Ident, Span, Symbol, sym}; -use crate::errors; +use crate::diagnostics; pub(crate) const RAW_IDENT_ERR: &str = "`${concat(..)}` currently does not support raw identifiers"; pub(crate) const UNSUPPORTED_CONCAT_ELEM_ERR: &str = "expected identifier or string literal"; @@ -51,15 +51,18 @@ impl MetaVarExpr { Some(tt) => (Some(tt.span()), None), None => (None, Some(ident.span.shrink_to_hi())), }; - let err = - errors::MveMissingParen { ident_span: ident.span, unexpected_span, insert_span }; + let err = diagnostics::MveMissingParen { + ident_span: ident.span, + unexpected_span, + insert_span, + }; return Err(psess.dcx().create_err(err)); }; // Ensure there are no trailing tokens in the braces, e.g. `${foo() extra}` if iter.peek().is_some() { let span = iter_span(&iter).expect("checked is_some above"); - let err = errors::MveExtraTokens { + let err = diagnostics::MveExtraTokens { span, ident_span: ident.span, extra_count: iter.count(), @@ -79,7 +82,7 @@ impl MetaVarExpr { sym::index => MetaVarExpr::Index(parse_depth(&mut iter, psess, ident.span)?), sym::len => MetaVarExpr::Len(parse_depth(&mut iter, psess, ident.span)?), _ => { - let err = errors::MveUnrecognizedExpr { + let err = diagnostics::MveUnrecognizedExpr { span: ident.span, valid_expr_list: "`count`, `ignore`, `index`, `len`, and `concat`", }; @@ -129,7 +132,7 @@ fn check_trailing_tokens<'psess>( other => unreachable!("unknown MVEs should be rejected earlier (got `{other}`)"), }; - let err = errors::MveExtraTokens { + let err = diagnostics::MveExtraTokens { span: iter_span(iter).expect("checked is_none above"), ident_span: ident.span, extra_count: iter.count(), diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index 443a17287d734..3e82a61067af4 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -9,7 +9,7 @@ use rustc_session::errors::feature_err; use rustc_span::edition::Edition; use rustc_span::{Ident, Span, kw, sym}; -use crate::errors; +use crate::diagnostics; use crate::mbe::macro_parser::count_metavar_decls; use crate::mbe::{Delimited, KleeneOp, KleeneToken, MetaVarExpr, SequenceRepetition, TokenTree}; @@ -94,7 +94,7 @@ fn parse( // Emit a missing-fragment diagnostic and return a `TokenTree` fallback so parsing can // continue. let missing_fragment_specifier = |span, add_span| { - sess.dcx().emit_err(errors::MissingFragmentSpecifier { + sess.dcx().emit_err(diagnostics::MissingFragmentSpecifier { span, add_span, valid: VALID_FRAGMENT_NAMES_MSG, @@ -163,7 +163,7 @@ fn parse( if !span.from_expansion() { edition } else { span.edition() } }; let kind = NonterminalKind::from_symbol(fragment.name, edition).unwrap_or_else(|| { - sess.dcx().emit_err(errors::InvalidFragmentSpecifier { + sess.dcx().emit_err(diagnostics::InvalidFragmentSpecifier { span, fragment, help: VALID_FRAGMENT_NAMES_MSG, @@ -299,7 +299,7 @@ fn parse_tree<'a>( _ => { let token = pprust::token_kind_to_string(&delim.as_open_token_kind()); - sess.dcx().emit_err(errors::ExpectedParenOrBrace { + sess.dcx().emit_err(diagnostics::ExpectedParenOrBrace { span: delim_span.entire(), token, }); diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index c56c5569f9a5b..34d5147606e90 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -17,7 +17,7 @@ use rustc_span::{ }; use smallvec::{SmallVec, smallvec}; -use crate::errors::{ +use crate::diagnostics::{ ConcatInvalidIdent, CountRepetitionMisplaced, InvalidIdentReason, MacroVarStillRepeating, MetaVarsDifSeqMatchers, MustRepeatOnce, MveUnrecognizedVar, NoRepeatableVar, NoSyntaxVarsExprRepeat, VarNoTypo, VarTypoSuggestionRepeatable, VarTypoSuggestionUnrepeatable, diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index d4bda53ece04b..febe5e16cf446 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -14,7 +14,7 @@ use rustc_span::{Ident, Span, sym}; use thin_vec::ThinVec; use crate::base::ModuleData; -use crate::errors::{ +use crate::diagnostics::{ ModuleCircular, ModuleFileNotFound, ModuleInBlock, ModuleInBlockName, ModuleMultipleCandidates, }; diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs index 2deba79a775a6..105d2d796aa80 100644 --- a/compiler/rustc_expand/src/proc_macro.rs +++ b/compiler/rustc_expand/src/proc_macro.rs @@ -11,7 +11,7 @@ use rustc_span::profiling::SpannedEventArgRecorder; use rustc_span::{LocalExpnId, Span}; use crate::base::{self, *}; -use crate::{errors, proc_macro_server}; +use crate::{diagnostics, proc_macro_server}; fn exec_strategy(sess: &Session) -> impl pm::bridge::server::ExecutionStrategy + 'static { pm::bridge::server::MaybeCrossThread { @@ -47,9 +47,11 @@ impl base::BangProcMacro for BangProcMacro { let strategy = exec_strategy(ecx.sess); let server = proc_macro_server::Rustc::new(ecx); self.client.run1(&strategy, server, input, proc_macro_backtrace).map_err(|e| { - ecx.dcx().emit_err(errors::ProcMacroPanicked { + ecx.dcx().emit_err(diagnostics::ProcMacroPanicked { span, - message: e.into_string().map(|message| errors::ProcMacroPanickedHelp { message }), + message: e + .into_string() + .map(|message| diagnostics::ProcMacroPanickedHelp { message }), }) }) } @@ -74,11 +76,11 @@ impl base::AttrProcMacro for AttrProcMacro { let server = proc_macro_server::Rustc::new(ecx); self.client.run2(&strategy, server, annotation, annotated, proc_macro_backtrace).map_err( |e| { - ecx.dcx().emit_err(errors::CustomAttributePanicked { + ecx.dcx().emit_err(diagnostics::CustomAttributePanicked { span, message: e .into_string() - .map(|message| errors::CustomAttributePanickedHelp { message }), + .map(|message| diagnostics::CustomAttributePanickedHelp { message }), }) }, ) @@ -154,7 +156,7 @@ impl MultiItemModifier for DeriveProcMacro { // fail if there have been errors emitted if ecx.dcx().err_count() > error_count_before { - ecx.dcx().emit_err(errors::ProcMacroDeriveTokens { span }); + ecx.dcx().emit_err(diagnostics::ProcMacroDeriveTokens { span }); } ExpandResult::Ready(items) @@ -202,11 +204,11 @@ fn expand_derive_macro( let invoc_expn_data = invoc_id.expn_data(); let span = invoc_expn_data.call_site; ecx.dcx().emit_err({ - errors::ProcMacroDerivePanicked { + diagnostics::ProcMacroDerivePanicked { span, message: e .into_string() - .map(|message| errors::ProcMacroDerivePanickedHelp { message }), + .map(|message| diagnostics::ProcMacroDerivePanickedHelp { message }), } }); Err(()) From 96eb195f9f4cc131e5419480d5915a4e92811dad Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 9 Jun 2026 17:35:55 +0200 Subject: [PATCH 43/59] Rename `rustc_metadata/src/errors.rs` into `rustc_metadata/src/diagnostics.rs` --- compiler/rustc_metadata/src/creader.rs | 48 +++++++++------- .../rustc_metadata/src/dependency_format.rs | 2 +- .../src/{errors.rs => diagnostics.rs} | 0 compiler/rustc_metadata/src/fs.rs | 2 +- compiler/rustc_metadata/src/lib.rs | 2 +- compiler/rustc_metadata/src/locator.rs | 57 +++++++++++++------ compiler/rustc_metadata/src/native_libs.rs | 31 +++++----- compiler/rustc_metadata/src/rmeta/encoder.rs | 2 +- 8 files changed, 87 insertions(+), 57 deletions(-) rename compiler/rustc_metadata/src/{errors.rs => diagnostics.rs} (100%) diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index d18764bc6814a..cb3d1b6d67487 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -39,7 +39,7 @@ use rustc_span::{DUMMY_SP, Ident, Span, Symbol, sym}; use rustc_target::spec::{PanicStrategy, Target}; use tracing::{debug, info, trace}; -use crate::errors; +use crate::diagnostics; use crate::locator::{CrateError, CrateLocator, CratePaths, CrateRejections}; use crate::rmeta::{ CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob, TargetModifiers, @@ -365,7 +365,7 @@ impl CStore { match (flag_local_value, flag_extern_value) { (Some(local_value), Some(extern_value)) => { - tcx.dcx().emit_err(errors::IncompatibleTargetModifiers { + tcx.dcx().emit_err(diagnostics::IncompatibleTargetModifiers { span, extern_crate, local_crate, @@ -376,7 +376,7 @@ impl CStore { }) } (None, Some(extern_value)) => { - tcx.dcx().emit_err(errors::IncompatibleTargetModifiersLMissed { + tcx.dcx().emit_err(diagnostics::IncompatibleTargetModifiersLMissed { span, extern_crate, local_crate, @@ -386,7 +386,7 @@ impl CStore { }) } (Some(local_value), None) => { - tcx.dcx().emit_err(errors::IncompatibleTargetModifiersRMissed { + tcx.dcx().emit_err(diagnostics::IncompatibleTargetModifiersRMissed { span, extern_crate, local_crate, @@ -458,7 +458,7 @@ impl CStore { pub fn report_incompatible_target_modifiers(&self, tcx: TyCtxt<'_>, krate: &Crate) { for flag_name in &tcx.sess.opts.cg.unsafe_allow_abi_mismatch { if !OptionsTargetModifiers::is_target_modifier(flag_name) { - tcx.dcx().emit_err(errors::UnknownTargetModifierUnsafeAllowed { + tcx.dcx().emit_err(diagnostics::UnknownTargetModifierUnsafeAllowed { span: krate.spans.inner_span.shrink_to_lo(), flag_name: flag_name.clone(), }); @@ -502,7 +502,7 @@ impl CStore { } *errors += 1; - tcx.dcx().emit_err(errors::MitigationLessStrictInDependency { + tcx.dcx().emit_err(diagnostics::MitigationLessStrictInDependency { span: krate.spans.inner_span.shrink_to_lo(), mitigation_name: my_mitigation.kind.to_string(), mitigation_level: my_mitigation.level.level_str().to_string(), @@ -525,7 +525,7 @@ impl CStore { if data.has_async_drops() { let extern_crate = data.name(); let local_crate = tcx.crate_name(LOCAL_CRATE); - tcx.dcx().emit_warn(errors::AsyncDropTypesInDependency { + tcx.dcx().emit_warn(diagnostics::AsyncDropTypesInDependency { span: krate.spans.inner_span.shrink_to_lo(), extern_crate, local_crate, @@ -1034,11 +1034,13 @@ impl CStore { // Sanity check the loaded crate to ensure it is indeed a panic runtime // and the panic strategy is indeed what we thought it was. if !cdata.is_panic_runtime() { - tcx.dcx().emit_err(errors::CrateNotPanicRuntime { crate_name: name }); + tcx.dcx().emit_err(diagnostics::CrateNotPanicRuntime { crate_name: name }); } if cdata.required_panic_strategy() != Some(desired_strategy) { - tcx.dcx() - .emit_err(errors::NoPanicStrategy { crate_name: name, strategy: desired_strategy }); + tcx.dcx().emit_err(diagnostics::NoPanicStrategy { + crate_name: name, + strategy: desired_strategy, + }); } self.injected_panic_runtime = Some(cnum); @@ -1074,7 +1076,7 @@ impl CStore { // Sanity check the loaded crate to ensure it is indeed a profiler runtime if !cdata.is_profiler_runtime() { - tcx.dcx().emit_err(errors::NotProfilerRuntime { crate_name: name }); + tcx.dcx().emit_err(diagnostics::NotProfilerRuntime { crate_name: name }); } } @@ -1082,8 +1084,10 @@ impl CStore { self.has_global_allocator = match &*fn_spans(krate, Symbol::intern(&global_fn_name(sym::alloc))) { [span1, span2, ..] => { - tcx.dcx() - .emit_err(errors::NoMultipleGlobalAlloc { span2: *span2, span1: *span1 }); + tcx.dcx().emit_err(diagnostics::NoMultipleGlobalAlloc { + span2: *span2, + span1: *span1, + }); true } spans => !spans.is_empty(), @@ -1091,8 +1095,10 @@ impl CStore { let alloc_error_handler = Symbol::intern(&global_fn_name(ALLOC_ERROR_HANDLER)); self.has_alloc_error_handler = match &*fn_spans(krate, alloc_error_handler) { [span1, span2, ..] => { - tcx.dcx() - .emit_err(errors::NoMultipleAllocErrorHandler { span2: *span2, span1: *span1 }); + tcx.dcx().emit_err(diagnostics::NoMultipleAllocErrorHandler { + span2: *span2, + span1: *span1, + }); true } spans => !spans.is_empty(), @@ -1130,7 +1136,7 @@ impl CStore { if data.has_global_allocator() { match global_allocator { Some(other_crate) => { - tcx.dcx().emit_err(errors::ConflictingGlobalAlloc { + tcx.dcx().emit_err(diagnostics::ConflictingGlobalAlloc { crate_name: data.name(), other_crate_name: other_crate, }); @@ -1144,7 +1150,7 @@ impl CStore { if data.has_alloc_error_handler() { match alloc_error_handler { Some(other_crate) => { - tcx.dcx().emit_err(errors::ConflictingAllocErrorHandler { + tcx.dcx().emit_err(diagnostics::ConflictingAllocErrorHandler { crate_name: data.name(), other_crate_name: other_crate, }); @@ -1164,7 +1170,7 @@ impl CStore { if !attr::contains_name(&krate.attrs, sym::default_lib_allocator) && !self.iter_crate_data().any(|(_, data)| data.has_default_lib_allocator()) { - tcx.dcx().emit_err(errors::GlobalAllocRequired); + tcx.dcx().emit_err(diagnostics::GlobalAllocRequired); } self.allocator_kind = Some(AllocatorKind::Default); } @@ -1229,7 +1235,7 @@ impl CStore { // Sanity check that the loaded crate is `#![compiler_builtins]` let cdata = self.get_crate_data(cnum); if !cdata.is_compiler_builtins() { - tcx.dcx().emit_err(errors::CrateNotCompilerBuiltins { crate_name: cdata.name() }); + tcx.dcx().emit_err(diagnostics::CrateNotCompilerBuiltins { crate_name: cdata.name() }); } } @@ -1261,7 +1267,7 @@ impl CStore { lint::builtin::UNUSED_CRATE_DEPENDENCIES, span, ast::CRATE_NODE_ID, - errors::UnusedCrateDependency { + diagnostics::UnusedCrateDependency { extern_crate: name_interned, local_crate: tcx.crate_name(LOCAL_CRATE), }, @@ -1298,7 +1304,7 @@ impl CStore { // Make a point span rather than covering the whole file let span = krate.spans.inner_span.shrink_to_lo(); - tcx.sess.dcx().emit_err(errors::WasmCAbi { span }); + tcx.sess.dcx().emit_err(diagnostics::WasmCAbi { span }); } } diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs index 673a7444f90c0..257b2a9b03884 100644 --- a/compiler/rustc_metadata/src/dependency_format.rs +++ b/compiler/rustc_metadata/src/dependency_format.rs @@ -65,7 +65,7 @@ use rustc_target::spec::PanicStrategy; use tracing::info; use crate::creader::CStore; -use crate::errors::{ +use crate::diagnostics::{ BadPanicStrategy, CrateDepMultiple, IncompatiblePanicInDropStrategy, IncompatibleWithImmediateAbort, IncompatibleWithImmediateAbortCore, LibRequired, NonStaticCrateDep, RequiredPanicStrategy, RlibRequired, RustcLibRequired, TwoPanicRuntimes, diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/diagnostics.rs similarity index 100% rename from compiler/rustc_metadata/src/errors.rs rename to compiler/rustc_metadata/src/diagnostics.rs diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs index 1eaad26ff8e80..5759b4afada7e 100644 --- a/compiler/rustc_metadata/src/fs.rs +++ b/compiler/rustc_metadata/src/fs.rs @@ -8,7 +8,7 @@ use rustc_session::Session; use rustc_session::config::{CrateType, OutFileName, OutputType}; use rustc_session::output::filename_for_metadata; -use crate::errors::{ +use crate::diagnostics::{ BinaryOutputToTty, FailedCopyToStdout, FailedCreateEncodedMetadata, FailedCreateFile, FailedCreateTempdir, FailedWriteError, }; diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index ebaff2a2d8f97..51c56d777a751 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -21,7 +21,7 @@ mod native_libs; mod rmeta; pub mod creader; -pub mod errors; +pub mod diagnostics; pub mod fs; pub mod locator; diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index e8b78fdbea3ff..321274243a857 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -235,7 +235,7 @@ use tempfile::Builder as TempFileBuilder; use tracing::{debug, info}; use crate::creader::{Library, MetadataLoader}; -use crate::errors; +use crate::diagnostics; use crate::rmeta::{METADATA_HEADER, MetadataBlob, ProcMacroKind, rustc_version}; #[derive(Clone)] @@ -1070,28 +1070,45 @@ impl CrateError { let dcx = sess.dcx(); match self { CrateError::NonAsciiName(crate_name) => { - dcx.emit_err(errors::NonAsciiName { span, crate_name }); + dcx.emit_err(diagnostics::NonAsciiName { span, crate_name }); } CrateError::ExternLocationNotExist(crate_name, loc) => { - dcx.emit_err(errors::ExternLocationNotExist { span, crate_name, location: &loc }); + dcx.emit_err(diagnostics::ExternLocationNotExist { + span, + crate_name, + location: &loc, + }); } CrateError::ExternLocationNotFile(crate_name, loc) => { - dcx.emit_err(errors::ExternLocationNotFile { span, crate_name, location: &loc }); + dcx.emit_err(diagnostics::ExternLocationNotFile { + span, + crate_name, + location: &loc, + }); } CrateError::MultipleCandidates(crate_name, flavor, candidates) => { - dcx.emit_err(errors::MultipleCandidates { span, crate_name, flavor, candidates }); + dcx.emit_err(diagnostics::MultipleCandidates { + span, + crate_name, + flavor, + candidates, + }); } CrateError::FullMetadataNotFound(crate_name, flavor) => { - dcx.emit_err(errors::FullMetadataNotFound { span, crate_name, flavor }); + dcx.emit_err(diagnostics::FullMetadataNotFound { span, crate_name, flavor }); } CrateError::SymbolConflictsCurrent(root_name) => { - dcx.emit_err(errors::SymbolConflictsCurrent { span, crate_name: root_name }); + dcx.emit_err(diagnostics::SymbolConflictsCurrent { span, crate_name: root_name }); } CrateError::StableCrateIdCollision(crate_name0, crate_name1) => { - dcx.emit_err(errors::StableCrateIdCollision { span, crate_name0, crate_name1 }); + dcx.emit_err(diagnostics::StableCrateIdCollision { + span, + crate_name0, + crate_name1, + }); } CrateError::DlOpen(path, err) | CrateError::DlSym(path, err) => { - dcx.emit_err(errors::DlError { span, path, err }); + dcx.emit_err(diagnostics::DlError { span, path, err }); } CrateError::LocatorCombined(locator) => { let crate_name = locator.crate_name; @@ -1102,8 +1119,12 @@ impl CrateError { if !locator.crate_rejections.via_filename.is_empty() { let mismatches = locator.crate_rejections.via_filename.iter(); for CrateMismatch { path, .. } in mismatches { - dcx.emit_err(errors::CrateLocationUnknownType { span, path, crate_name }); - dcx.emit_err(errors::LibFilenameForm { + dcx.emit_err(diagnostics::CrateLocationUnknownType { + span, + path, + crate_name, + }); + dcx.emit_err(diagnostics::LibFilenameForm { span, dll_prefix: &locator.dll_prefix, dll_suffix: &locator.dll_suffix, @@ -1129,7 +1150,7 @@ impl CrateError { )); } } - dcx.emit_err(errors::NewerCrateVersion { + dcx.emit_err(diagnostics::NewerCrateVersion { span, crate_name, add_info, @@ -1145,7 +1166,7 @@ impl CrateError { path.display(), )); } - dcx.emit_err(errors::NoCrateWithTriple { + dcx.emit_err(diagnostics::NoCrateWithTriple { span, crate_name, locator_triple: locator.triple.tuple(), @@ -1161,7 +1182,7 @@ impl CrateError { path.display() )); } - dcx.emit_err(errors::FoundStaticlib { + dcx.emit_err(diagnostics::FoundStaticlib { span, crate_name, add_info, @@ -1177,7 +1198,7 @@ impl CrateError { path.display(), )); } - dcx.emit_err(errors::IncompatibleRustc { + dcx.emit_err(diagnostics::IncompatibleRustc { span, crate_name, add_info, @@ -1189,14 +1210,14 @@ impl CrateError { for CrateMismatch { path: _, got } in locator.crate_rejections.via_invalid { crate_rejections.push(got); } - dcx.emit_err(errors::InvalidMetadataFiles { + dcx.emit_err(diagnostics::InvalidMetadataFiles { span, crate_name, add_info, crate_rejections, }); } else { - let error = errors::CannotFindCrate { + let error = diagnostics::CannotFindCrate { span, crate_name, add_info, @@ -1222,7 +1243,7 @@ impl CrateError { } } CrateError::NotFound(crate_name) => { - let error = errors::CannotFindCrate { + let error = diagnostics::CannotFindCrate { span, crate_name, add_info: String::new(), diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index bfe7e01dc85e7..e467cf9bf105b 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -21,7 +21,7 @@ use rustc_span::Symbol; use rustc_span::def_id::{DefId, LOCAL_CRATE}; use rustc_target::spec::{Arch, BinaryFormat, CfgAbi, Env, LinkSelfContainedComponents, Os}; -use crate::errors; +use crate::diagnostics; /// The fallback directories are passed to linker, but not used when rustc does the search, /// because in the latter case the set of fallback directories cannot always be determined @@ -163,8 +163,9 @@ pub fn try_find_native_dynamic_library( } pub fn find_native_static_library(name: &str, verbatim: bool, sess: &Session) -> PathBuf { - try_find_native_static_library(sess, name, verbatim) - .unwrap_or_else(|| sess.dcx().emit_fatal(errors::MissingNativeLibrary::new(name, verbatim))) + try_find_native_static_library(sess, name, verbatim).unwrap_or_else(|| { + sess.dcx().emit_fatal(diagnostics::MissingNativeLibrary::new(name, verbatim)) + }) } fn find_bundled_library( @@ -241,7 +242,7 @@ impl<'tcx> Collector<'tcx> { if let Some(span) = find_attr!(self.tcx, child_item, LinkOrdinal {span, ..} => *span) { - sess.dcx().emit_err(errors::LinkOrdinalRawDylib { span }); + sess.dcx().emit_err(diagnostics::LinkOrdinalRawDylib { span }); } } @@ -277,16 +278,18 @@ impl<'tcx> Collector<'tcx> { && !self.tcx.sess.target.is_like_darwin { // Cannot check this when parsing options because the target is not yet available. - self.tcx.dcx().emit_err(errors::LibFrameworkApple); + self.tcx.dcx().emit_err(diagnostics::LibFrameworkApple); } if let Some(ref new_name) = lib.new_name { let any_duplicate = self.libs.iter().any(|n| n.name.as_str() == lib.name); if new_name.is_empty() { - self.tcx.dcx().emit_err(errors::EmptyRenamingTarget { lib_name: &lib.name }); + self.tcx + .dcx() + .emit_err(diagnostics::EmptyRenamingTarget { lib_name: &lib.name }); } else if !any_duplicate { - self.tcx.dcx().emit_err(errors::RenamingNoLink { lib_name: &lib.name }); + self.tcx.dcx().emit_err(diagnostics::RenamingNoLink { lib_name: &lib.name }); } else if !renames.insert(&lib.name) { - self.tcx.dcx().emit_err(errors::MultipleRenamings { lib_name: &lib.name }); + self.tcx.dcx().emit_err(diagnostics::MultipleRenamings { lib_name: &lib.name }); } } } @@ -312,14 +315,14 @@ impl<'tcx> Collector<'tcx> { if lib.has_modifiers() || passed_lib.has_modifiers() { match lib.foreign_module { Some(def_id) => { - self.tcx.dcx().emit_err(errors::NoLinkModOverride { + self.tcx.dcx().emit_err(diagnostics::NoLinkModOverride { span: Some(self.tcx.def_span(def_id)), }) } None => self .tcx .dcx() - .emit_err(errors::NoLinkModOverride { span: None }), + .emit_err(diagnostics::NoLinkModOverride { span: None }), }; } if passed_lib.kind != NativeLibKind::Unspecified { @@ -434,7 +437,7 @@ impl<'tcx> Collector<'tcx> { DllCallingConvention::Vectorcall(self.i686_arg_list_size(item)) } _ => { - self.tcx.dcx().emit_fatal(errors::RawDylibUnsupportedAbi { span }); + self.tcx.dcx().emit_fatal(diagnostics::RawDylibUnsupportedAbi { span }); } } } else { @@ -443,7 +446,7 @@ impl<'tcx> Collector<'tcx> { DllCallingConvention::C } _ => { - self.tcx.dcx().emit_fatal(errors::RawDylibUnsupportedAbi { span }); + self.tcx.dcx().emit_fatal(diagnostics::RawDylibUnsupportedAbi { span }); } } }; @@ -458,11 +461,11 @@ impl<'tcx> Collector<'tcx> { if self.tcx.sess.target.binary_format == BinaryFormat::Elf { let name = name.as_str(); if name.contains('\0') { - self.tcx.dcx().emit_err(errors::RawDylibMalformed { span }); + self.tcx.dcx().emit_err(diagnostics::RawDylibMalformed { span }); } else if let Some((left, right)) = name.split_once('@') && (left.is_empty() || right.is_empty() || right.contains('@')) { - self.tcx.dcx().emit_err(errors::RawDylibMalformed { span }); + self.tcx.dcx().emit_err(diagnostics::RawDylibMalformed { span }); } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 6219c23a0c6ab..915cfb970550b 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -35,8 +35,8 @@ use rustc_span::{ }; use tracing::{debug, instrument, trace}; +use crate::diagnostics::{FailCreateFileEncoder, FailWriteFile}; use crate::eii::EiiMapEncodedKeyValue; -use crate::errors::{FailCreateFileEncoder, FailWriteFile}; use crate::rmeta::*; pub(super) struct EncodeContext<'a, 'tcx> { From 32a2f0cdaa32635194db3c6f9c7afa26fa34fdb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 10 Jun 2026 11:59:20 +0200 Subject: [PATCH 44/59] Add more tests that exercise the well-formedness checking of lazy type aliases --- tests/ui/lazy-type-alias/def-site-body-wf.rs | 19 +++++++ .../lazy-type-alias/def-site-body-wf.stderr | 54 +++++++++++++++++++ .../unsatisfied-bounds-type-alias-body.rs | 8 --- .../unsatisfied-bounds-type-alias-body.stderr | 14 ----- tests/ui/lazy-type-alias/use-site-wf.rs | 16 ++++++ tests/ui/lazy-type-alias/use-site-wf.stderr | 50 +++++++++++++++++ 6 files changed, 139 insertions(+), 22 deletions(-) create mode 100644 tests/ui/lazy-type-alias/def-site-body-wf.rs create mode 100644 tests/ui/lazy-type-alias/def-site-body-wf.stderr delete mode 100644 tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.rs delete mode 100644 tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.stderr create mode 100644 tests/ui/lazy-type-alias/use-site-wf.rs create mode 100644 tests/ui/lazy-type-alias/use-site-wf.stderr diff --git a/tests/ui/lazy-type-alias/def-site-body-wf.rs b/tests/ui/lazy-type-alias/def-site-body-wf.rs new file mode 100644 index 0000000000000..9287cb461195a --- /dev/null +++ b/tests/ui/lazy-type-alias/def-site-body-wf.rs @@ -0,0 +1,19 @@ +// Test that we check the body at the definition site for well-formedness. +// Compare with `tests/ui/type-alias/lack-of-wfcheck.rs`. + +#![feature(lazy_type_alias)] + +// unsatisified trait bounds +type _A = ::Output; //~ ERROR cannot multiply `T` by `T` +type _B = Vec; //~ ERROR the size for values of type `str` cannot be known at compilation time + +// unsatisfied outlives-bounds +type _C<'a> = &'static &'a (); //~ ERROR reference has a longer lifetime than the data it references + +// diverging const exprs +type _D = [(); panic!()]; //~ ERROR evaluation panicked + +// dyn incompatibility +type _E = dyn Sized; //~ ERROR the trait `Sized` is not dyn compatible + +fn main() {} diff --git a/tests/ui/lazy-type-alias/def-site-body-wf.stderr b/tests/ui/lazy-type-alias/def-site-body-wf.stderr new file mode 100644 index 0000000000000..99ebc95616816 --- /dev/null +++ b/tests/ui/lazy-type-alias/def-site-body-wf.stderr @@ -0,0 +1,54 @@ +error[E0277]: cannot multiply `T` by `T` + --> $DIR/def-site-body-wf.rs:7:14 + | +LL | type _A = ::Output; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `T * T` + | +help: consider restricting type parameter `T` with trait `Mul` + | +LL | type _A = ::Output; + | +++++++++++++++ + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/def-site-body-wf.rs:8:11 + | +LL | type _B = Vec; + | ^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` +note: required by an implicit `Sized` bound in `Vec` + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + +error[E0491]: in type `&'static &'a ()`, reference has a longer lifetime than the data it references + --> $DIR/def-site-body-wf.rs:11:1 + | +LL | type _C<'a> = &'static &'a (); + | ^^^^^^^^^^^ + | + = note: the pointer is valid for the static lifetime +note: but the referenced data is only valid for the lifetime `'a` as defined here + --> $DIR/def-site-body-wf.rs:11:9 + | +LL | type _C<'a> = &'static &'a (); + | ^^ + +error[E0080]: evaluation panicked: explicit panic + --> $DIR/def-site-body-wf.rs:14:16 + | +LL | type _D = [(); panic!()]; + | ^^^^^^^^ evaluation of `_D::{constant#0}` failed here + +error[E0038]: the trait `Sized` is not dyn compatible + --> $DIR/def-site-body-wf.rs:17:11 + | +LL | type _E = dyn Sized; + | ^^^^^^^^^ `Sized` is not dyn compatible + | + = note: the trait is not dyn compatible because it requires `Self: Sized` + = note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0038, E0080, E0277, E0491. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.rs b/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.rs deleted file mode 100644 index c798e4e436824..0000000000000 --- a/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.rs +++ /dev/null @@ -1,8 +0,0 @@ -// Test that we check lazy type aliases for well-formedness. - -#![feature(lazy_type_alias)] -#![allow(incomplete_features)] - -type Alias = ::Output; //~ ERROR cannot multiply `T` by `T` - -fn main() {} diff --git a/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.stderr b/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.stderr deleted file mode 100644 index d0d4d04e28a38..0000000000000 --- a/tests/ui/lazy-type-alias/unsatisfied-bounds-type-alias-body.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0277]: cannot multiply `T` by `T` - --> $DIR/unsatisfied-bounds-type-alias-body.rs:6:17 - | -LL | type Alias = ::Output; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `T * T` - | -help: consider restricting type parameter `T` with trait `Mul` - | -LL | type Alias = ::Output; - | +++++++++++++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/lazy-type-alias/use-site-wf.rs b/tests/ui/lazy-type-alias/use-site-wf.rs new file mode 100644 index 0000000000000..a44ff3e3493d7 --- /dev/null +++ b/tests/ui/lazy-type-alias/use-site-wf.rs @@ -0,0 +1,16 @@ +// Test that we check usage sites of lazy type aliases, aka free alias types, for well-formedness. +// We check trailing where-clauses separately in `trailing-where-clause.rs`. + +#![feature(lazy_type_alias)] + +type B = T; + +fn b(_: B) {} +//~^ ERROR the trait bound `X: Copy` is not satisfied +//~| ERROR the trait bound `X: Copy` is not satisfied + +type A<'a: 'static> = &'a (); + +fn a<'r>(_: A<'r>) {} //~ ERROR lifetime bound not satisfied + +fn main() {} diff --git a/tests/ui/lazy-type-alias/use-site-wf.stderr b/tests/ui/lazy-type-alias/use-site-wf.stderr new file mode 100644 index 0000000000000..b473a2db055e4 --- /dev/null +++ b/tests/ui/lazy-type-alias/use-site-wf.stderr @@ -0,0 +1,50 @@ +error[E0277]: the trait bound `X: Copy` is not satisfied + --> $DIR/use-site-wf.rs:8:12 + | +LL | fn b(_: B) {} + | ^^^^ the trait `Copy` is not implemented for `X` + | +note: required by a bound on the type alias `B` + --> $DIR/use-site-wf.rs:6:11 + | +LL | type B = T; + | ^^^^ required by this bound +help: consider restricting type parameter `X` with trait `Copy` + | +LL | fn b(_: B) {} + | +++++++++++++++++++ + +error[E0478]: lifetime bound not satisfied + --> $DIR/use-site-wf.rs:14:13 + | +LL | fn a<'r>(_: A<'r>) {} + | ^^^^^ + | +note: lifetime parameter instantiated with the lifetime `'r` as defined here + --> $DIR/use-site-wf.rs:14:6 + | +LL | fn a<'r>(_: A<'r>) {} + | ^^ + = note: but lifetime parameter must outlive the static lifetime + +error[E0277]: the trait bound `X: Copy` is not satisfied + --> $DIR/use-site-wf.rs:8:12 + | +LL | fn b(_: B) {} + | ^^^^ the trait `Copy` is not implemented for `X` + | +note: required by a bound on the type alias `B` + --> $DIR/use-site-wf.rs:6:11 + | +LL | type B = T; + | ^^^^ required by this bound + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider restricting type parameter `X` with trait `Copy` + | +LL | fn b(_: B) {} + | +++++++++++++++++++ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0478. +For more information about an error, try `rustc --explain E0277`. From 05aee18d230c46505eac1d11aeec4bb171764abb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Thu, 15 May 2025 12:59:20 +0200 Subject: [PATCH 45/59] Expand free alias types during variance computation --- .../rustc_hir_analysis/src/check/check.rs | 9 +-- .../rustc_hir_analysis/src/check/wfcheck.rs | 23 ++----- .../src/variance/constraints.rs | 20 ++---- .../rustc_hir_analysis/src/variance/dump.rs | 8 +-- .../rustc_hir_analysis/src/variance/mod.rs | 5 -- .../rustc_hir_analysis/src/variance/terms.rs | 3 - compiler/rustc_metadata/src/rmeta/encoder.rs | 2 +- compiler/rustc_middle/src/ty/util.rs | 10 ++- .../inherent-impls-overflow.current.stderr | 4 +- .../inherent-impls-overflow.next.stderr | 30 ++------- .../inherent-impls-overflow.rs | 6 +- ...-arguments-not-wfchecked.next-fixed.stderr | 9 +++ .../unused-generic-arguments-not-wfchecked.rs | 33 ++++++++++ .../unused-generic-parameters.fail.stderr | 50 +++++++++++++++ .../unused-generic-parameters.rs | 42 ++++++++----- .../unused-generic-parameters.stderr | 28 --------- tests/ui/lazy-type-alias/variance-0.rs | 61 +++++++++++++++++++ tests/ui/lazy-type-alias/variance-1.rs | 42 +++++++++++++ tests/ui/lazy-type-alias/variance-1.stderr | 22 +++++++ tests/ui/lazy-type-alias/variance-overflow.rs | 22 +++++++ .../lazy-type-alias/variance-overflow.stderr | 29 +++++++++ tests/ui/lazy-type-alias/variance.rs | 38 ------------ 22 files changed, 324 insertions(+), 172 deletions(-) create mode 100644 tests/ui/lazy-type-alias/unused-generic-arguments-not-wfchecked.next-fixed.stderr create mode 100644 tests/ui/lazy-type-alias/unused-generic-arguments-not-wfchecked.rs create mode 100644 tests/ui/lazy-type-alias/unused-generic-parameters.fail.stderr delete mode 100644 tests/ui/lazy-type-alias/unused-generic-parameters.stderr create mode 100644 tests/ui/lazy-type-alias/variance-0.rs create mode 100644 tests/ui/lazy-type-alias/variance-1.rs create mode 100644 tests/ui/lazy-type-alias/variance-1.stderr create mode 100644 tests/ui/lazy-type-alias/variance-overflow.rs create mode 100644 tests/ui/lazy-type-alias/variance-overflow.stderr delete mode 100644 tests/ui/lazy-type-alias/variance.rs diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 00bb8fab3cc2d..6f7cd7960a242 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -974,7 +974,6 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), tcx.ensure_ok().generics_of(def_id); tcx.ensure_ok().type_of(def_id); tcx.ensure_ok().predicates_of(def_id); - check_type_alias_type_params_are_used(tcx, def_id); let ty = tcx.type_of(def_id).instantiate_identity(); let span = tcx.def_span(def_id); if tcx.type_alias_is_lazy(def_id) { @@ -988,8 +987,8 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), check_where_clauses(wfcx, def_id); Ok(()) })); - check_variances_for_type_defn(tcx, def_id); } else { + check_type_alias_type_params_are_used(tcx, def_id); res = res.and(enter_wf_checking_ctxt(tcx, def_id, |wfcx| { // HACK: We sometimes incidentally check that const arguments have the correct // type as a side effect of the anon const desugaring. To make this "consistent" @@ -2064,12 +2063,6 @@ fn detect_discriminant_duplicate<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) } fn check_type_alias_type_params_are_used<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) { - if tcx.type_alias_is_lazy(def_id) { - // Since we compute the variances for lazy type aliases and already reject bivariant - // parameters as unused, we can and should skip this check for lazy type aliases. - return; - } - let generics = tcx.generics_of(def_id); if generics.own_counts().types == 0 { return; diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index f5b414d2aa4a2..e85ecb63421d1 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -2049,12 +2049,6 @@ pub(super) fn check_variances_for_type_defn<'tcx>(tcx: TyCtxt<'tcx>, def_id: Loc DefKind::Enum | DefKind::Struct | DefKind::Union => { // Ok } - DefKind::TyAlias => { - assert!( - tcx.type_alias_is_lazy(def_id), - "should not be computing variance of non-free type alias" - ); - } kind => span_bug!(tcx.def_span(def_id), "cannot compute the variances of {kind:?}"), } @@ -2206,7 +2200,6 @@ fn report_bivariance<'tcx>( errors::UnusedGenericParameterHelp::AdtNoPhantomData { param_name } } } - ItemKind::TyAlias(..) => errors::UnusedGenericParameterHelp::TyAlias { param_name }, item_kind => bug!("report_bivariance: unexpected item kind: {item_kind:?}"), }; @@ -2288,9 +2281,6 @@ impl<'tcx> IsProbablyCyclical<'tcx> { .visit_with(self) }) } - DefKind::TyAlias if self.tcx.type_alias_is_lazy(def_id) => { - self.tcx.type_of(def_id).instantiate_identity().skip_norm_wip().visit_with(self) - } _ => ControlFlow::Continue(()), } } @@ -2300,17 +2290,12 @@ impl<'tcx> TypeVisitor> for IsProbablyCyclical<'tcx> { type Result = ControlFlow<(), ()>; fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<(), ()> { - let def_id = match ty.kind() { - ty::Adt(adt_def, _) => Some(adt_def.did()), - &ty::Alias(ty::AliasTy { kind: ty::Free { def_id }, .. }) => Some(def_id), - _ => None, - }; - if let Some(def_id) = def_id { - if def_id == self.item_def_id { + if let Some(adt_def) = ty.ty_adt_def() { + if adt_def.did() == self.item_def_id { return ControlFlow::Break(()); } - if self.seen.insert(def_id) { - self.visit_def(def_id)?; + if self.seen.insert(adt_def.did()) { + self.visit_def(adt_def.did())?; } } ty.super_visit_with(self) diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs index a45856937a8e0..3e7f5b73e4569 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -79,9 +79,6 @@ pub(crate) fn add_constraints_from_crate<'a, 'tcx>( } } DefKind::Fn | DefKind::AssocFn => constraint_cx.build_constraints_for_item(def_id), - DefKind::TyAlias if tcx.type_alias_is_lazy(def_id) => { - constraint_cx.build_constraints_for_item(def_id) - } _ => {} } } @@ -107,15 +104,6 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { let current_item = &CurrentItem { inferred_start }; let ty = tcx.type_of(def_id).instantiate_identity().skip_norm_wip(); - // The type as returned by `type_of` is the underlying type and generally not a free alias. - // Therefore we need to check the `DefKind` first. - if let DefKind::TyAlias = tcx.def_kind(def_id) - && tcx.type_alias_is_lazy(def_id) - { - self.add_constraints_from_ty(current_item, ty, self.covariant); - return; - } - match ty.kind() { ty::Adt(def, _) => { // Not entirely obvious: constraints on structs/enums do not @@ -216,14 +204,13 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { /// Adds constraints appropriate for an instance of `ty` appearing /// in a context with the generics defined in `generics` and /// ambient variance `variance` + #[instrument(level = "debug", skip(self, current))] fn add_constraints_from_ty( &mut self, current: &CurrentItem, ty: Ty<'tcx>, variance: VarianceTermPtr<'a>, ) { - debug!("add_constraints_from_ty(ty={:?}, variance={:?})", ty, variance); - match *ty.kind() { ty::Bool | ty::Char @@ -281,8 +268,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraints_from_invariant_args(current, args, variance); } - ty::Alias(ty::AliasTy { kind: ty::Free { def_id }, args, .. }) => { - self.add_constraints_from_args(current, def_id, args, variance); + ty::Alias(ty::AliasTy { kind: ty::Free { .. }, .. }) => { + let ty = self.tcx().expand_free_alias_tys(ty); + self.add_constraints_from_ty(current, ty, variance); } ty::Dynamic(data, r) => { diff --git a/compiler/rustc_hir_analysis/src/variance/dump.rs b/compiler/rustc_hir_analysis/src/variance/dump.rs index 2e17464736959..7963f5da0e870 100644 --- a/compiler/rustc_hir_analysis/src/variance/dump.rs +++ b/compiler/rustc_hir_analysis/src/variance/dump.rs @@ -38,18 +38,16 @@ pub(crate) fn variances(tcx: TyCtxt<'_>) { } match tcx.def_kind(id) { - DefKind::AssocFn | DefKind::Fn | DefKind::Enum | DefKind::Struct | DefKind::Union => {} - DefKind::TyAlias if tcx.type_alias_is_lazy(id) => {} + DefKind::AssocFn | DefKind::Fn | DefKind::Enum | DefKind::Struct | DefKind::Union => { + tcx.dcx().span_err(tcx.def_span(id), format_variances(tcx, id.def_id)); + } kind => { let message = format!( "attr parsing didn't report an error for `#[{}]` on {kind:?}", rustc_span::sym::rustc_dump_variances, ); tcx.dcx().span_delayed_bug(tcx.def_span(id), message); - continue; } } - - tcx.dcx().span_err(tcx.def_span(id), format_variances(tcx, id.def_id)); } } diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 9c20ef1a73dcf..c4287a8d0bb10 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -52,11 +52,6 @@ pub(super) fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Va let crate_map = tcx.crate_variances(()); return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]); } - DefKind::TyAlias if tcx.type_alias_is_lazy(item_def_id) => { - // These are inferred. - let crate_map = tcx.crate_variances(()); - return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]); - } DefKind::AssocTy => match tcx.opt_rpitit_info(item_def_id.to_def_id()) { Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => { return variance_of_opaque( diff --git a/compiler/rustc_hir_analysis/src/variance/terms.rs b/compiler/rustc_hir_analysis/src/variance/terms.rs index 9c7680b921205..6faeab4217e37 100644 --- a/compiler/rustc_hir_analysis/src/variance/terms.rs +++ b/compiler/rustc_hir_analysis/src/variance/terms.rs @@ -99,9 +99,6 @@ pub(crate) fn determine_parameters_to_be_inferred<'a, 'tcx>( } } DefKind::Fn | DefKind::AssocFn => terms_cx.add_inferreds_for_item(def_id), - DefKind::TyAlias if tcx.type_alias_is_lazy(def_id) => { - terms_cx.add_inferreds_for_item(def_id) - } _ => {} } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 1483de572c341..d6492f098d07e 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1153,6 +1153,7 @@ fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: Def | DefKind::Static { .. } | DefKind::Const { .. } | DefKind::ForeignMod + | DefKind::TyAlias | DefKind::Impl { .. } | DefKind::Trait | DefKind::TraitAlias @@ -1166,7 +1167,6 @@ fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: Def | DefKind::Closure | DefKind::ExternCrate | DefKind::SyntheticCoroutineBody => false, - DefKind::TyAlias => tcx.type_alias_is_lazy(def_id), } } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 9f6d1170a85f1..ee6aaf9cb6e17 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -905,7 +905,7 @@ impl<'tcx> TyCtxt<'tcx> { return Ty::new_error(self, guar); } - ty = self.type_of(def_id).instantiate(self, args).skip_norm_wip(); + ty = self.type_of(def_id).instantiate(self, args).skip_normalization(); depth += 1; } @@ -967,7 +967,7 @@ impl<'tcx> OpaqueTypeExpander<'tcx> { Some(expanded_ty) => *expanded_ty, None => { let generic_ty = self.tcx.type_of(def_id); - let concrete_ty = generic_ty.instantiate(self.tcx, args).skip_norm_wip(); + let concrete_ty = generic_ty.instantiate(self.tcx, args).skip_normalization(); let expanded_ty = self.fold_ty(concrete_ty); self.expanded_cache.insert((def_id, args), expanded_ty); expanded_ty @@ -1047,7 +1047,11 @@ impl<'tcx> TypeFolder> for FreeAliasTypeExpander<'tcx> { self.depth += 1; let ty = ensure_sufficient_stack(|| { - self.tcx.type_of(def_id).instantiate(self.tcx, args).skip_norm_wip().fold_with(self) + self.tcx + .type_of(def_id) + .instantiate(self.tcx, args) + .skip_normalization() + .fold_with(self) }); self.depth -= 1; ty diff --git a/tests/ui/lazy-type-alias/inherent-impls-overflow.current.stderr b/tests/ui/lazy-type-alias/inherent-impls-overflow.current.stderr index e91946066bd08..dee809ebf7e81 100644 --- a/tests/ui/lazy-type-alias/inherent-impls-overflow.current.stderr +++ b/tests/ui/lazy-type-alias/inherent-impls-overflow.current.stderr @@ -23,7 +23,7 @@ LL | type Poly0 = Poly1<(T,)>; = note: in case this is a recursive type alias, consider using a struct, enum, or union instead error[E0275]: overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>` - --> $DIR/inherent-impls-overflow.rs:21:1 + --> $DIR/inherent-impls-overflow.rs:20:1 | LL | type Poly1 = Poly0<(T,)>; | ^^^^^^^^^^^^^ @@ -31,7 +31,7 @@ LL | type Poly1 = Poly0<(T,)>; = note: in case this is a recursive type alias, consider using a struct, enum, or union instead error[E0275]: overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>` - --> $DIR/inherent-impls-overflow.rs:26:1 + --> $DIR/inherent-impls-overflow.rs:24:1 | LL | impl Poly0<()> {} | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr b/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr index 62ed6e8e513d9..a592d3537ebde 100644 --- a/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr +++ b/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr @@ -24,38 +24,16 @@ LL | type Poly0 = Poly1<(T,)>; | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`inherent_impls_overflow`) -error: type parameter `T` is only used recursively - --> $DIR/inherent-impls-overflow.rs:17:24 - | -LL | type Poly0 = Poly1<(T,)>; - | - ^ - | | - | type parameter must be used non-recursively in the definition - | - = help: consider removing `T` or referring to it in the body of the type alias - = note: all type parameters must be used in a non-recursive way in order to constrain their variance - error[E0275]: overflow evaluating the requirement `Poly0<(T,)> == _` - --> $DIR/inherent-impls-overflow.rs:21:1 + --> $DIR/inherent-impls-overflow.rs:20:1 | LL | type Poly1 = Poly0<(T,)>; | ^^^^^^^^^^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`inherent_impls_overflow`) -error: type parameter `T` is only used recursively - --> $DIR/inherent-impls-overflow.rs:21:24 - | -LL | type Poly1 = Poly0<(T,)>; - | - ^ - | | - | type parameter must be used non-recursively in the definition - | - = help: consider removing `T` or referring to it in the body of the type alias - = note: all type parameters must be used in a non-recursive way in order to constrain their variance - error[E0275]: overflow evaluating the requirement `Poly0<()> == _` - --> $DIR/inherent-impls-overflow.rs:26:1 + --> $DIR/inherent-impls-overflow.rs:24:1 | LL | impl Poly0<()> {} | ^^^^^^^^^^^^^^^^^ @@ -63,14 +41,14 @@ LL | impl Poly0<()> {} = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`inherent_impls_overflow`) error[E0275]: overflow evaluating the requirement `Poly0<()> == _` - --> $DIR/inherent-impls-overflow.rs:26:6 + --> $DIR/inherent-impls-overflow.rs:24:6 | LL | impl Poly0<()> {} | ^^^^^^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`inherent_impls_overflow`) -error: aborting due to 9 previous errors +error: aborting due to 7 previous errors Some errors have detailed explanations: E0271, E0275. For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/lazy-type-alias/inherent-impls-overflow.rs b/tests/ui/lazy-type-alias/inherent-impls-overflow.rs index b4a347cb098ca..be3cda4d53584 100644 --- a/tests/ui/lazy-type-alias/inherent-impls-overflow.rs +++ b/tests/ui/lazy-type-alias/inherent-impls-overflow.rs @@ -16,12 +16,10 @@ impl Loop {} type Poly0 = Poly1<(T,)>; //[current]~^ ERROR overflow normalizing the type alias `Poly0<(((((((...,),),),),),),)>` -//[next]~^^ ERROR type parameter `T` is only used recursively -//[next]~| ERROR overflow evaluating the requirement +//[next]~^^ ERROR overflow evaluating the requirement type Poly1 = Poly0<(T,)>; //[current]~^ ERROR overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>` -//[next]~^^ ERROR type parameter `T` is only used recursively -//[next]~| ERROR overflow evaluating the requirement +//[next]~^^ ERROR overflow evaluating the requirement impl Poly0<()> {} //[current]~^ ERROR overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>` diff --git a/tests/ui/lazy-type-alias/unused-generic-arguments-not-wfchecked.next-fixed.stderr b/tests/ui/lazy-type-alias/unused-generic-arguments-not-wfchecked.next-fixed.stderr new file mode 100644 index 0000000000000..7148c5d49e926 --- /dev/null +++ b/tests/ui/lazy-type-alias/unused-generic-arguments-not-wfchecked.next-fixed.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation panicked: explicit panic + --> $DIR/unused-generic-arguments-not-wfchecked.rs:28:43 + | +LL | #[cfg(not(next_bugged))] type A2 = A<[(); panic!()]>; // FIXME: `panic!()` diverging + | ^^^^^^^^ evaluation of `A2::{constant#0}` failed here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/lazy-type-alias/unused-generic-arguments-not-wfchecked.rs b/tests/ui/lazy-type-alias/unused-generic-arguments-not-wfchecked.rs new file mode 100644 index 0000000000000..eeabe85d82734 --- /dev/null +++ b/tests/ui/lazy-type-alias/unused-generic-arguments-not-wfchecked.rs @@ -0,0 +1,33 @@ +// We currently fail to wfcheck generic arguments that correspond to unused LTA generic parameters +// since we generally normalize types before wfchecking them, so we accidentally "expand them away" +// before we can check them. +// +// (We do still check predicates that reference unused parameters, of course.) +// +// FIXME(lazy_type_alias): I consider #100041 to be a stabilization-blocking concern for the checked +// version of LTA! The *entire premise* of checked_LTA is wfchecking; +// we can't have such obvious holes in it! +// +//@ revisions: current-bugged next-bugged next-fixed +// +//@[next-bugged] compile-flags: -Znext-solver +//@[next-fixed] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) +// +//@[current-bugged] known-bug: #100041 +//@[current-bugged] check-pass +//@[next-bugged] known-bug: #100041 +//@[next-bugged] check-pass + +#![feature(lazy_type_alias)] + +type A = (); + +type A0 = A<[str]>; // FIXME: `str: Sized` unsatisfied +type A1<'r> = A<&'static &'r ()>; // FIXME: `'r: 'static` unsatisfied +#[cfg(not(next_bugged))] type A2 = A<[(); panic!()]>; // FIXME: `panic!()` diverging +//[next-fixed]~^ ERROR evaluation panicked + +#[cfg(not(next_bugged))] const _: A<[str]> = (); // FIXME: `str: Sized` unsatisfied + +fn main() {} diff --git a/tests/ui/lazy-type-alias/unused-generic-parameters.fail.stderr b/tests/ui/lazy-type-alias/unused-generic-parameters.fail.stderr new file mode 100644 index 0000000000000..05e3881cb090c --- /dev/null +++ b/tests/ui/lazy-type-alias/unused-generic-parameters.fail.stderr @@ -0,0 +1,50 @@ +error[E0478]: lifetime bound not satisfied + --> $DIR/unused-generic-parameters.rs:24:22 + | +LL | #[cfg(fail)] fn a(_: A<'_>) {} + | ^^^^^ + | +note: lifetime parameter instantiated with the anonymous lifetime defined here + --> $DIR/unused-generic-parameters.rs:24:22 + | +LL | #[cfg(fail)] fn a(_: A<'_>) {} + | ^^^^^ + = note: but lifetime parameter must outlive the static lifetime + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unused-generic-parameters.rs:28:22 + | +LL | #[cfg(fail)] fn b(_: B) {} + | ^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` +note: required by a bound on the type alias `B` + --> $DIR/unused-generic-parameters.rs:26:8 + | +LL | type B = (); + | ^ required by this bound + +error[E0080]: evaluation panicked: explicit panic + --> $DIR/unused-generic-parameters.rs:34:26 + | +LL | #[cfg(fail)] fn c(_: C<{ panic!() }>) {} + | ^^^^^^^^ evaluation of `c::{constant#0}` failed here + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/unused-generic-parameters.rs:28:22 + | +LL | #[cfg(fail)] fn b(_: B) {} + | ^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` +note: required by a bound on the type alias `B` + --> $DIR/unused-generic-parameters.rs:26:8 + | +LL | type B = (); + | ^ required by this bound + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0080, E0277, E0478. +For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/lazy-type-alias/unused-generic-parameters.rs b/tests/ui/lazy-type-alias/unused-generic-parameters.rs index 9d02de7a7212b..3482512671226 100644 --- a/tests/ui/lazy-type-alias/unused-generic-parameters.rs +++ b/tests/ui/lazy-type-alias/unused-generic-parameters.rs @@ -1,22 +1,36 @@ -// Check that we reject bivariant generic parameters as unused. -// Furthermore, check that we only emit a single diagnostic for unused type parameters: -// Previously, we would emit *two* errors, namely E0392 and E0091. +// Check that we accept unused generic parameters on lazy type aliases (for context, we reject +// unused type parameters on eager type aliases). +// +// As long as we check well-formedness before normalization there shouldn't be anything wrong with +// such parameters since we know that the corresponding arguments will get wfchecked regardless. +// +// FIXME(lazy_type_alias, #100041): At the time of writing however, that's not the case. I consider +// this to be stabilization-blocking concern for the strong / +// checked version of LTA! +// See also `unused-generic-arguments-not-wfchecked.rs`. +// +// (We *do* ofc still detect unsatisfied predicates even if they +// reference unused parameters) +// +// issue: +// +//@ revisions: pass fail +//@[pass] check-pass #![feature(lazy_type_alias)] -#![allow(incomplete_features)] -type A<'a> = (); -//~^ ERROR lifetime parameter `'a` is never used -//~| HELP consider removing `'a` +type A<'a: 'static> = (); +const _: A<'static> = (); +#[cfg(fail)] fn a(_: A<'_>) {} //[fail]~ ERROR lifetime bound not satisfied type B = (); -//~^ ERROR type parameter `T` is never used -//~| HELP consider removing `T` -//~| HELP if you intended `T` to be a const parameter +const _: B = (); +#[cfg(fail)] fn b(_: B) {} +//[fail]~^ ERROR the size for values of type `str` cannot be known at compilation time +//[fail]~| ERROR the size for values of type `str` cannot be known at compilation time -// Check that we don't emit the const param help message here: -type C = (); -//~^ ERROR type parameter `T` is never used -//~| HELP consider removing `T` +type C = (); +const _: C<{ 0 * 1 }> = (); +#[cfg(fail)] fn c(_: C<{ panic!() }>) {} //[fail]~ ERROR evaluation panicked fn main() {} diff --git a/tests/ui/lazy-type-alias/unused-generic-parameters.stderr b/tests/ui/lazy-type-alias/unused-generic-parameters.stderr deleted file mode 100644 index 484e21b0a03f9..0000000000000 --- a/tests/ui/lazy-type-alias/unused-generic-parameters.stderr +++ /dev/null @@ -1,28 +0,0 @@ -error[E0392]: lifetime parameter `'a` is never used - --> $DIR/unused-generic-parameters.rs:8:8 - | -LL | type A<'a> = (); - | ^^ unused lifetime parameter - | - = help: consider removing `'a` or referring to it in the body of the type alias - -error[E0392]: type parameter `T` is never used - --> $DIR/unused-generic-parameters.rs:12:8 - | -LL | type B = (); - | ^ unused type parameter - | - = help: consider removing `T` or referring to it in the body of the type alias - = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead - -error[E0392]: type parameter `T` is never used - --> $DIR/unused-generic-parameters.rs:18:8 - | -LL | type C = (); - | ^ unused type parameter - | - = help: consider removing `T` or referring to it in the body of the type alias - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/lazy-type-alias/variance-0.rs b/tests/ui/lazy-type-alias/variance-0.rs new file mode 100644 index 0000000000000..1cecdff2977b3 --- /dev/null +++ b/tests/ui/lazy-type-alias/variance-0.rs @@ -0,0 +1,61 @@ +// Ensure that we eagerly *expand* free alias types during variance computation. +// +// Since free alias types are always normalizable it's not unreasonable to expect that variance +// information "propagates through" free aliases unlike projections for example which constrain +// all of their generic arguments to be invariant[^1]. +// +// For context, we can't *normalize* types before trying to compute variances because we need +// variances for normalization in the first place, more specifically type relating. +// +// [^1]: Parent args: Traits are invariant over their params. Own args: Projections can be rigid. +// +// issue: +// +//@ check-pass + +// FIXME(lazy_type_alias): Revisit this before stabilization (it's not blocking tho): +// We might want to compute variances for free alias types again +// with a special rule. See `variance-1.rs` for details. + +#![feature(lazy_type_alias)] + +// `Co` is covariant over `'a` since we expand `A` to `&'a ()`. +struct Co<'a>(A<'a>); + +// `A` is *not* in a variance relation with its args since it's a type alias. +type A<'a> = &'a (); + +fn co<'a>(x: Co<'static>) { + let _: Co<'a> = x; // OK +} + +// `Contra` is contravariant over `'a` since we expand `B` to `fn(&'a ())`. +struct Contra<'a>(B<'a>); + +// (not in a variance relation) +type B<'a> = fn(&'a ()); + +fn contra<'a>(x: Contra<'a>) { + let _: Contra<'static> = x; // OK +} + +// `CoContra` is covariant over `T` and contravariant over `U` since we expand `C`. +struct CoContra(C); + +// (not in a variance relation) +type C = Option<(T, fn(U))>; + +fn co_contra<'a>(x: CoContra<&'static (), &'a ()>) -> CoContra<&'a (), &'static ()> { + x // OK +} + +// Check that we deeply expand: +struct Co2<'a>(D0<'a>); +type D0<'a> = D1<'a>; +type D1<'a> = D2<'a>; +type D2<'a> = D3<'a>; +type D3<'a> = &'a (); + +fn co2<'a>(x: Co2<'static>) -> Co2<'a> { x } // OK + +fn main() {} diff --git a/tests/ui/lazy-type-alias/variance-1.rs b/tests/ui/lazy-type-alias/variance-1.rs new file mode 100644 index 0000000000000..51480d271b439 --- /dev/null +++ b/tests/ui/lazy-type-alias/variance-1.rs @@ -0,0 +1,42 @@ +// Demonstrate that free alias types don't constrain their lifetime & type arguments if the corresp. +// lifetime & type parameters are unused in the lazy type alias (before normalization) since we +// eagerly expand them during variance computation unlike other alias types which constrain args to +// be invariant. + +// FIXME(lazy_type_alias): Revisit this before stabilization (altho it's not blocking): +// Do we want to compute variances for lazy type aliases & free alias types +// again and "force bivariant parameters to be invariant" if they're not +// constrained by a projection? +// This would make `struct WrapDiscard` below compile. + +#![feature(lazy_type_alias)] + +type Discard<'a, T> = (); + +// `'a` and `T` are bivariant & unconstrained => rejection +struct WrapDiscard<'a, T>(Discard<'a, T>); +//~^ ERROR lifetime parameter `'a` is never used +//~| ERROR type parameter `T` is never used + +type DiscardConstrained<'a, T, X> = X +where + X: Iterator; + +// `'a` and `T` are bivariant & constrained => acceptance +struct WrapDiscardConstrained<'a, T, X>(DiscardConstrained<'a, T, X>) +where + X: Iterator; + +type Co<'a> = std::vec::IntoIter<(&'a (), &'a ())>; + +// NOTE: If we end up switching back to computing variances for free alias types with the special +// rule explained in the FIXME above, then this function should still compile since +// LTA `DiscardConstrained` should be bivariant over `'a` and `T`, not invariant due to them +// being constrained by a projection. +fn bi<'r>( + x: WrapDiscardConstrained<'static, &'static (), Co<'static>>, +) -> WrapDiscardConstrained<'r, &'r (), Co<'r>> { + x +} + +fn main() {} diff --git a/tests/ui/lazy-type-alias/variance-1.stderr b/tests/ui/lazy-type-alias/variance-1.stderr new file mode 100644 index 0000000000000..5eb2f5d0673aa --- /dev/null +++ b/tests/ui/lazy-type-alias/variance-1.stderr @@ -0,0 +1,22 @@ +error[E0392]: lifetime parameter `'a` is never used + --> $DIR/variance-1.rs:17:20 + | +LL | struct WrapDiscard<'a, T>(Discard<'a, T>); + | ^^ unused lifetime parameter + | + = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` + +error[E0392]: type parameter `T` is never used + --> $DIR/variance-1.rs:17:24 + | +LL | struct WrapDiscard<'a, T>(Discard<'a, T>); + | ^ - `T` is named here, but is likely unused in the containing type + | | + | unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/lazy-type-alias/variance-overflow.rs b/tests/ui/lazy-type-alias/variance-overflow.rs new file mode 100644 index 0000000000000..6bd7acc3ebef7 --- /dev/null +++ b/tests/ui/lazy-type-alias/variance-overflow.rs @@ -0,0 +1,22 @@ +// Ensure that we don't enter infinite recursion and trigger a stack overflow when computing the +// variances of items that reference diverging free alias types. This once used to happen in a dev +// version of PR #141030. +// +// This test demonstrates that we cannot rely on wfck bailing out early with a normalization error +// for such free alias types before we reach variance computation. At least at the time of writing, +// we wfck item `First` first which includes variance computation -- at which point item `Second` +// hasn't been wfck'ed yet. +// This means we can't use `type_of` to recurse into free alias types, we do have to use +// `expand_free_alias_tys`. + +#![feature(lazy_type_alias)] + +// the (unused) type parameter is necessary to actually trigger variance computation for `First`. +struct First(Second); +//~^ ERROR type parameter `T` is never used +//~| ERROR overflow normalizing the type alias `Second` + +type Second = Second; // diverging free alias type +//~^ ERROR overflow normalizing the type alias `Second` + +fn main() {} diff --git a/tests/ui/lazy-type-alias/variance-overflow.stderr b/tests/ui/lazy-type-alias/variance-overflow.stderr new file mode 100644 index 0000000000000..35486ccdc169f --- /dev/null +++ b/tests/ui/lazy-type-alias/variance-overflow.stderr @@ -0,0 +1,29 @@ +error[E0392]: type parameter `T` is never used + --> $DIR/variance-overflow.rs:15:14 + | +LL | struct First(Second); + | ^ unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error[E0275]: overflow normalizing the type alias `Second` + --> $DIR/variance-overflow.rs:15:17 + | +LL | struct First(Second); + | ^^^^^^ + | + = note: in case this is a recursive type alias, consider using a struct, enum, or union instead + +error[E0275]: overflow normalizing the type alias `Second` + --> $DIR/variance-overflow.rs:19:1 + | +LL | type Second = Second; // diverging free alias type + | ^^^^^^^^^^^ + | + = note: in case this is a recursive type alias, consider using a struct, enum, or union instead + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0275, E0392. +For more information about an error, try `rustc --explain E0275`. diff --git a/tests/ui/lazy-type-alias/variance.rs b/tests/ui/lazy-type-alias/variance.rs deleted file mode 100644 index dae2069502a20..0000000000000 --- a/tests/ui/lazy-type-alias/variance.rs +++ /dev/null @@ -1,38 +0,0 @@ -// This is a regression test for issue #114221. -// Check that we compute variances for lazy type aliases. - -//@ check-pass - -#![feature(lazy_type_alias)] -#![allow(incomplete_features)] - -// [+] `A` is covariant over `'a`. -struct A<'a>(Co<'a>); - -// [+] `Co` is covariant over `'a`. -type Co<'a> = &'a (); - -fn co<'a>(x: A<'static>) { - let _: A<'a> = x; -} - -// [-] `B` is contravariant over `'a`. -struct B<'a>(Contra<'a>); - -// [-] `Contra` is contravariant over `'a`. -type Contra<'a> = fn(&'a ()); - -fn contra<'a>(x: B<'a>) { - let _: B<'static> = x; -} - -struct C(CoContra); - -// [+, -] `CoContra` is covariant over `T` and contravariant over `U`. -type CoContra = Option<(T, fn(U))>; - -fn co_contra<'a>(x: C<&'static (), &'a ()>) -> C<&'a (), &'static ()> { - x -} - -fn main() {} From 00ac5629f732beca1c77f892f12fb6d125d71f77 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 10 Jun 2026 12:51:00 +0200 Subject: [PATCH 46/59] Rename `rustc_mir_build/src/errors.rs` into `rustc_mir_build/src/diagnostics.rs` --- compiler/rustc_mir_build/src/builder/expr/into.rs | 2 +- compiler/rustc_mir_build/src/builder/mod.rs | 4 ++-- compiler/rustc_mir_build/src/builder/scope.rs | 4 ++-- compiler/rustc_mir_build/src/check_unsafety.rs | 2 +- compiler/rustc_mir_build/src/{errors.rs => diagnostics.rs} | 0 compiler/rustc_mir_build/src/lib.rs | 2 +- compiler/rustc_mir_build/src/thir/cx/expr.rs | 2 +- compiler/rustc_mir_build/src/thir/pattern/check_match.rs | 2 +- compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs | 2 +- compiler/rustc_mir_build/src/thir/pattern/mod.rs | 2 +- 10 files changed, 11 insertions(+), 11 deletions(-) rename compiler/rustc_mir_build/src/{errors.rs => diagnostics.rs} (100%) diff --git a/compiler/rustc_mir_build/src/builder/expr/into.rs b/compiler/rustc_mir_build/src/builder/expr/into.rs index a6c3d5f9fb9a7..e802b5b5c4898 100644 --- a/compiler/rustc_mir_build/src/builder/expr/into.rs +++ b/compiler/rustc_mir_build/src/builder/expr/into.rs @@ -18,7 +18,7 @@ use crate::builder::expr::category::{Category, RvalueFunc}; use crate::builder::matches::{DeclareLetBindings, Exhaustive, HasMatchGuard}; use crate::builder::scope::LintLevel; use crate::builder::{BlockAnd, BlockAndExtension, BlockFrame, Builder, NeedsTemporary}; -use crate::errors::{LoopMatchArmWithGuard, LoopMatchUnsupportedType}; +use crate::diagnostics::{LoopMatchArmWithGuard, LoopMatchUnsupportedType}; impl<'a, 'tcx> Builder<'a, 'tcx> { /// Compile `expr`, storing the result into `destination`, which diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index d158f55a3111c..c0234b718f1d0 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -44,7 +44,7 @@ use rustc_span::{Span, Symbol}; use crate::builder::expr::as_place::PlaceBuilder; use crate::builder::scope::{DropKind, LintLevel}; -use crate::errors; +use crate::diagnostics; pub(crate) fn closure_saved_names_of_captured_variables<'tcx>( tcx: TyCtxt<'tcx>, @@ -931,7 +931,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { lint::builtin::UNREACHABLE_CODE, lint_root, target_loc.span, - errors::UnreachableDueToUninhabited { + diagnostics::UnreachableDueToUninhabited { expr: target_loc.span, orig: orig_span, descr, diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs index a341bef032889..84abb6ca70e70 100644 --- a/compiler/rustc_mir_build/src/builder/scope.rs +++ b/compiler/rustc_mir_build/src/builder/scope.rs @@ -99,7 +99,7 @@ use tracing::{debug, instrument}; use super::matches::BuiltMatchTree; use crate::builder::{BlockAnd, BlockAndExtension, BlockFrame, Builder, CFG}; -use crate::errors::{ +use crate::diagnostics::{ ConstContinueBadConst, ConstContinueNotMonomorphicConst, ConstContinueUnknownJumpTarget, }; @@ -924,7 +924,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | ExprKind::NamedConst { .. } => self.as_constant(&self.thir[value]), other => { - use crate::errors::ConstContinueNotMonomorphicConstReason as Reason; + use crate::diagnostics::ConstContinueNotMonomorphicConstReason as Reason; let span = expr.span; let reason = match other { diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index f99d8934aa7fa..a5e5b9f7699b8 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -16,7 +16,7 @@ use rustc_session::lint::builtin::{DEPRECATED_SAFE_2024, UNSAFE_OP_IN_UNSAFE_FN, use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::{Span, Symbol}; -use crate::errors::*; +use crate::diagnostics::*; struct UnsafetyVisitor<'a, 'tcx> { tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/diagnostics.rs similarity index 100% rename from compiler/rustc_mir_build/src/errors.rs rename to compiler/rustc_mir_build/src/diagnostics.rs diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index e5516b45ee6b3..78be159b08292 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -11,7 +11,7 @@ mod builder; mod check_tail_calls; mod check_unsafety; -mod errors; +mod diagnostics; pub mod thir; use rustc_middle::util::Providers; diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index b32d7dce4f4d3..d8015046aab28 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -22,7 +22,7 @@ use rustc_middle::{bug, span_bug}; use rustc_span::Span; use tracing::{debug, info, instrument, trace}; -use crate::errors::*; +use crate::diagnostics::*; use crate::thir::cx::ThirBuildCx; impl<'tcx> ThirBuildCx<'tcx> { diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 8e147a44d3b75..274a9d874790e 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -27,7 +27,7 @@ use rustc_span::{Ident, Span}; use rustc_trait_selection::infer::InferCtxtExt; use tracing::instrument; -use crate::errors::*; +use crate::diagnostics::*; pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> { let typeck_results = tcx.typeck(def_id); diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 56aeabe83898f..178f79173ea50 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -20,7 +20,7 @@ use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use tracing::{debug, instrument, trace}; use super::PatCtxt; -use crate::errors::{ +use crate::diagnostics::{ ConstPatternDependsOnGenericParameter, CouldNotEvalConstPattern, InvalidPattern, NaNPattern, PointerPattern, SuggestEq, TypeNotPartialEq, TypeNotStructural, UnionPattern, UnsizedPattern, }; diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index d826a7ed1f30a..92cb9dd8de7ca 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -29,7 +29,7 @@ use tracing::{debug, instrument}; pub(crate) use self::check_match::check_match; use self::migration::PatMigration; -use crate::errors::*; +use crate::diagnostics::*; use crate::thir::cx::ThirBuildCx; /// Context for lowering HIR patterns to THIR patterns. From b679cbd70cff66547780ae0e73373c16619c1467 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 10 Jun 2026 13:04:51 +0200 Subject: [PATCH 47/59] Rename `rustc_mir_dataflow/src/errors.rs` into `rustc_mir_dataflow/src/diagnostics.rs` --- compiler/rustc_mir_dataflow/src/{errors.rs => diagnostics.rs} | 0 compiler/rustc_mir_dataflow/src/lib.rs | 2 +- compiler/rustc_mir_dataflow/src/rustc_peek.rs | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename compiler/rustc_mir_dataflow/src/{errors.rs => diagnostics.rs} (100%) diff --git a/compiler/rustc_mir_dataflow/src/errors.rs b/compiler/rustc_mir_dataflow/src/diagnostics.rs similarity index 100% rename from compiler/rustc_mir_dataflow/src/errors.rs rename to compiler/rustc_mir_dataflow/src/diagnostics.rs diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index f29a1f361e4b1..7cec1db2a810c 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -23,8 +23,8 @@ pub use self::framework::{ use self::move_paths::MoveData; pub mod debuginfo; +mod diagnostics; mod drop_flag_effects; -mod errors; mod framework; pub mod impls; pub mod move_paths; diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs index 8d16e99f751e8..4eb38569e6d48 100644 --- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs +++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs @@ -5,7 +5,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::{Span, sym}; use tracing::{debug, info}; -use crate::errors::{ +use crate::diagnostics::{ PeekArgumentNotALocal, PeekArgumentUntracked, PeekBitNotSet, PeekMustBeNotTemporary, PeekMustBePlaceOrRefPlace, StopAfterDataFlowEndedCompilation, }; From 67081117f068b2617fafb8e5a82b2c03a924a02a Mon Sep 17 00:00:00 2001 From: aerooneqq Date: Wed, 10 Jun 2026 14:07:39 +0300 Subject: [PATCH 48/59] Emit error for unused target expression in glob and list delegations --- compiler/rustc_ast/src/ast.rs | 8 +- compiler/rustc_ast/src/visit.rs | 1 - compiler/rustc_ast_lowering/src/delegation.rs | 38 +- compiler/rustc_ast_lowering/src/lib.rs | 6 +- compiler/rustc_expand/src/expand.rs | 32 +- compiler/rustc_hir/src/hir.rs | 4 +- compiler/rustc_hir_analysis/src/delegation.rs | 21 +- compiler/rustc_hir_typeck/src/callee.rs | 5 +- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 5 +- compiler/rustc_interface/src/passes.rs | 2 + compiler/rustc_middle/src/hir/map.rs | 8 + compiler/rustc_middle/src/ty/mod.rs | 8 +- compiler/rustc_passes/src/delegation.rs | 32 + compiler/rustc_passes/src/lib.rs | 1 + compiler/rustc_resolve/src/lib.rs | 5 +- .../delegation/self-coercion-static-free.rs | 2 + .../self-coercion-static-free.stderr | 28 +- .../unused-target-expr-in-glob-or-list.rs | 208 +++++++ .../unused-target-expr-in-glob-or-list.stderr | 569 ++++++++++++++++++ 19 files changed, 918 insertions(+), 65 deletions(-) create mode 100644 compiler/rustc_passes/src/delegation.rs create mode 100644 tests/ui/delegation/unused-target-expr-in-glob-or-list.rs create mode 100644 tests/ui/delegation/unused-target-expr-in-glob-or-list.stderr diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index b8339c74dac03..b8d54df4fb75a 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -31,7 +31,8 @@ use rustc_data_structures::tagged_ptr::Tag; use rustc_macros::{Decodable, Encodable, StableHash, Walkable}; pub use rustc_span::AttrId; use rustc_span::{ - ByteSymbol, DUMMY_SP, ErrorGuaranteed, Ident, Span, Spanned, Symbol, kw, respan, sym, + ByteSymbol, DUMMY_SP, ErrorGuaranteed, Ident, LocalExpnId, Span, Spanned, Symbol, kw, respan, + sym, }; use thin_vec::{ThinVec, thin_vec}; @@ -3906,10 +3907,10 @@ pub struct EiiImpl { pub is_default: bool, } -#[derive(Clone, Encodable, Decodable, Debug, Walkable, PartialEq, Eq)] +#[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq, Eq)] pub enum DelegationSource { Single, - List, + List(LocalExpnId), Glob, } @@ -3923,6 +3924,7 @@ pub struct Delegation { pub rename: Option, pub body: Option>, /// The item was expanded from a glob delegation item. + #[visitable(ignore)] pub source: DelegationSource, } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 19255e55506f9..1e96d1d52f7eb 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -431,7 +431,6 @@ macro_rules! common_visitor_and_walkers { Delegation, DelegationMac, DelegationSuffixes, - DelegationSource, DelimArgs, DelimSpan, EnumDef, diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 68ae9e68b029a..90c7604b7babc 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -62,7 +62,7 @@ use crate::diagnostics::{ }; use crate::{ AllowReturnTypeNotation, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode, - ResolverAstLoweringExt, index_crate, + index_crate, }; mod generics; @@ -126,7 +126,7 @@ pub(crate) fn delegations_resolutions( let delegation = ast_index[def_id].delegation().expect("processing delegations"); let span = delegation.last_segment_span(); - if let Some(info) = resolver.delegation_info(def_id) { + if let Some(info) = tcx.resolutions(()).delegation_infos.get(&def_id) { let res = info.resolution_id.map(|id| check_for_cycles(tcx, id, span).map(|_| id)); result.insert(def_id, res.flatten()); } else { @@ -143,8 +143,6 @@ pub(crate) fn delegations_resolutions( fn check_for_cycles(tcx: TyCtxt<'_>, mut def_id: DefId, span: Span) -> Result<(), ErrorGuaranteed> { let mut visited: FxHashSet = Default::default(); - let (resolver, _) = &*tcx.hir_crate(()).delayed_resolver.borrow(); - loop { visited.insert(def_id); @@ -152,7 +150,7 @@ fn check_for_cycles(tcx: TyCtxt<'_>, mut def_id: DefId, span: Span) -> Result<() // it means that we refer to another delegation as a callee, so in order to obtain // a signature DefId we obtain NodeId of the callee delegation and try to get signature from it. if let Some(local_id) = def_id.as_local() - && let Some(info) = resolver.delegation_info(local_id) + && let Some(info) = tcx.resolutions(()).delegation_infos.get(&local_id) && let Ok(id) = info.resolution_id { def_id = id; @@ -209,10 +207,11 @@ impl<'hir> LoweringContext<'_, 'hir> { let mut generics = self.uplift_delegation_generics(delegation, sig_id, is_method); - let (body_id, call_expr_id) = + let (body_id, call_expr_id, unused_target_expr) = self.lower_delegation_body(delegation, sig_id, param_count, &mut generics, span); let decl = self.lower_delegation_decl( + delegation.source, sig_id, param_count, c_variadic, @@ -220,6 +219,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &generics, delegation.id, call_expr_id, + unused_target_expr, ); let sig = self.lower_delegation_sig(sig_id, decl, span); @@ -375,6 +375,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_delegation_decl( &mut self, + source: DelegationSource, sig_id: DefId, param_count: usize, c_variadic: bool, @@ -382,6 +383,7 @@ impl<'hir> LoweringContext<'_, 'hir> { generics: &GenericsGenerationResults<'hir>, call_path_node_id: NodeId, call_expr_id: HirId, + unused_target_expr: bool, ) -> &'hir hir::FnDecl<'hir> { // The last parameter in C variadic functions is skipped in the signature, // like during regular lowering. @@ -406,6 +408,17 @@ impl<'hir> LoweringContext<'_, 'hir> { parent_args_segment_id: generics.parent.args_segment_id, self_ty_id: generics.self_ty_id, propagate_self_ty: generics.propagate_self_ty, + group_id: { + let id = match source { + DelegationSource::Single => None, + DelegationSource::List(expn_id) => Some(expn_id), + DelegationSource::Glob => { + Some(self.tcx.expn_that_defined(self.owner.def_id).expect_local()) + } + }; + + id.map(|id| (id, unused_target_expr)) + }, })), )), span, @@ -504,9 +517,10 @@ impl<'hir> LoweringContext<'_, 'hir> { param_count: usize, generics: &mut GenericsGenerationResults<'hir>, span: Span, - ) -> (BodyId, HirId) { + ) -> (BodyId, HirId, bool) { let block = delegation.body.as_deref(); let mut call_expr_id = HirId::INVALID; + let mut unused_target_expr = false; let block_id = self.lower_body(|this| { let mut parameters: Vec> = Vec::with_capacity(param_count); @@ -514,6 +528,12 @@ impl<'hir> LoweringContext<'_, 'hir> { let mut stmts: &[hir::Stmt<'hir>] = &[]; let is_method = this.is_method(sig_id, span); + let should_generate_block = this.should_generate_block(delegation, sig_id, is_method); + + // Consider non-specified target expression as generated, + // as we do not want to emit error when target expression is + // not specified. + unused_target_expr = block.is_some() && (param_count == 0 || !should_generate_block); for idx in 0..param_count { let (param, pat_node_id) = this.generate_param(is_method, idx, span); @@ -524,7 +544,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let arg = if let Some(block) = block && idx == 0 - && this.should_generate_block(delegation, sig_id, is_method) + && should_generate_block { let mut self_resolver = SelfResolver { ctxt: this, @@ -565,7 +585,7 @@ impl<'hir> LoweringContext<'_, 'hir> { debug_assert_ne!(call_expr_id, HirId::INVALID); - (block_id, call_expr_id) + (block_id, call_expr_id, unused_target_expr) } fn finalize_body_lowering( diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 8b4a2795ec90c..e3cb4c4590a43 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -62,7 +62,7 @@ use rustc_macros::extension; use rustc_middle::hir::{self as mid_hir}; use rustc_middle::queries::Providers; use rustc_middle::span_bug; -use rustc_middle::ty::{DelegationInfo, PerOwnerResolverData, ResolverAstLowering, TyCtxt}; +use rustc_middle::ty::{PerOwnerResolverData, ResolverAstLowering, TyCtxt}; use rustc_session::errors::add_feature_diagnostics; use rustc_span::symbol::{Ident, Symbol, kw, sym}; use rustc_span::{DUMMY_SP, DesugaringKind, Span}; @@ -306,10 +306,6 @@ impl<'tcx> ResolverAstLowering<'tcx> { self.extra_lifetime_params_map.get(&id).map_or(&[], |v| &v[..]) } - fn delegation_info(&self, id: LocalDefId) -> Option<&DelegationInfo> { - self.delegation_infos.get(&id) - } - fn owner_def_id(&self, id: NodeId) -> LocalDefId { self.owners[&id].def_id } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index ac16dbc2fa387..0745b85c0ad47 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -8,9 +8,9 @@ use rustc_ast::tokenstream::TokenStream; use rustc_ast::visit::{self, AssocCtxt, Visitor, VisitorResult, try_visit, walk_list}; use rustc_ast::{ self as ast, AssocItemKind, AstNodeWrapper, AttrArgs, AttrItemKind, AttrStyle, AttrVec, - DUMMY_NODE_ID, DelegationSuffixes, EarlyParsedAttribute, ExprKind, ForeignItemKind, HasAttrs, - HasNodeId, Inline, ItemKind, MacStmtStyle, MetaItemInner, MetaItemKind, ModKind, NodeId, - PatKind, StmtKind, TyKind, token, + DUMMY_NODE_ID, DelegationSource, DelegationSuffixes, EarlyParsedAttribute, ExprKind, + ForeignItemKind, HasAttrs, HasNodeId, Inline, ItemKind, MacStmtStyle, MetaItemInner, + MetaItemKind, ModKind, NodeId, PatKind, StmtKind, TyKind, token, }; use rustc_ast_pretty::pprust; use rustc_attr_parsing::parser::AllowExprMetavar; @@ -992,7 +992,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> { type Node = AstNodeWrapper, ImplItemTag>; let single_delegations = build_single_delegations::( - self.cx, deleg, &item, &suffixes, item.span, true, + self.cx, + deleg, + &item, + &suffixes, + item.span, + DelegationSource::Glob, ); // `-Zmacro-stats` ignores these because they don't seem important. fragment_kind.expect_from_annotatables(single_delegations.map(|item| { @@ -2041,8 +2046,12 @@ fn build_single_delegations<'a, Node: InvocationCollectorNode>( item: &'a ast::Item, suffixes: &'a [(Ident, Option)], item_span: Span, - from_glob: bool, + source: DelegationSource, ) -> impl Iterator> + 'a { + debug_assert_ne!(source, DelegationSource::Single); + + let from_glob = source == DelegationSource::Glob; + if suffixes.is_empty() { // Report an error for now, to avoid keeping stem for resolution and // stability checks. @@ -2066,11 +2075,7 @@ fn build_single_delegations<'a, Node: InvocationCollectorNode>( ident: rename.unwrap_or(ident), rename, body: deleg.body.clone(), - source: if from_glob { - ast::DelegationSource::Glob - } else { - ast::DelegationSource::List - }, + source, })), tokens: None, } @@ -2414,7 +2419,12 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { }; let single_delegations = build_single_delegations::( - self.cx, deleg, item, suffixes, item.span, false, + self.cx, + deleg, + item, + suffixes, + item.span, + DelegationSource::List(LocalExpnId::fresh_empty()), ); Node::flatten_outputs(single_delegations.map(|item| { let mut item = Node::from_item(item); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 53141dcc5042f..58becf68ccc6f 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -25,7 +25,8 @@ use rustc_index::IndexVec; use rustc_macros::{Decodable, Encodable, StableHash}; use rustc_span::def_id::LocalDefId; use rustc_span::{ - BytePos, DUMMY_SP, DesugaringKind, ErrorGuaranteed, Ident, Span, Spanned, Symbol, kw, sym, + BytePos, DUMMY_SP, DesugaringKind, ErrorGuaranteed, Ident, LocalExpnId, Span, Spanned, Symbol, + kw, sym, }; use rustc_target::asm::InlineAsmRegOrRegClass; use smallvec::SmallVec; @@ -3875,6 +3876,7 @@ pub struct DelegationInfo { pub child_args_segment_id: Option, pub self_ty_id: Option, pub propagate_self_ty: bool, + pub group_id: Option<(LocalExpnId, bool /* unused_target_expr */)>, } #[derive(Debug, Clone, Copy, PartialEq, Eq, StableHash)] diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs index 4e5908c4d8885..0f0449c0aa9b3 100644 --- a/compiler/rustc_hir_analysis/src/delegation.rs +++ b/compiler/rustc_hir_analysis/src/delegation.rs @@ -5,9 +5,9 @@ use std::debug_assert_matches; use rustc_data_structures::fx::FxHashMap; +use rustc_hir::PathSegment; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{DelegationInfo, PathSegment}; use rustc_middle::ty::{ self, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; @@ -71,19 +71,6 @@ enum SelfPositionKind { None, } -pub fn opt_get_delegation_info( - tcx: TyCtxt<'_>, - delegation_id: LocalDefId, -) -> Option<&DelegationInfo> { - tcx.hir_node(tcx.local_def_id_to_hir_id(delegation_id)) - .fn_sig() - .and_then(|sig| sig.decl.opt_delegation_info()) -} - -fn get_delegation_info(tcx: TyCtxt<'_>, delegation_id: LocalDefId) -> &DelegationInfo { - opt_get_delegation_info(tcx, delegation_id).expect("processing delegation") -} - fn create_self_position_kind( tcx: TyCtxt<'_>, delegation_id: LocalDefId, @@ -96,7 +83,7 @@ fn create_self_position_kind( | (FnKind::AssocTrait, FnKind::Free) => SelfPositionKind::Zero, (FnKind::Free, FnKind::AssocTrait) => { - let propagate_self_ty = get_delegation_info(tcx, delegation_id).propagate_self_ty; + let propagate_self_ty = tcx.hir_delegation_info(delegation_id).propagate_self_ty; SelfPositionKind::AfterLifetimes(propagate_self_ty) } @@ -282,7 +269,7 @@ fn get_parent_and_inheritance_kind<'tcx>( } fn get_delegation_self_ty_or_err(tcx: TyCtxt<'_>, delegation_id: LocalDefId) -> Ty<'_> { - get_delegation_info(tcx, delegation_id) + tcx.hir_delegation_info(delegation_id) .self_ty_id .map(|id| { let ctx = ItemCtxt::new(tcx, delegation_id); @@ -644,7 +631,7 @@ pub(crate) fn delegation_user_specified_args<'tcx>( tcx: TyCtxt<'tcx>, delegation_id: LocalDefId, ) -> (&'tcx [ty::GenericArg<'tcx>], &'tcx [ty::GenericArg<'tcx>]) { - let info = get_delegation_info(tcx, delegation_id); + let info = tcx.hir_delegation_info(delegation_id); let get_segment = |hir_id| -> Option<(&'tcx PathSegment<'tcx>, DefId)> { let segment = tcx.hir_node(hir_id).expect_path_segment(); diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index e70936972e7c7..b6773747b563b 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -7,7 +7,6 @@ use rustc_hir::def::{self, CtorKind, Namespace, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, HirId, LangItem, find_attr}; use rustc_hir_analysis::autoderef::Autoderef; -use rustc_hir_analysis::delegation::opt_get_delegation_info; use rustc_infer::infer::BoundRegionConversionTime; use rustc_infer::traits::{Obligation, ObligationCause, ObligationCauseCode}; use rustc_middle::ty::adjustment::{ @@ -701,7 +700,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // by comparing their hir ids (otherwise we will encounter errors in nested delegations, // see tests\ui\delegation\impl-reuse-pass.rs:237). let parent_def = self.tcx.hir_get_parent_item(call_expr.hir_id).def_id; - let Some(info) = opt_get_delegation_info(self.tcx, parent_def) else { return None }; + let Some(info) = self.tcx.hir_opt_delegation_info(parent_def) else { + return None; + }; if call_expr.hir_id != info.call_expr_id { return None; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index d62ba9cf804eb..f3bf57ab4cd34 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -13,7 +13,6 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; use rustc_hir::{Expr, ExprKind, FnRetTy, HirId, LangItem, Node, QPath, is_range_literal}; use rustc_hir_analysis::check::potentially_plural_count; -use rustc_hir_analysis::delegation::opt_get_delegation_info; use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, ResolvedStructPath}; use rustc_index::IndexVec; use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk, TypeTrace}; @@ -341,7 +340,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If we are processing first arg of delegation then we could have adjusted it // in `execute_delegation_aware_arguments_check`. - let checked_ty = opt_get_delegation_info(self.tcx, self.body_id) + let checked_ty = self + .tcx + .hir_opt_delegation_info(self.body_id) .and_then(|_| self.typeck_results.borrow().node_type_opt(provided_arg.hir_id)) .unwrap_or_else(|| self.check_expr_with_expectation(provided_arg, expectation)); diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index df6f2909796ee..62cdc2ca60f34 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -1083,6 +1083,8 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { // to use `hir_crate_items`. tcx.ensure_done().hir_crate_items(()); + rustc_passes::delegation::check_glob_and_list_delegations_target_expr(tcx); + let sess = tcx.sess; sess.time("misc_checking_1", || { par_fns(&mut [ diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index 232a4e6c2f77b..046221b648fc3 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -865,6 +865,14 @@ impl<'tcx> TyCtxt<'tcx> { self.opt_hir_owner_node(def_id)?.fn_decl()?.opt_delegation_sig_id() } + pub fn hir_opt_delegation_info(self, def_id: LocalDefId) -> Option<&'tcx DelegationInfo> { + self.opt_hir_owner_node(def_id)?.fn_decl()?.opt_delegation_info() + } + + pub fn hir_delegation_info(self, delegation_id: LocalDefId) -> &'tcx DelegationInfo { + self.hir_opt_delegation_info(delegation_id).expect("processing delegation") + } + #[inline] fn hir_opt_ident(self, id: HirId) -> Option { match self.hir_node(id) { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 8ea14b0c5a28b..390e75e5087de 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -201,6 +201,9 @@ pub struct ResolverGlobalCtxt { pub doc_link_traits_in_scope: FxIndexMap>, pub all_macro_rules: UnordSet, pub stripped_cfg_items: Vec, + // Information about delegations which is used when handling recursive delegations + // and ensures easy access to delegation-only `LocalDefId`s. + pub delegation_infos: FxIndexMap, } #[derive(Debug)] @@ -257,13 +260,10 @@ pub struct ResolverAstLowering<'tcx> { /// Lints that were emitted by the resolver and early lints. pub lint_buffer: Steal, - // Information about delegations which is used when handling recursive delegations - pub delegation_infos: LocalDefIdMap, - pub disambiguators: LocalDefIdMap>, } -#[derive(Debug)] +#[derive(Debug, StableHash)] pub struct DelegationInfo { // `DefId` (either the resolution at delegation.id or item_id in case of a trait impl) for signature resolution, // for details see https://github.com/rust-lang/rust/issues/118212#issuecomment-2160686914 diff --git a/compiler/rustc_passes/src/delegation.rs b/compiler/rustc_passes/src/delegation.rs new file mode 100644 index 0000000000000..5b2267efbccd8 --- /dev/null +++ b/compiler/rustc_passes/src/delegation.rs @@ -0,0 +1,32 @@ +use rustc_data_structures::fx::FxIndexMap; +use rustc_macros::Diagnostic; +use rustc_middle::ty::TyCtxt; +use rustc_span::Span; + +pub fn check_glob_and_list_delegations_target_expr(tcx: TyCtxt<'_>) { + let mut delegations_by_group_id = FxIndexMap::default(); + + for &id in tcx.resolutions(()).delegation_infos.keys() { + if let Some(info) = tcx.hir_opt_delegation_info(id) + && let Some((group_id, unused_target_expr)) = info.group_id + { + delegations_by_group_id + .entry(group_id) + .or_insert_with(|| (true, tcx.def_span(id))) + .0 &= unused_target_expr; + } + } + + for (_, (unused_target_expr, span)) in delegations_by_group_id { + if unused_target_expr { + tcx.dcx().emit_err(DelegationTargetExprDeletedEverywhere { span }); + } + } +} + +#[derive(Diagnostic)] +#[diag("unused target expression is specified for glob or list delegation")] +struct DelegationTargetExprDeletedEverywhere { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index dea57cf4eba51..b51934cab90c4 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -11,6 +11,7 @@ mod check_attr; mod check_export; pub mod dead; mod debugger_visualizer; +pub mod delegation; mod diagnostic_items; mod eii; pub mod entry; diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 090722c496fd8..b8ab618673aa9 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1506,7 +1506,7 @@ pub struct Resolver<'ra, 'tcx> { /// Generic args to suggest for required params (e.g. `<'_>`, `<_, _>`), if any. item_required_generic_args_suggestions: FxHashMap = default::fx_hash_map(), delegation_fn_sigs: LocalDefIdMap = Default::default(), - delegation_infos: LocalDefIdMap = Default::default(), + delegation_infos: FxIndexMap, main_def: Option = None, trait_impls: FxIndexMap>, @@ -1871,6 +1871,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { doc_link_traits_in_scope: Default::default(), current_crate_outer_attr_insert_span, disambiguators: Default::default(), + delegation_infos: Default::default(), .. }; @@ -1991,6 +1992,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { doc_link_traits_in_scope: self.doc_link_traits_in_scope, all_macro_rules: self.all_macro_rules, stripped_cfg_items, + delegation_infos: self.delegation_infos, }; let ast_lowering = ty::ResolverAstLowering { partial_res_map: self.partial_res_map, @@ -1998,7 +2000,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { next_node_id: self.next_node_id, owners: self.owners, lint_buffer: Steal::new(self.lint_buffer), - delegation_infos: self.delegation_infos, disambiguators, }; ResolverOutputs { global_ctxt, ast_lowering } diff --git a/tests/ui/delegation/self-coercion-static-free.rs b/tests/ui/delegation/self-coercion-static-free.rs index 2aeb5bd404991..408b29a12cde0 100644 --- a/tests/ui/delegation/self-coercion-static-free.rs +++ b/tests/ui/delegation/self-coercion-static-free.rs @@ -23,6 +23,7 @@ impl Trait for S { //~^ ERROR: mismatched types //~| ERROR: mismatched types //~| ERROR: mismatched types + //~| ERROR: unused target expression is specified for glob or list delegation let _ = self; S::static_self() } @@ -35,6 +36,7 @@ impl Trait for S1 { //~^ ERROR: mismatched types //~| ERROR: mismatched types //~| ERROR: mismatched types + //~| ERROR: unused target expression is specified for glob or list delegation let _ = self; S1::static_self() } diff --git a/tests/ui/delegation/self-coercion-static-free.stderr b/tests/ui/delegation/self-coercion-static-free.stderr index b61ec58ee715c..870bd6bf3073b 100644 --- a/tests/ui/delegation/self-coercion-static-free.stderr +++ b/tests/ui/delegation/self-coercion-static-free.stderr @@ -1,3 +1,15 @@ +error: unused target expression is specified for glob or list delegation + --> $DIR/self-coercion-static-free.rs:22:26 + | +LL | reuse ::{static_value, static_mut_ref, static_ref} { + | ^^^^^^^^^^^^ + +error: unused target expression is specified for glob or list delegation + --> $DIR/self-coercion-static-free.rs:35:26 + | +LL | reuse ::{static_value, static_mut_ref, static_ref} { + | ^^^^^^^^^^^^ + error[E0308]: mismatched types --> $DIR/self-coercion-static-free.rs:22:26 | @@ -48,7 +60,7 @@ LL | fn static_ref(_: &Self) -> i32 { 3 } | ^^^^^^^^^^ -------- error[E0308]: mismatched types - --> $DIR/self-coercion-static-free.rs:34:26 + --> $DIR/self-coercion-static-free.rs:35:26 | LL | reuse ::{static_value, static_mut_ref, static_ref} { | ^^^^^^^^^^^^ @@ -63,7 +75,7 @@ LL | fn static_value(_: Self) -> i32 { 1 } | ^^^^^^^^^^^^ ------- error[E0308]: mismatched types - --> $DIR/self-coercion-static-free.rs:34:40 + --> $DIR/self-coercion-static-free.rs:35:40 | LL | reuse ::{static_value, static_mut_ref, static_ref} { | ^^^^^^^^^^^^^^ @@ -80,7 +92,7 @@ LL | fn static_mut_ref(_: &mut Self) -> i32 { 2 } | ^^^^^^^^^^^^^^ ------------ error[E0308]: mismatched types - --> $DIR/self-coercion-static-free.rs:34:56 + --> $DIR/self-coercion-static-free.rs:35:56 | LL | reuse ::{static_value, static_mut_ref, static_ref} { | ^^^^^^^^^^ @@ -97,7 +109,7 @@ LL | fn static_ref(_: &Self) -> i32 { 3 } | ^^^^^^^^^^ -------- error[E0308]: mismatched types - --> $DIR/self-coercion-static-free.rs:50:43 + --> $DIR/self-coercion-static-free.rs:52:43 | LL | reuse to_reuse::{value, mut_ref, r#ref} { F } | ------- ^ expected `&mut _`, found `F` @@ -107,7 +119,7 @@ LL | reuse to_reuse::{value, mut_ref, r#ref} { F } = note: expected mutable reference `&mut _` found struct `F` note: function defined here - --> $DIR/self-coercion-static-free.rs:46:12 + --> $DIR/self-coercion-static-free.rs:48:12 | LL | pub fn mut_ref(_: &mut impl Trait) -> i32 { 2 } | ^^^^^^^ ------------------ @@ -117,7 +129,7 @@ LL | reuse to_reuse::{value, mut_ref, r#ref} { &mut F } | ++++ error[E0308]: mismatched types - --> $DIR/self-coercion-static-free.rs:50:43 + --> $DIR/self-coercion-static-free.rs:52:43 | LL | reuse to_reuse::{value, mut_ref, r#ref} { F } | ----- ^ expected `&_`, found `F` @@ -127,7 +139,7 @@ LL | reuse to_reuse::{value, mut_ref, r#ref} { F } = note: expected reference `&_` found struct `F` note: function defined here - --> $DIR/self-coercion-static-free.rs:47:12 + --> $DIR/self-coercion-static-free.rs:49:12 | LL | pub fn r#ref(_: &impl Trait) -> i32 { 3 } | ^^^^^ -------------- @@ -136,6 +148,6 @@ help: consider borrowing here LL | reuse to_reuse::{value, mut_ref, r#ref} { &F } | + -error: aborting due to 8 previous errors +error: aborting due to 10 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/delegation/unused-target-expr-in-glob-or-list.rs b/tests/ui/delegation/unused-target-expr-in-glob-or-list.rs new file mode 100644 index 0000000000000..72f82390b62be --- /dev/null +++ b/tests/ui/delegation/unused-target-expr-in-glob-or-list.rs @@ -0,0 +1,208 @@ +#![feature(fn_delegation)] + +pub trait Trait: Sized { + fn static_self() -> F { F } + fn static_self2() -> F { F } + + fn static_value(_: F) -> i32 { 1 } + fn static_mut_ref(_: &mut F) -> i32 { 2 } + fn static_ref(_: &F) -> i32 { 3 } +} + +#[derive(Default, Eq, PartialEq, Debug)] +pub struct F; +impl Trait for F {} + +struct S(F); +impl Trait for S { + reuse ::* { self.0 } + //~^ ERROR: unused target expression is specified for glob or list delegation +} + +struct S1(F); +impl S1 { + reuse ::* { self.0 } + //~^ ERROR: unused target expression is specified for glob or list delegation +} + +struct S2(F); +impl Trait for S2 { + reuse ::{static_self} { self.0 } + //~^ ERROR: unused target expression is specified for glob or list delegation +} + +struct S3(F); +impl Trait for S3 { + reuse ::{static_self, static_value} { self.0 } + //~^ ERROR: unused target expression is specified for glob or list delegation +} + +struct S4(F); +impl Trait for S4 { + reuse ::{static_self, static_value, static_mut_ref, static_ref} { self.0 } + //~^ ERROR: unused target expression is specified for glob or list delegation +} + +struct S5(F); +impl Trait for S5 { + reuse ::{static_self, static_value, static_mut_ref, static_ref} { } + //~^ ERROR: unused target expression is specified for glob or list delegation +} + +struct S6(F); +impl Trait for S6 { + // Error about unused target expression is not emitted when error delegation is generated. + reuse UnresolvedTrait::* { self.0 } + //~^ ERROR: cannot find type `UnresolvedTrait` in this scope +} + +struct S7(F); +impl Trait for S7 { + reuse ::*; +} + +struct S8(F); +impl Trait for S8 { + reuse ::{static_self, static_self2} { { F } } + //~^ ERROR: unused target expression is specified for glob or list delegation +} + +struct S9; +impl S9 { + reuse ::{static_self, static_self2} { { F } } + //~^ ERROR: unused target expression is specified for glob or list delegation + + reuse ::{static_value, static_mut_ref, static_ref} { } + //~^ ERROR: unused target expression is specified for glob or list delegation +} + +trait Trait2 { + reuse ::{static_self, static_self2} { { F } } + //~^ ERROR: unused target expression is specified for glob or list delegation + + reuse ::{static_value, static_mut_ref} { } + //~^ ERROR: unused target expression is specified for glob or list delegation + + reuse ::{static_ref}; +} + +mod free_to_trait1 { + use super::{F, Trait}; + + reuse ::{static_self, static_self2} { { F } } + //~^ ERROR: unused target expression is specified for glob or list delegation + + reuse ::{static_value, static_mut_ref} { } + //~^ ERROR: unused target expression is specified for glob or list delegation + + reuse ::{static_ref}; +} + +mod macros { + use super::*; + + macro_rules! delegation { + () => { + impl Trait for S { + reuse ::static_self { self.0 } + //~^ ERROR: delegation's target expression is specified for function with no params + //~| ERROR: mismatched types + //~| ERROR: this function takes 0 arguments but 1 argument was supplied + //~| ERROR: method `static_self` has an incompatible type for trait + reuse ::static_value { self.0 } + //~^ ERROR: no field `0` on type `F` + reuse ::static_mut_ref { self.0 } + //~^ ERROR: no field `0` on type `&mut F` + reuse ::static_ref { self.0 } + //~^ ERROR: no field `0` on type `&F` + } + }; + } + + struct S(F); + delegation!(); + + macro_rules! delegation2 { + () => { + reuse ::static_self { self.0 } + //~^ ERROR: delegation's target expression is specified for function with no params + //~| ERROR: mismatched types + //~| ERROR: this function takes 0 arguments but 1 argument was supplied + //~| ERROR: method `static_self` has an incompatible type for trait + reuse ::static_value { self.0 } + //~^ ERROR: no field `0` on type `F` + reuse ::static_mut_ref { self.0 } + //~^ ERROR: no field `0` on type `&mut F` + reuse ::static_ref { self.0 } + //~^ ERROR: no field `0` on type `&F` + }; + } + + struct S1(F); + impl Trait for S1 { + delegation2!(); + } +} + +mod free_list { + mod to_reuse { + pub fn value() -> i32 { 1 } + pub fn mut_ref() -> i32 { 2 } + pub fn r#ref() -> i32 { 3 } + } + + reuse to_reuse::{value, mut_ref, r#ref} { () } + //~^ ERROR: this function takes 0 arguments but 1 argument was supplied + //~| ERROR: this function takes 0 arguments but 1 argument was supplied + //~| ERROR: this function takes 0 arguments but 1 argument was supplied + //~| ERROR: mismatched types + //~| ERROR: mismatched types + //~| ERROR: mismatched types + //~| ERROR: delegation's target expression is specified for function with no params + //~| ERROR: delegation's target expression is specified for function with no params + //~| ERROR: delegation's target expression is specified for function with no params + + reuse to_reuse::{value as value2} { } + //~^ ERROR: this function takes 0 arguments but 1 argument was supplied + //~| ERROR: mismatched types + //~| ERROR: delegation's target expression is specified for function with no params +} + +mod to_free { + trait Trait { + fn value() -> i32 { 1 } + fn mut_ref() -> i32 { 2 } + fn r#ref() -> i32 { 3 } + } + + mod to_reuse { + pub fn value() -> i32 { 1 } + pub fn mut_ref() -> i32 { 2 } + pub fn r#ref() -> i32 { 3 } + } + + struct F; + impl Trait for F {} + + struct S(F); + impl Trait for S { + reuse to_reuse::{value, mut_ref, r#ref} { () } + //~^ ERROR: unused target expression is specified for glob or list delegation + } + + struct S2; + impl S2 { + reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } + //~^ ERROR: this function takes 0 arguments but 1 argument was supplied + //~| ERROR: this function takes 0 arguments but 1 argument was supplied + //~| ERROR: this function takes 0 arguments but 1 argument was supplied + //~| ERROR: mismatched types + //~| ERROR: mismatched types + //~| ERROR: mismatched types + //~| ERROR: delegation's target expression is specified for function with no params + //~| ERROR: delegation's target expression is specified for function with no params + //~| ERROR: delegation's target expression is specified for function with no params + } +} + +fn main() {} diff --git a/tests/ui/delegation/unused-target-expr-in-glob-or-list.stderr b/tests/ui/delegation/unused-target-expr-in-glob-or-list.stderr new file mode 100644 index 0000000000000..65091ac8b5d49 --- /dev/null +++ b/tests/ui/delegation/unused-target-expr-in-glob-or-list.stderr @@ -0,0 +1,569 @@ +error[E0433]: cannot find type `UnresolvedTrait` in this scope + --> $DIR/unused-target-expr-in-glob-or-list.rs:55:11 + | +LL | reuse UnresolvedTrait::* { self.0 } + | ^^^^^^^^^^^^^^^ use of undeclared type `UnresolvedTrait` + +error: delegation's target expression is specified for function with no params + --> $DIR/unused-target-expr-in-glob-or-list.rs:154:45 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { () } + | ^^^^^^ + +error: delegation's target expression is specified for function with no params + --> $DIR/unused-target-expr-in-glob-or-list.rs:154:45 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { () } + | ^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: delegation's target expression is specified for function with no params + --> $DIR/unused-target-expr-in-glob-or-list.rs:154:45 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { () } + | ^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: delegation's target expression is specified for function with no params + --> $DIR/unused-target-expr-in-glob-or-list.rs:165:39 + | +LL | reuse to_reuse::{value as value2} { } + | ^^^ + +error: delegation's target expression is specified for function with no params + --> $DIR/unused-target-expr-in-glob-or-list.rs:195:49 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } + | ^^^^^^^^^ + +error: delegation's target expression is specified for function with no params + --> $DIR/unused-target-expr-in-glob-or-list.rs:195:49 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } + | ^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: delegation's target expression is specified for function with no params + --> $DIR/unused-target-expr-in-glob-or-list.rs:195:49 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } + | ^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: delegation's target expression is specified for function with no params + --> $DIR/unused-target-expr-in-glob-or-list.rs:107:49 + | +LL | reuse ::static_self { self.0 } + | ^^^^^^^^^^ +... +LL | delegation!(); + | ------------- in this macro invocation + | + = note: this error originates in the macro `delegation` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: delegation's target expression is specified for function with no params + --> $DIR/unused-target-expr-in-glob-or-list.rs:127:45 + | +LL | reuse ::static_self { self.0 } + | ^^^^^^^^^^ +... +LL | delegation2!(); + | -------------- in this macro invocation + | + = note: this error originates in the macro `delegation2` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unused target expression is specified for glob or list delegation + --> $DIR/unused-target-expr-in-glob-or-list.rs:18:25 + | +LL | reuse ::* { self.0 } + | ^ + +error: unused target expression is specified for glob or list delegation + --> $DIR/unused-target-expr-in-glob-or-list.rs:24:25 + | +LL | reuse ::* { self.0 } + | ^ + +error: unused target expression is specified for glob or list delegation + --> $DIR/unused-target-expr-in-glob-or-list.rs:30:26 + | +LL | reuse ::{static_self} { self.0 } + | ^^^^^^^^^^^ + +error: unused target expression is specified for glob or list delegation + --> $DIR/unused-target-expr-in-glob-or-list.rs:36:26 + | +LL | reuse ::{static_self, static_value} { self.0 } + | ^^^^^^^^^^^ + +error: unused target expression is specified for glob or list delegation + --> $DIR/unused-target-expr-in-glob-or-list.rs:42:26 + | +LL | reuse ::{static_self, static_value, static_mut_ref, static_ref} { self.0 } + | ^^^^^^^^^^^ + +error: unused target expression is specified for glob or list delegation + --> $DIR/unused-target-expr-in-glob-or-list.rs:48:26 + | +LL | reuse ::{static_self, static_value, static_mut_ref, static_ref} { } + | ^^^^^^^^^^^ + +error: unused target expression is specified for glob or list delegation + --> $DIR/unused-target-expr-in-glob-or-list.rs:66:26 + | +LL | reuse ::{static_self, static_self2} { { F } } + | ^^^^^^^^^^^ + +error: unused target expression is specified for glob or list delegation + --> $DIR/unused-target-expr-in-glob-or-list.rs:72:26 + | +LL | reuse ::{static_self, static_self2} { { F } } + | ^^^^^^^^^^^ + +error: unused target expression is specified for glob or list delegation + --> $DIR/unused-target-expr-in-glob-or-list.rs:75:26 + | +LL | reuse ::{static_value, static_mut_ref, static_ref} { } + | ^^^^^^^^^^^^ + +error: unused target expression is specified for glob or list delegation + --> $DIR/unused-target-expr-in-glob-or-list.rs:80:26 + | +LL | reuse ::{static_self, static_self2} { { F } } + | ^^^^^^^^^^^ + +error: unused target expression is specified for glob or list delegation + --> $DIR/unused-target-expr-in-glob-or-list.rs:83:26 + | +LL | reuse ::{static_value, static_mut_ref} { } + | ^^^^^^^^^^^^ + +error: unused target expression is specified for glob or list delegation + --> $DIR/unused-target-expr-in-glob-or-list.rs:92:26 + | +LL | reuse ::{static_self, static_self2} { { F } } + | ^^^^^^^^^^^ + +error: unused target expression is specified for glob or list delegation + --> $DIR/unused-target-expr-in-glob-or-list.rs:95:26 + | +LL | reuse ::{static_value, static_mut_ref} { } + | ^^^^^^^^^^^^ + +error: unused target expression is specified for glob or list delegation + --> $DIR/unused-target-expr-in-glob-or-list.rs:189:26 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { () } + | ^^^^^ + +error[E0053]: method `static_self` has an incompatible type for trait + --> $DIR/unused-target-expr-in-glob-or-list.rs:107:37 + | +LL | reuse ::static_self { self.0 } + | ^^^^^^^^^^^ expected `F`, found `()` +... +LL | delegation!(); + | ------------- in this macro invocation + | +note: type in trait + --> $DIR/unused-target-expr-in-glob-or-list.rs:4:25 + | +LL | fn static_self() -> F { F } + | ^ + = note: expected signature `fn() -> F` + found signature `fn() -> ()` + = note: this error originates in the macro `delegation` (in Nightly builds, run with -Z macro-backtrace for more info) +help: change the output type to match the trait + | +LL - reuse ::static_self { self.0 } +LL + reuse :: -> F { self.0 } + | + +error[E0053]: method `static_self` has an incompatible type for trait + --> $DIR/unused-target-expr-in-glob-or-list.rs:127:33 + | +LL | reuse ::static_self { self.0 } + | ^^^^^^^^^^^ expected `F`, found `()` +... +LL | delegation2!(); + | -------------- in this macro invocation + | +note: type in trait + --> $DIR/unused-target-expr-in-glob-or-list.rs:4:25 + | +LL | fn static_self() -> F { F } + | ^ + = note: expected signature `fn() -> F` + found signature `fn() -> ()` + = note: this error originates in the macro `delegation2` (in Nightly builds, run with -Z macro-backtrace for more info) +help: change the output type to match the trait + | +LL - reuse ::static_self { self.0 } +LL + reuse :: -> F { self.0 } + | + +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/unused-target-expr-in-glob-or-list.rs:107:37 + | +LL | reuse ::static_self { self.0 } + | ^^^^^^^^^^^ ---------- unexpected argument +... +LL | delegation!(); + | ------------- in this macro invocation + | +note: associated function defined here + --> $DIR/unused-target-expr-in-glob-or-list.rs:4:8 + | +LL | fn static_self() -> F { F } + | ^^^^^^^^^^^ + = note: this error originates in the macro `delegation` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/unused-target-expr-in-glob-or-list.rs:107:37 + | +LL | reuse ::static_self { self.0 } + | ^^^^^^^^^^^- help: consider using a semicolon here: `;` + | | + | expected `()`, found `F` + | expected `()` because of default return type +... +LL | delegation!(); + | ------------- in this macro invocation + | + = note: this error originates in the macro `delegation` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0609]: no field `0` on type `F` + --> $DIR/unused-target-expr-in-glob-or-list.rs:112:57 + | +LL | reuse ::static_value { self.0 } + | ^ unknown field +... +LL | delegation!(); + | ------------- in this macro invocation + | + = note: this error originates in the macro `delegation` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0609]: no field `0` on type `&mut F` + --> $DIR/unused-target-expr-in-glob-or-list.rs:114:59 + | +LL | reuse ::static_mut_ref { self.0 } + | ^ unknown field +... +LL | delegation!(); + | ------------- in this macro invocation + | + = note: this error originates in the macro `delegation` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0609]: no field `0` on type `&F` + --> $DIR/unused-target-expr-in-glob-or-list.rs:116:55 + | +LL | reuse ::static_ref { self.0 } + | ^ unknown field +... +LL | delegation!(); + | ------------- in this macro invocation + | + = note: this error originates in the macro `delegation` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/unused-target-expr-in-glob-or-list.rs:127:33 + | +LL | reuse ::static_self { self.0 } + | ^^^^^^^^^^^ ---------- unexpected argument +... +LL | delegation2!(); + | -------------- in this macro invocation + | +note: associated function defined here + --> $DIR/unused-target-expr-in-glob-or-list.rs:4:8 + | +LL | fn static_self() -> F { F } + | ^^^^^^^^^^^ + = note: this error originates in the macro `delegation2` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/unused-target-expr-in-glob-or-list.rs:127:33 + | +LL | reuse ::static_self { self.0 } + | ^^^^^^^^^^^- help: consider using a semicolon here: `;` + | | + | expected `()`, found `F` + | expected `()` because of default return type +... +LL | delegation2!(); + | -------------- in this macro invocation + | + = note: this error originates in the macro `delegation2` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0609]: no field `0` on type `F` + --> $DIR/unused-target-expr-in-glob-or-list.rs:132:53 + | +LL | reuse ::static_value { self.0 } + | ^ unknown field +... +LL | delegation2!(); + | -------------- in this macro invocation + | + = note: this error originates in the macro `delegation2` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0609]: no field `0` on type `&mut F` + --> $DIR/unused-target-expr-in-glob-or-list.rs:134:55 + | +LL | reuse ::static_mut_ref { self.0 } + | ^ unknown field +... +LL | delegation2!(); + | -------------- in this macro invocation + | + = note: this error originates in the macro `delegation2` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0609]: no field `0` on type `&F` + --> $DIR/unused-target-expr-in-glob-or-list.rs:136:51 + | +LL | reuse ::static_ref { self.0 } + | ^ unknown field +... +LL | delegation2!(); + | -------------- in this macro invocation + | + = note: this error originates in the macro `delegation2` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/unused-target-expr-in-glob-or-list.rs:154:22 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { () } + | ^^^^^ ------ unexpected argument of type `()` + | +note: function defined here + --> $DIR/unused-target-expr-in-glob-or-list.rs:149:16 + | +LL | pub fn value() -> i32 { 1 } + | ^^^^^ +help: remove the extra argument + | +LL - reuse to_reuse::{value, mut_ref, r#ref} { () } +LL + reuse to_reuse::{valu{ () } + | + +error[E0308]: mismatched types + --> $DIR/unused-target-expr-in-glob-or-list.rs:154:22 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { () } + | ^^^^^ expected `()`, found `i32` + | +help: consider using a semicolon here + | +LL | reuse to_reuse::{value;, mut_ref, r#ref} { () } + | + +help: try adding a return type + | +LL - reuse to_reuse::{value, mut_ref, r#ref} { () } +LL + reuse to_reuse::{ -> i32, mut_ref, r#ref} { () } + | + +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/unused-target-expr-in-glob-or-list.rs:154:29 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { () } + | ^^^^^^^ ------ unexpected argument of type `()` + | +note: function defined here + --> $DIR/unused-target-expr-in-glob-or-list.rs:150:16 + | +LL | pub fn mut_ref() -> i32 { 2 } + | ^^^^^^^ +help: remove the extra argument + | +LL - reuse to_reuse::{value, mut_ref, r#ref} { () } +LL + reuse to_reuse::{value, mut_re{ () } + | + +error[E0308]: mismatched types + --> $DIR/unused-target-expr-in-glob-or-list.rs:154:29 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { () } + | ^^^^^^^ expected `()`, found `i32` + | +help: consider using a semicolon here + | +LL | reuse to_reuse::{value, mut_ref;, r#ref} { () } + | + +help: try adding a return type + | +LL - reuse to_reuse::{value, mut_ref, r#ref} { () } +LL + reuse to_reuse::{value, -> i32, r#ref} { () } + | + +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/unused-target-expr-in-glob-or-list.rs:154:38 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { () } + | ^^^^^ ------ unexpected argument of type `()` + | +note: function defined here + --> $DIR/unused-target-expr-in-glob-or-list.rs:151:16 + | +LL | pub fn r#ref() -> i32 { 3 } + | ^^^^^ +help: remove the extra argument + | +LL - reuse to_reuse::{value, mut_ref, r#ref} { () } +LL + reuse to_reuse::{value, mut_ref, r#re{ () } + | + +error[E0308]: mismatched types + --> $DIR/unused-target-expr-in-glob-or-list.rs:154:38 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { () } + | ^^^^^ expected `()`, found `i32` + | +help: consider using a semicolon here + | +LL | reuse to_reuse::{value, mut_ref, r#ref;} { () } + | + +help: try adding a return type + | +LL - reuse to_reuse::{value, mut_ref, r#ref} { () } +LL + reuse to_reuse::{value, mut_ref, -> i32} { () } + | + +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/unused-target-expr-in-glob-or-list.rs:165:22 + | +LL | reuse to_reuse::{value as value2} { } + | ^^^^^ --- unexpected argument of type `()` + | +note: function defined here + --> $DIR/unused-target-expr-in-glob-or-list.rs:149:16 + | +LL | pub fn value() -> i32 { 1 } + | ^^^^^ +help: remove the extra argument + | +LL - reuse to_reuse::{value as value2} { } +LL + reuse to_reuse::{valu{ } + | + +error[E0308]: mismatched types + --> $DIR/unused-target-expr-in-glob-or-list.rs:165:22 + | +LL | reuse to_reuse::{value as value2} { } + | ^^^^^ expected `()`, found `i32` + | +help: consider using a semicolon here + | +LL | reuse to_reuse::{value; as value2} { } + | + +help: try adding a return type + | +LL - reuse to_reuse::{value as value2} { } +LL + reuse to_reuse::{ -> i32 as value2} { } + | + +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/unused-target-expr-in-glob-or-list.rs:195:26 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } + | ^^^^^ --------- unexpected argument of type `{integer}` + | +note: function defined here + --> $DIR/unused-target-expr-in-glob-or-list.rs:179:16 + | +LL | pub fn value() -> i32 { 1 } + | ^^^^^ +help: remove the extra argument + | +LL - reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } +LL + reuse to_reuse::{valu{ 1 + 1 } + | + +error[E0308]: mismatched types + --> $DIR/unused-target-expr-in-glob-or-list.rs:195:26 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } + | ^^^^^ expected `()`, found `i32` + | +help: consider using a semicolon here + | +LL | reuse to_reuse::{value;, mut_ref, r#ref} { 1 + 1 } + | + +help: try adding a return type + | +LL - reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } +LL + reuse to_reuse::{ -> i32, mut_ref, r#ref} { 1 + 1 } + | + +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/unused-target-expr-in-glob-or-list.rs:195:33 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } + | ^^^^^^^ --------- unexpected argument of type `{integer}` + | +note: function defined here + --> $DIR/unused-target-expr-in-glob-or-list.rs:180:16 + | +LL | pub fn mut_ref() -> i32 { 2 } + | ^^^^^^^ +help: remove the extra argument + | +LL - reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } +LL + reuse to_reuse::{value, mut_re{ 1 + 1 } + | + +error[E0308]: mismatched types + --> $DIR/unused-target-expr-in-glob-or-list.rs:195:33 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } + | ^^^^^^^ expected `()`, found `i32` + | +help: consider using a semicolon here + | +LL | reuse to_reuse::{value, mut_ref;, r#ref} { 1 + 1 } + | + +help: try adding a return type + | +LL - reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } +LL + reuse to_reuse::{value, -> i32, r#ref} { 1 + 1 } + | + +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/unused-target-expr-in-glob-or-list.rs:195:42 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } + | ^^^^^ --------- unexpected argument of type `{integer}` + | +note: function defined here + --> $DIR/unused-target-expr-in-glob-or-list.rs:181:16 + | +LL | pub fn r#ref() -> i32 { 3 } + | ^^^^^ +help: remove the extra argument + | +LL - reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } +LL + reuse to_reuse::{value, mut_ref, r#re{ 1 + 1 } + | + +error[E0308]: mismatched types + --> $DIR/unused-target-expr-in-glob-or-list.rs:195:42 + | +LL | reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } + | ^^^^^ expected `()`, found `i32` + | +help: consider using a semicolon here + | +LL | reuse to_reuse::{value, mut_ref, r#ref;} { 1 + 1 } + | + +help: try adding a return type + | +LL - reuse to_reuse::{value, mut_ref, r#ref} { 1 + 1 } +LL + reuse to_reuse::{value, mut_ref, -> i32} { 1 + 1 } + | + +error: aborting due to 50 previous errors + +Some errors have detailed explanations: E0053, E0061, E0308, E0433, E0609. +For more information about an error, try `rustc --explain E0053`. From 6a0f2d4772b5d806d8b98d4409f4acf06d1e3554 Mon Sep 17 00:00:00 2001 From: Orson Peters Date: Wed, 10 Jun 2026 14:21:24 +0200 Subject: [PATCH 49/59] Fix doc link to Instant sub in saturating caveat --- library/std/src/time.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/std/src/time.rs b/library/std/src/time.rs index 4dda8061a11a9..5566c497e06cb 100644 --- a/library/std/src/time.rs +++ b/library/std/src/time.rs @@ -137,9 +137,9 @@ use crate::sys::{FromInner, IntoInner, time}; /// if available, which is the case for all [tier 1] platforms. /// In practice such guarantees are – under rare circumstances – broken by hardware, virtualization /// or operating system bugs. To work around these bugs and platforms not offering monotonic clocks -/// [`duration_since`], [`elapsed`] and [`sub`] saturate to zero. In older Rust versions this -/// lead to a panic instead. [`checked_duration_since`] can be used to detect and handle situations -/// where monotonicity is violated, or `Instant`s are subtracted in the wrong order. +/// [`duration_since`], [`elapsed`] and [`sub`](#impl-Sub-for-Instant) saturate to zero. In older +/// Rust versions this lead to a panic instead. [`checked_duration_since`] can be used to detect and +/// handle situations where monotonicity is violated, or `Instant`s are subtracted in the wrong order. /// /// This workaround obscures programming errors where earlier and later instants are accidentally /// swapped. For this reason future Rust versions may reintroduce panics. From f5e570935d41f20732a7535fe333be87fd75150d Mon Sep 17 00:00:00 2001 From: Ohad Ravid Date: Tue, 9 Jun 2026 10:22:23 -0700 Subject: [PATCH 50/59] Only register the `atexit` hook when `cleanup` is unloadable --- .../std/src/sys/pal/windows/c/bindings.txt | 3 ++ .../std/src/sys/pal/windows/c/windows_sys.rs | 3 ++ .../std/src/sys/thread_local/guard/windows.rs | 50 +++++++++++++++++-- library/std/src/thread/local.rs | 4 +- .../dynamic-loading-cdylib/load_and_unload.rs | 14 +++++- .../output_load_only_unix.txt | 12 +++++ .../output_load_only_windows.txt | 12 +++++ ...output_unix.txt => output_unload_unix.txt} | 1 + ..._windows.txt => output_unload_windows.txt} | 1 + .../run-make/dynamic-loading-cdylib/rmake.rs | 24 +++++---- 10 files changed, 106 insertions(+), 18 deletions(-) create mode 100644 tests/run-make/dynamic-loading-cdylib/output_load_only_unix.txt create mode 100644 tests/run-make/dynamic-loading-cdylib/output_load_only_windows.txt rename tests/run-make/dynamic-loading-cdylib/{output_unix.txt => output_unload_unix.txt} (93%) rename tests/run-make/dynamic-loading-cdylib/{output_windows.txt => output_unload_windows.txt} (93%) diff --git a/library/std/src/sys/pal/windows/c/bindings.txt b/library/std/src/sys/pal/windows/c/bindings.txt index 50ea67a5609e8..ac1603020312f 100644 --- a/library/std/src/sys/pal/windows/c/bindings.txt +++ b/library/std/src/sys/pal/windows/c/bindings.txt @@ -2154,6 +2154,8 @@ GENERIC_ALL GENERIC_EXECUTE GENERIC_READ GENERIC_WRITE +GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS +GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT GetActiveProcessorCount getaddrinfo GetCommandLineW @@ -2178,6 +2180,7 @@ GetFullPathNameW GetLastError GetModuleFileNameW GetModuleHandleA +GetModuleHandleExW GetModuleHandleW GetOverlappedResult getpeername diff --git a/library/std/src/sys/pal/windows/c/windows_sys.rs b/library/std/src/sys/pal/windows/c/windows_sys.rs index d4e522b8491b1..2348f890d8a1d 100644 --- a/library/std/src/sys/pal/windows/c/windows_sys.rs +++ b/library/std/src/sys/pal/windows/c/windows_sys.rs @@ -56,6 +56,7 @@ windows_link::link!("kernel32.dll" "system" fn GetFullPathNameW(lpfilename : PCW windows_link::link!("kernel32.dll" "system" fn GetLastError() -> WIN32_ERROR); windows_link::link!("kernel32.dll" "system" fn GetModuleFileNameW(hmodule : HMODULE, lpfilename : PWSTR, nsize : u32) -> u32); windows_link::link!("kernel32.dll" "system" fn GetModuleHandleA(lpmodulename : PCSTR) -> HMODULE); +windows_link::link!("kernel32.dll" "system" fn GetModuleHandleExW(dwflags : u32, lpmodulename : PCWSTR, phmodule : *mut HMODULE) -> BOOL); windows_link::link!("kernel32.dll" "system" fn GetModuleHandleW(lpmodulename : PCWSTR) -> HMODULE); windows_link::link!("kernel32.dll" "system" fn GetOverlappedResult(hfile : HANDLE, lpoverlapped : *const OVERLAPPED, lpnumberofbytestransferred : *mut u32, bwait : BOOL) -> BOOL); windows_link::link!("kernel32.dll" "system" fn GetProcAddress(hmodule : HMODULE, lpprocname : PCSTR) -> FARPROC); @@ -2716,6 +2717,8 @@ pub const GENERIC_EXECUTE: GENERIC_ACCESS_RIGHTS = 536870912u32; pub const GENERIC_READ: GENERIC_ACCESS_RIGHTS = 2147483648u32; pub const GENERIC_WRITE: GENERIC_ACCESS_RIGHTS = 1073741824u32; pub type GETFINALPATHNAMEBYHANDLE_FLAGS = u32; +pub const GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS: u32 = 4u32; +pub const GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT: u32 = 2u32; #[repr(C)] #[derive(Clone, Copy)] pub struct GUID { diff --git a/library/std/src/sys/thread_local/guard/windows.rs b/library/std/src/sys/thread_local/guard/windows.rs index 7a9c69ae43784..1b4b87360c1c0 100644 --- a/library/std/src/sys/thread_local/guard/windows.rs +++ b/library/std/src/sys/thread_local/guard/windows.rs @@ -159,9 +159,11 @@ pub fn enable() { // // Miri has no DLL unloading so we can skip this step here. if !cfg!(miri) { - let res = unsafe { c::atexit(free_fls_key_at_exit) }; - if res != 0 { - rtabort!("failed to register fls atexit hook"); + if cleanup_is_unloadable() { + let res = unsafe { c::atexit(free_fls_key_at_exit) }; + if res != 0 { + rtabort!("failed to register fls atexit hook"); + } } } @@ -179,6 +181,48 @@ pub fn enable() { } } +/// Checks if `cleanup` is in a different module from the main executable, +/// using `GetModuleHandleExW(FLAG_FROM_ADDRESS, cleanup) != GetModuleHandleW(ptr::null())`. +/// +/// If `cleanup` lives in the main executable, its code cannot be unmapped +/// before process exit, so no unload hook is needed. +/// +/// If it lives in a DLL, the DLL may be unloaded while the process keeps +/// running, so the FLS callback must be unregistered before that image is +/// unmapped. +/// +/// On failure, return true, which assumes it can be unloaded. +fn cleanup_is_unloadable() -> bool { + // Get a handle to the module of `cleanup`. + let cleanup_module = { + let mut handle: c::HMODULE = ptr::null_mut(); + + let res = unsafe { + c::GetModuleHandleExW( + c::GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS + | c::GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + cleanup as *const () as c::PCWSTR, + &mut handle, + ) + }; + + if res == c::FALSE || handle.is_null() { + return true; + } + + handle + }; + + // Get a handle to the file used to create the calling process (.exe file). + let main_exe_module = unsafe { c::GetModuleHandleW(ptr::null()) }; + + if main_exe_module.is_null() { + return true; + } + + cleanup_module != main_exe_module +} + extern "C" fn free_fls_key_at_exit() { // The main purpose of this hook is to free the FLS slot during DLL unload. // However, this hook will also be called during normal process exit, while other Rust threads are still running, diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index b20dc21ac3c38..ec0ba9970e479 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -104,8 +104,8 @@ use crate::fmt; /// If a process loads a Rust `cdylib`, it must not cause the Rust TLS destructor support // to be initialized for the first time during process shutdown. /// -/// When dynamically unloading a Rust `cdylib`, threads with pending TLS destructors -/// may run during the unload or may be leaked. +/// When dynamically unloading a Rust `cdylib`, pending TLS destructors may run +// during the unload or may be leaked. /// /// [converted into a fiber]: https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-convertthreadtofiber /// [converted back into a thread]: https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-convertfibertothread diff --git a/tests/run-make/dynamic-loading-cdylib/load_and_unload.rs b/tests/run-make/dynamic-loading-cdylib/load_and_unload.rs index ec3c558156c7b..eb1baea93dc00 100644 --- a/tests/run-make/dynamic-loading-cdylib/load_and_unload.rs +++ b/tests/run-make/dynamic-loading-cdylib/load_and_unload.rs @@ -88,6 +88,9 @@ mod libloading { type ExternFn = unsafe extern "C" fn(u32, u32) -> u32; fn main() { + let args: Vec = std::env::args().collect(); + assert_eq!(args.len(), 2, "This program should be run with one argument"); + let foo = libloading::load("foo").expect("Failed to load library"); println!("loaded library"); @@ -110,6 +113,13 @@ fn main() { .expect("Thread panicked"); println!("thread joined"); - libloading::unload(foo); - println!("unloaded library"); + match args[1].as_str() { + "unload" => { + println!("unloading library"); + libloading::unload(foo); + println!("unloaded library"); + } + "load_only" => println!("dropping library handle without unloading"), + arg => panic!("unexpected argument: {}", arg), + } } diff --git a/tests/run-make/dynamic-loading-cdylib/output_load_only_unix.txt b/tests/run-make/dynamic-loading-cdylib/output_load_only_unix.txt new file mode 100644 index 0000000000000..7b799691056cf --- /dev/null +++ b/tests/run-make/dynamic-loading-cdylib/output_load_only_unix.txt @@ -0,0 +1,12 @@ +loaded library +extern_fn_1 +result of extern_fn_1(2, 3): 5 +extern_fn_2(2, 3) +result of extern_fn_2(2, 3): 6 +spawning thread +extern_fn_2(4, 5) +result of extern_fn_2(4, 5) in other thread: 20 +dropping, last result: 20 +thread joined +dropping library handle without unloading +dropping, last result: 6 diff --git a/tests/run-make/dynamic-loading-cdylib/output_load_only_windows.txt b/tests/run-make/dynamic-loading-cdylib/output_load_only_windows.txt new file mode 100644 index 0000000000000..7b799691056cf --- /dev/null +++ b/tests/run-make/dynamic-loading-cdylib/output_load_only_windows.txt @@ -0,0 +1,12 @@ +loaded library +extern_fn_1 +result of extern_fn_1(2, 3): 5 +extern_fn_2(2, 3) +result of extern_fn_2(2, 3): 6 +spawning thread +extern_fn_2(4, 5) +result of extern_fn_2(4, 5) in other thread: 20 +dropping, last result: 20 +thread joined +dropping library handle without unloading +dropping, last result: 6 diff --git a/tests/run-make/dynamic-loading-cdylib/output_unix.txt b/tests/run-make/dynamic-loading-cdylib/output_unload_unix.txt similarity index 93% rename from tests/run-make/dynamic-loading-cdylib/output_unix.txt rename to tests/run-make/dynamic-loading-cdylib/output_unload_unix.txt index 6e1736ca38d86..243707e73cb5e 100644 --- a/tests/run-make/dynamic-loading-cdylib/output_unix.txt +++ b/tests/run-make/dynamic-loading-cdylib/output_unload_unix.txt @@ -8,5 +8,6 @@ extern_fn_2(4, 5) result of extern_fn_2(4, 5) in other thread: 20 dropping, last result: 20 thread joined +unloading library unloaded library dropping, last result: 6 diff --git a/tests/run-make/dynamic-loading-cdylib/output_windows.txt b/tests/run-make/dynamic-loading-cdylib/output_unload_windows.txt similarity index 93% rename from tests/run-make/dynamic-loading-cdylib/output_windows.txt rename to tests/run-make/dynamic-loading-cdylib/output_unload_windows.txt index e87baf4b52110..d543bd317ec75 100644 --- a/tests/run-make/dynamic-loading-cdylib/output_windows.txt +++ b/tests/run-make/dynamic-loading-cdylib/output_unload_windows.txt @@ -8,5 +8,6 @@ extern_fn_2(4, 5) result of extern_fn_2(4, 5) in other thread: 20 dropping, last result: 20 thread joined +unloading library dropping, last result: 6 unloaded library diff --git a/tests/run-make/dynamic-loading-cdylib/rmake.rs b/tests/run-make/dynamic-loading-cdylib/rmake.rs index 2cf0ebfef4434..ffd91e4a6ebc0 100644 --- a/tests/run-make/dynamic-loading-cdylib/rmake.rs +++ b/tests/run-make/dynamic-loading-cdylib/rmake.rs @@ -7,23 +7,25 @@ //@ ignore-cross-compile -use run_make_support::{diff, run, rustc}; +use run_make_support::{diff, run_with_args, rustc}; fn main() { rustc().input("foo.rs").run(); rustc().crate_type("bin").crate_name("load_and_unload_bin").input("load_and_unload.rs").run(); - let out_raw = run("load_and_unload_bin").stdout_utf8(); + for command_arg in ["unload", "load_only"] { + let out_raw = run_with_args("load_and_unload_bin", &[command_arg]).stdout_utf8(); - #[cfg(windows)] - let output_filename = "output_windows.txt"; - #[cfg(unix)] - let output_filename = "output_unix.txt"; + #[cfg(windows)] + let output_filename = format!("output_{}_windows.txt", command_arg); + #[cfg(unix)] + let output_filename = format!("output_{}_unix.txt", command_arg); - diff() - .expected_file(output_filename) - .actual_text("actual", out_raw) - .normalize(r#"\r"#, "") - .run(); + diff() + .expected_file(output_filename) + .actual_text("actual", out_raw) + .normalize(r#"\r"#, "") + .run(); + } } From 88f3ac1b43dbdeb0da4357a14824f02ee6f08b60 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 8 Jun 2026 17:40:36 +0200 Subject: [PATCH 51/59] Manually download chrome instead of letting yarn/npm doing it --- src/ci/docker/host-x86_64/pr-check-1/Dockerfile | 2 ++ src/ci/docker/host-x86_64/tidy/Dockerfile | 2 ++ src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile | 11 +++++++++++ 3 files changed, 15 insertions(+) diff --git a/src/ci/docker/host-x86_64/pr-check-1/Dockerfile b/src/ci/docker/host-x86_64/pr-check-1/Dockerfile index a595a079b48f1..346ecb453f4d0 100644 --- a/src/ci/docker/host-x86_64/pr-check-1/Dockerfile +++ b/src/ci/docker/host-x86_64/pr-check-1/Dockerfile @@ -36,6 +36,8 @@ RUN pip3 install --no-deps --no-cache-dir --require-hashes -r /tmp/reuse-require COPY host-x86_64/pr-check-1/check-default-config-profiles.sh /scripts/ COPY host-x86_64/pr-check-1/validate-toolstate.sh /scripts/ +ENV PUPPETEER_SKIP_DOWNLOAD 1 + # Check library crates on all tier 1 targets. # We disable optimized compiler built-ins because that requires a C toolchain for the target. # We also skip the x86_64-unknown-linux-gnu target as it is well-tested by other jobs. diff --git a/src/ci/docker/host-x86_64/tidy/Dockerfile b/src/ci/docker/host-x86_64/tidy/Dockerfile index e84d61e0b99cc..0c6029a6a5442 100644 --- a/src/ci/docker/host-x86_64/tidy/Dockerfile +++ b/src/ci/docker/host-x86_64/tidy/Dockerfile @@ -24,6 +24,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ mingw-w64 \ && rm -rf /var/lib/apt/lists/* +ENV PUPPETEER_SKIP_DOWNLOAD 1 + COPY scripts/nodejs.sh /scripts/ RUN sh /scripts/nodejs.sh /node ENV PATH="/node/bin:${PATH}" diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile index 3eb424ceef4a3..f007024485b8b 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile @@ -56,6 +56,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ lsb-release \ xdg-utils \ wget \ + unzip \ # libgccjit dependencies flex \ libmpfr-dev \ @@ -72,6 +73,16 @@ ENV GCC_EXEC_PREFIX="/usr/lib/gcc/" COPY host-x86_64/x86_64-gnu-tools/checktools.sh /tmp/ +# The version used by current `browser-ui-test` version. To be removed once `yarn` can download +# it without failing... +RUN curl https://ci-mirrors.rust-lang.org/rustc/chrome-linux64.zip > chrome-linux64.zip +RUN unzip -d /usr/bin/ chrome-linux64.zip && rm chrome-linux64.zip + +# We already downloaded chromium so no need to download it again. +ENV PUPPETEER_SKIP_DOWNLOAD 1 +# We provide the path to the extracted chrome binary. +ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chrome-linux64/chrome + COPY scripts/nodejs.sh /scripts/ RUN sh /scripts/nodejs.sh /node ENV PATH="/node/bin:${PATH}" From cdb6acc4810adeff79d2fe92db8d0f7cdf2d1a2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=9D=E5=80=89=E6=B0=B4=E5=B8=8C?= Date: Tue, 9 Jun 2026 20:03:53 +0800 Subject: [PATCH 52/59] Reject static EII defaults on Apple targets --- compiler/rustc_builtin_macros/src/diagnostics.rs | 9 +++++++++ compiler/rustc_builtin_macros/src/eii.rs | 13 ++++++++++++- tests/ui/eii/static/auxiliary/decl_with_default.rs | 1 + .../eii/static/auxiliary/impl_default_override.rs | 1 + tests/ui/eii/static/default.rs | 2 ++ tests/ui/eii/static/default_apple.rs | 8 ++++++++ tests/ui/eii/static/default_apple.stderr | 10 ++++++++++ tests/ui/eii/static/default_cross_crate.rs | 2 ++ tests/ui/eii/static/default_cross_crate_explicit.rs | 2 ++ tests/ui/eii/static/default_explicit.rs | 2 ++ 10 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 tests/ui/eii/static/default_apple.rs create mode 100644 tests/ui/eii/static/default_apple.stderr diff --git a/compiler/rustc_builtin_macros/src/diagnostics.rs b/compiler/rustc_builtin_macros/src/diagnostics.rs index afd9aea3efe0c..6ae0f908a88a0 100644 --- a/compiler/rustc_builtin_macros/src/diagnostics.rs +++ b/compiler/rustc_builtin_macros/src/diagnostics.rs @@ -1134,6 +1134,15 @@ pub(crate) struct EiiStaticMultipleImplementations { pub span: Span, } +#[derive(Diagnostic)] +#[diag("`#[{$name}]` cannot be used on statics with a value on Apple targets")] +#[note("see issue #157649 for more information")] +pub(crate) struct EiiStaticDefaultApple { + #[primary_span] + pub span: Span, + pub name: String, +} + #[derive(Diagnostic)] #[diag("`#[{$name}]` requires the name as an explicit argument when used on a static")] pub(crate) struct EiiStaticArgumentRequired { diff --git a/compiler/rustc_builtin_macros/src/eii.rs b/compiler/rustc_builtin_macros/src/eii.rs index b482867582227..68d5278c85ef1 100644 --- a/compiler/rustc_builtin_macros/src/eii.rs +++ b/compiler/rustc_builtin_macros/src/eii.rs @@ -13,7 +13,7 @@ use crate::diagnostics::{ EiiAttributeNotSupported, EiiExternTargetExpectedList, EiiExternTargetExpectedMacro, EiiExternTargetExpectedUnsafe, EiiMacroExpectedMaxOneArgument, EiiOnlyOnce, EiiSharedMacroInStatementPosition, EiiSharedMacroTarget, EiiStaticArgumentRequired, - EiiStaticMultipleImplementations, EiiStaticMutable, + EiiStaticDefaultApple, EiiStaticMultipleImplementations, EiiStaticMutable, }; /// ```rust @@ -86,6 +86,17 @@ fn eii_( let (item_span, foreign_item_name) = match kind { ItemKind::Fn(func) => (func.sig.span, func.ident), ItemKind::Static(stat) => { + // See https://github.com/rust-lang/rust/issues/157649 + if let Some(expr) = &stat.expr + && ecx.sess.target.is_like_darwin + { + ecx.dcx().emit_err(EiiStaticDefaultApple { + span: expr.span, + name: path_to_string(&meta_item.path), + }); + return vec![]; + } + // Statics must have an explicit name for the eii if meta_item.is_word() { ecx.dcx().emit_err(EiiStaticArgumentRequired { diff --git a/tests/ui/eii/static/auxiliary/decl_with_default.rs b/tests/ui/eii/static/auxiliary/decl_with_default.rs index ba87b35deb457..53cdc8d62bb7e 100644 --- a/tests/ui/eii/static/auxiliary/decl_with_default.rs +++ b/tests/ui/eii/static/auxiliary/decl_with_default.rs @@ -1,3 +1,4 @@ +//@ no-prefer-dynamic #![crate_type = "rlib"] #![feature(extern_item_impls)] diff --git a/tests/ui/eii/static/auxiliary/impl_default_override.rs b/tests/ui/eii/static/auxiliary/impl_default_override.rs index d70a137fbc459..03cb061135e70 100644 --- a/tests/ui/eii/static/auxiliary/impl_default_override.rs +++ b/tests/ui/eii/static/auxiliary/impl_default_override.rs @@ -1,3 +1,4 @@ +//@ no-prefer-dynamic //@ aux-build: decl_with_default.rs #![crate_type = "rlib"] #![feature(extern_item_impls)] diff --git a/tests/ui/eii/static/default.rs b/tests/ui/eii/static/default.rs index 02307432e2f81..6234ee2f0c15e 100644 --- a/tests/ui/eii/static/default.rs +++ b/tests/ui/eii/static/default.rs @@ -3,6 +3,8 @@ //@ ignore-backends: gcc // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 //@ ignore-windows +// FIXME(#157649): static EII defaults currently fail to link on Apple targets. +//@ ignore-apple // Tests static EIIs with default implementations. #![feature(extern_item_impls)] diff --git a/tests/ui/eii/static/default_apple.rs b/tests/ui/eii/static/default_apple.rs new file mode 100644 index 0000000000000..f638ee480f4cb --- /dev/null +++ b/tests/ui/eii/static/default_apple.rs @@ -0,0 +1,8 @@ +//@ only-apple +//@ ignore-backends: gcc + +#![feature(extern_item_impls)] +#![crate_type = "lib"] +#[eii(eii1)] +pub static DECL1: u64 = 5; +//~^ ERROR `#[eii]` cannot be used on statics with a value on Apple targets diff --git a/tests/ui/eii/static/default_apple.stderr b/tests/ui/eii/static/default_apple.stderr new file mode 100644 index 0000000000000..d4ced5948970d --- /dev/null +++ b/tests/ui/eii/static/default_apple.stderr @@ -0,0 +1,10 @@ +error: `#[eii]` cannot be used on statics with a value on Apple targets + --> $DIR/default_apple.rs:7:25 + | +LL | pub static DECL1: u64 = 5; + | ^ + | + = note: see issue #157649 for more information + +error: aborting due to 1 previous error + diff --git a/tests/ui/eii/static/default_cross_crate.rs b/tests/ui/eii/static/default_cross_crate.rs index 4d6df4b7ee717..f9de906ac267e 100644 --- a/tests/ui/eii/static/default_cross_crate.rs +++ b/tests/ui/eii/static/default_cross_crate.rs @@ -4,6 +4,8 @@ //@ ignore-backends: gcc // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 //@ ignore-windows +// FIXME(#157649): static EII defaults currently fail to link on Apple targets. +//@ ignore-apple // Tests that a static EII default can be used from another crate. extern crate decl_with_default; diff --git a/tests/ui/eii/static/default_cross_crate_explicit.rs b/tests/ui/eii/static/default_cross_crate_explicit.rs index c3139f45d19c5..1f534e300e0c3 100644 --- a/tests/ui/eii/static/default_cross_crate_explicit.rs +++ b/tests/ui/eii/static/default_cross_crate_explicit.rs @@ -5,6 +5,8 @@ //@ ignore-backends: gcc // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 //@ ignore-windows +// FIXME(#157649): static EII defaults currently fail to link on Apple targets. +//@ ignore-apple // Tests that an explicit static EII implementation overrides a cross-crate default. extern crate decl_with_default; diff --git a/tests/ui/eii/static/default_explicit.rs b/tests/ui/eii/static/default_explicit.rs index b18da35c3debe..6cf36d8da50a5 100644 --- a/tests/ui/eii/static/default_explicit.rs +++ b/tests/ui/eii/static/default_explicit.rs @@ -3,6 +3,8 @@ //@ ignore-backends: gcc // FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 //@ ignore-windows +// FIXME(#157649): static EII defaults currently fail to link on Apple targets. +//@ ignore-apple // Tests that an explicit static EII implementation overrides a local default. #![feature(extern_item_impls)] From c13ed31ac67ed09cc1073069fe5bbc538e10eb58 Mon Sep 17 00:00:00 2001 From: Maximilian Azendorf Date: Tue, 9 Jun 2026 14:19:14 +0200 Subject: [PATCH 53/59] Keep rename-imported main alive in dead-code analysis under --test --- .../rustc_builtin_macros/src/test_harness.rs | 6 +++-- compiler/rustc_passes/src/dead.rs | 16 ++++++++++++++ compiler/rustc_session/src/session.rs | 5 +++++ .../imported_main_dead_code_under_test.rs | 13 +++++++++++ .../imported_main_glob_under_test.rs | 10 +++++++++ .../imported_main_path_under_test.rs | 10 +++++++++ ...ported_main_renamed_from_mod_under_test.rs | 11 ++++++++++ .../dead-code/lint-dead-code-2-under-test.rs | 22 +++++++++++++++++++ .../lint-dead-code-2-under-test.stderr | 20 +++++++++++++++++ .../submodule_main_not_entry_under_test.rs | 9 ++++++++ ...submodule_main_not_entry_under_test.stderr | 14 ++++++++++++ 11 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 tests/ui/lint/dead-code/imported_main_dead_code_under_test.rs create mode 100644 tests/ui/lint/dead-code/imported_main_glob_under_test.rs create mode 100644 tests/ui/lint/dead-code/imported_main_path_under_test.rs create mode 100644 tests/ui/lint/dead-code/imported_main_renamed_from_mod_under_test.rs create mode 100644 tests/ui/lint/dead-code/lint-dead-code-2-under-test.rs create mode 100644 tests/ui/lint/dead-code/lint-dead-code-2-under-test.stderr create mode 100644 tests/ui/lint/dead-code/submodule_main_not_entry_under_test.rs create mode 100644 tests/ui/lint/dead-code/submodule_main_not_entry_under_test.stderr diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index 0b68b44769987..e08fb81d4de68 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -1,6 +1,7 @@ // Code that generates a test runner to run all the tests in a crate use std::mem; +use std::sync::atomic::Ordering; use rustc_ast as ast; use rustc_ast::attr::contains_name; @@ -202,7 +203,7 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> { // clash with the one we're going to add, but mark it as // #[allow(dead_code)] to avoid printing warnings. match entry_point_type(&item, self.depth == 0) { - EntryPointType::MainNamed | EntryPointType::RustcMainAttr => { + EntryPointType::RustcMainAttr => { let allow_dead_code = attr::mk_attr_nested_word( &self.sess.psess.attr_id_generator, ast::AttrStyle::Outer, @@ -213,8 +214,9 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> { ); item.attrs.retain(|attr| !attr.has_name(sym::rustc_main)); item.attrs.push(allow_dead_code); + self.sess.removed_rustc_main_attr.store(true, Ordering::Relaxed); } - EntryPointType::None | EntryPointType::OtherMain => {} + EntryPointType::None | EntryPointType::MainNamed | EntryPointType::OtherMain => {} }; } } diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index b79460afad99e..59a347c9042bf 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -5,6 +5,7 @@ use std::mem; use std::ops::ControlFlow; +use std::sync::atomic::Ordering; use hir::def_id::{LocalDefIdMap, LocalDefIdSet}; use rustc_abi::FieldIdx; @@ -930,6 +931,21 @@ fn create_and_seed_worklist(tcx: TyCtxt<'_>) -> SeedWorklists { }); } + // Under `--test`, what `main` resolves to is the would-be entry point of a normal build, + // so keep it live, unless a stripped user `#[rustc_main]` would have been the entry instead. + if tcx.sess.is_test_crate() + && !tcx.sess.removed_rustc_main_attr.load(Ordering::Relaxed) + && let Some(main_def) = tcx.resolutions(()).main_def + && let Some(def_id) = main_def.opt_fn_def_id() + && let Some(local_def_id) = def_id.as_local() + { + worklist.push(WorkItem { + id: local_def_id, + propagated: ComesFromAllowExpect::No, + own: ComesFromAllowExpect::No, + }); + } + for (id, effective_vis) in tcx.effective_visibilities(()).iter() { if effective_vis.is_public_at_level(Level::Reachable) { deferred_seeds.push(WorkItem { diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 64818f0114b61..9f88161073b60 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -181,6 +181,10 @@ pub struct Session { /// /// The value is the `DepNodeIndex` of the node encodes the used feature. pub used_features: Lock>, + + /// Whether the test harness removed a user-written `#[rustc_main]` attribute + /// while generating the synthetic test entry point. + pub removed_rustc_main_attr: AtomicBool, } #[derive(Clone, Copy)] @@ -1133,6 +1137,7 @@ pub fn build_session( thin_lto_supported: true, // filled by `run_compiler` mir_opt_bisect_eval_count: AtomicUsize::new(0), used_features: Lock::default(), + removed_rustc_main_attr: AtomicBool::new(false), }; validate_commandline_args_with_session_available(&sess); diff --git a/tests/ui/lint/dead-code/imported_main_dead_code_under_test.rs b/tests/ui/lint/dead-code/imported_main_dead_code_under_test.rs new file mode 100644 index 0000000000000..ce8de2839780e --- /dev/null +++ b/tests/ui/lint/dead-code/imported_main_dead_code_under_test.rs @@ -0,0 +1,13 @@ +//@ check-pass +//@ compile-flags: --test + +// Regression test for https://github.com/rust-lang/rust/issues/157608: a function used +// as `main` via a rename import was wrongly reported as dead code under `--test`. + +#![deny(dead_code)] + +fn different_main() { + println!("Hello from different_main"); +} + +use different_main as main; diff --git a/tests/ui/lint/dead-code/imported_main_glob_under_test.rs b/tests/ui/lint/dead-code/imported_main_glob_under_test.rs new file mode 100644 index 0000000000000..95ed510e95e6f --- /dev/null +++ b/tests/ui/lint/dead-code/imported_main_glob_under_test.rs @@ -0,0 +1,10 @@ +//@ check-pass +//@ compile-flags: --test + +#![deny(dead_code)] + +mod m { + pub fn main() {} +} + +use m::*; diff --git a/tests/ui/lint/dead-code/imported_main_path_under_test.rs b/tests/ui/lint/dead-code/imported_main_path_under_test.rs new file mode 100644 index 0000000000000..70731cc0765b3 --- /dev/null +++ b/tests/ui/lint/dead-code/imported_main_path_under_test.rs @@ -0,0 +1,10 @@ +//@ check-pass +//@ compile-flags: --test + +#![deny(dead_code)] + +mod m { + pub fn main() {} +} + +use m::main; diff --git a/tests/ui/lint/dead-code/imported_main_renamed_from_mod_under_test.rs b/tests/ui/lint/dead-code/imported_main_renamed_from_mod_under_test.rs new file mode 100644 index 0000000000000..0e8875791950e --- /dev/null +++ b/tests/ui/lint/dead-code/imported_main_renamed_from_mod_under_test.rs @@ -0,0 +1,11 @@ +//@ check-pass +//@ compile-flags: --test + + +#![deny(dead_code)] + +mod m { + pub fn other() {} +} + +use m::other as main; diff --git a/tests/ui/lint/dead-code/lint-dead-code-2-under-test.rs b/tests/ui/lint/dead-code/lint-dead-code-2-under-test.rs new file mode 100644 index 0000000000000..1939070daac5a --- /dev/null +++ b/tests/ui/lint/dead-code/lint-dead-code-2-under-test.rs @@ -0,0 +1,22 @@ +//@ compile-flags: --test + +// A `fn main` demoted by an explicit `#[rustc_main]` on another function is dead code and +// must be flagged under `--test` just like in a normal build. + +#![allow(unused_variables)] +#![deny(dead_code)] +#![feature(rustc_attrs)] + +fn dead_fn() {} //~ ERROR: function `dead_fn` is never used + +fn used_fn() {} + +#[rustc_main] +fn actual_main() { + used_fn(); +} + +// this is not main +fn main() { //~ ERROR: function `main` is never used + dead_fn(); +} diff --git a/tests/ui/lint/dead-code/lint-dead-code-2-under-test.stderr b/tests/ui/lint/dead-code/lint-dead-code-2-under-test.stderr new file mode 100644 index 0000000000000..2c5fa7ea0aed6 --- /dev/null +++ b/tests/ui/lint/dead-code/lint-dead-code-2-under-test.stderr @@ -0,0 +1,20 @@ +error: function `dead_fn` is never used + --> $DIR/lint-dead-code-2-under-test.rs:10:4 + | +LL | fn dead_fn() {} + | ^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-dead-code-2-under-test.rs:7:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: function `main` is never used + --> $DIR/lint-dead-code-2-under-test.rs:20:4 + | +LL | fn main() { + | ^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/dead-code/submodule_main_not_entry_under_test.rs b/tests/ui/lint/dead-code/submodule_main_not_entry_under_test.rs new file mode 100644 index 0000000000000..3f46e6fa4601b --- /dev/null +++ b/tests/ui/lint/dead-code/submodule_main_not_entry_under_test.rs @@ -0,0 +1,9 @@ +//@ compile-flags: --test + +#![deny(dead_code)] + +fn main() {} + +mod m { + pub fn main() {} //~ ERROR: function `main` is never used +} diff --git a/tests/ui/lint/dead-code/submodule_main_not_entry_under_test.stderr b/tests/ui/lint/dead-code/submodule_main_not_entry_under_test.stderr new file mode 100644 index 0000000000000..3c68a3bb0a682 --- /dev/null +++ b/tests/ui/lint/dead-code/submodule_main_not_entry_under_test.stderr @@ -0,0 +1,14 @@ +error: function `main` is never used + --> $DIR/submodule_main_not_entry_under_test.rs:8:12 + | +LL | pub fn main() {} + | ^^^^ + | +note: the lint level is defined here + --> $DIR/submodule_main_not_entry_under_test.rs:3:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: aborting due to 1 previous error + From 1c511f41a3fcce7bff0792a3507076c923acc105 Mon Sep 17 00:00:00 2001 From: xmakro Date: Fri, 5 Jun 2026 06:22:20 -0700 Subject: [PATCH 54/59] compiletest: ignore SVG `y` offset in by-lines comparison --- src/tools/compiletest/src/runtest.rs | 27 +++++++++++++++---- .../compiletest/src/runtest/compute_diff.rs | 11 ++++---- .../multiline-removal-suggestion.rs | 1 - 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 27bbc56c36d1b..9645cf58ef92e 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2304,6 +2304,23 @@ impl<'test> TestCx<'test> { self.props.compile_flags.iter().any(|s| s.contains("--color=always")) } + /// Returns the lines for the by-lines comparison, normalized for the + /// parallel front-end: for SVG output, strip the header line and `y` + /// offsets; otherwise, filter out padded empty code lines (a single `|`). + fn lines_for_comparison(&self, output: &str) -> Vec { + if self.force_color_svg() { + let strip_y = static_regex!(r#"y="\d+px""#); + output + .lines() + // anstyle_svg causes environment-dependent width parameter + .skip(1) + .map(|line| strip_y.replace_all(line, r#"y="0px""#).into_owned()) + .collect() + } else { + output.lines().filter(|l| l.trim() != "|").map(str::to_owned).collect() + } + } + fn load_compare_outputs( &self, proc_res: &ProcRes, @@ -2719,10 +2736,8 @@ impl<'test> TestCx<'test> { (&tmp.0, &tmp.1) } } else if compare_output_by_lines { - // Filter out padded empty code lines - let mut actual_lines: Vec<&str> = actual.lines().filter(|l| l.trim() != "|").collect(); - let mut expected_lines: Vec<&str> = - expected.lines().filter(|l| l.trim() != "|").collect(); + let mut actual_lines = self.lines_for_comparison(actual); + let mut expected_lines = self.lines_for_comparison(expected); actual_lines.sort_unstable(); expected_lines.sort_unstable(); if actual_lines == expected_lines { @@ -2866,7 +2881,9 @@ impl<'test> TestCx<'test> { } if show_diff_by_lines { - write!(self.stderr, "{}", diff_by_lines(expected, actual)); + let expected_lines = self.lines_for_comparison(expected); + let actual_lines = self.lines_for_comparison(actual); + write!(self.stderr, "{}", diff_by_lines(&expected_lines, &actual_lines)); } } diff --git a/src/tools/compiletest/src/runtest/compute_diff.rs b/src/tools/compiletest/src/runtest/compute_diff.rs index ce796d2820568..8b9a39b244ecf 100644 --- a/src/tools/compiletest/src/runtest/compute_diff.rs +++ b/src/tools/compiletest/src/runtest/compute_diff.rs @@ -105,19 +105,18 @@ pub(crate) fn write_diff(expected: &str, actual: &str, context_size: usize) -> S output } -pub(crate) fn diff_by_lines(expected: &str, actual: &str) -> String { +pub(crate) fn diff_by_lines(expected: &[String], actual: &[String]) -> String { use std::collections::HashMap; use std::fmt::Write; let mut output = String::new(); let mut expected_counts: HashMap<&str, usize> = HashMap::new(); let mut actual_counts: HashMap<&str, usize> = HashMap::new(); - // Filter out padded empty code lines - for line in expected.lines().filter(|l| l.trim() != "|") { - *expected_counts.entry(line).or_insert(0) += 1; + for line in expected { + *expected_counts.entry(line.as_str()).or_insert(0) += 1; } - for line in actual.lines().filter(|l| l.trim() != "|") { - *actual_counts.entry(line).or_insert(0) += 1; + for line in actual { + *actual_counts.entry(line.as_str()).or_insert(0) += 1; } fn write_expected_only_lines( diff --git a/tests/ui/error-emitter/multiline-removal-suggestion.rs b/tests/ui/error-emitter/multiline-removal-suggestion.rs index 36127ab13123a..72e9ea357c9e6 100644 --- a/tests/ui/error-emitter/multiline-removal-suggestion.rs +++ b/tests/ui/error-emitter/multiline-removal-suggestion.rs @@ -56,4 +56,3 @@ fn bay() -> Vec<(bool, HashSet)> { .collect() } fn main() {} -//@ ignore-parallel-frontend invalid svg(multiple threads trying to write to the same file) From 816c70b52c78eaf1a98bec55e8047e1327d31d39 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 10 Jun 2026 19:44:15 +0300 Subject: [PATCH 55/59] resolve: Partially revert "Remove a special case for dummy imports" --- compiler/rustc_resolve/src/imports.rs | 9 +++++++++ .../auxiliary/dummy-import-ice-macro.rs | 15 ++++++++++++++ tests/ui/imports/dummy-import-ice.rs | 20 +++++++++++++++++++ tests/ui/imports/issue-56125.rs | 2 +- tests/ui/imports/issue-56125.stderr | 19 +++++++++++++++++- .../shadow-glob-module-resolution-2.rs | 2 ++ .../shadow-glob-module-resolution-2.stderr | 16 ++++++++++++++- .../shadow-glob-module-resolution-4.rs | 2 ++ .../shadow-glob-module-resolution-4.stderr | 16 ++++++++++++++- 9 files changed, 97 insertions(+), 4 deletions(-) create mode 100644 tests/ui/imports/auxiliary/dummy-import-ice-macro.rs create mode 100644 tests/ui/imports/dummy-import-ice.rs diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 4f55c165e2f36..f23cb3dd003a9 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -628,6 +628,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { module.underscore_disambiguator.get() }); self.update_local_resolution(module, key, orig_ident_span, |this, resolution| { + if res == Res::Err + && let Some(old_decl) = resolution.best_decl() + && old_decl.res() != Res::Err + { + // Do not override real declarations with `Res::Err`s from error recovery. + // FIXME: this special case shouldn't be necessary, but removing it triggers an ICE + // due to some other issues (#157406, tests/ui/imports/dummy-import-ice.rs). + return Ok(()); + } if decl.is_glob_import() { resolution.glob_decl = Some(match resolution.glob_decl { Some(old_decl) => this.select_glob_decl(old_decl, decl), diff --git a/tests/ui/imports/auxiliary/dummy-import-ice-macro.rs b/tests/ui/imports/auxiliary/dummy-import-ice-macro.rs new file mode 100644 index 0000000000000..b5bc9c72575c5 --- /dev/null +++ b/tests/ui/imports/auxiliary/dummy-import-ice-macro.rs @@ -0,0 +1,15 @@ +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro] +pub fn my_macro(_: proc_macro::TokenStream) -> proc_macro::TokenStream { + r" + use own::*; + mod own { + pub use super::submodule::*; + pub use super::ambiguous; + } + " + .parse() + .unwrap() +} diff --git a/tests/ui/imports/dummy-import-ice.rs b/tests/ui/imports/dummy-import-ice.rs new file mode 100644 index 0000000000000..e1e82db9d9f80 --- /dev/null +++ b/tests/ui/imports/dummy-import-ice.rs @@ -0,0 +1,20 @@ +// Regression test for issue #157406. + +//@ check-pass +//@ proc-macro: dummy-import-ice-macro.rs + +extern crate dummy_import_ice_macro; + +pub fn foo() { + ambiguous(); +} + +mod submodule { + pub fn ambiguous() {} +} + +pub mod ambiguous {} + +dummy_import_ice_macro::my_macro!(); + +fn main() {} diff --git a/tests/ui/imports/issue-56125.rs b/tests/ui/imports/issue-56125.rs index a30ac36473bdd..4e7e7ac67c572 100644 --- a/tests/ui/imports/issue-56125.rs +++ b/tests/ui/imports/issue-56125.rs @@ -15,7 +15,7 @@ mod m2 { mod m3 { mod empty {} use empty::issue_56125; //~ ERROR unresolved import `empty::issue_56125` - use issue_56125::*; + use issue_56125::*; //~ ERROR `issue_56125` is ambiguous } fn main() {} diff --git a/tests/ui/imports/issue-56125.stderr b/tests/ui/imports/issue-56125.stderr index 8c8c45a3f76f4..122e9ae3b3575 100644 --- a/tests/ui/imports/issue-56125.stderr +++ b/tests/ui/imports/issue-56125.stderr @@ -56,7 +56,24 @@ LL | use issue_56125::non_last_segment::non_last_segment::*; = help: consider adding an explicit import of `issue_56125` to disambiguate = help: or use `self::issue_56125` to refer to this module unambiguously -error: aborting due to 3 previous errors +error[E0659]: `issue_56125` is ambiguous + --> $DIR/issue-56125.rs:18:9 + | +LL | use issue_56125::*; + | ^^^^^^^^^^^ ambiguous name + | + = note: ambiguous because of a conflict between a name from a glob import and an outer scope during import or macro resolution + = note: `issue_56125` could refer to a crate passed with `--extern` + = help: use `::issue_56125` to refer to this crate unambiguously +note: `issue_56125` could also refer to the module imported here + --> $DIR/issue-56125.rs:18:9 + | +LL | use issue_56125::*; + | ^^^^^^^^^^^^^^ + = help: consider adding an explicit import of `issue_56125` to disambiguate + = help: or use `self::issue_56125` to refer to this module unambiguously + +error: aborting due to 4 previous errors Some errors have detailed explanations: E0432, E0659. For more information about an error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/shadow-glob-module-resolution-2.rs b/tests/ui/imports/shadow-glob-module-resolution-2.rs index ac2901eb35290..c3abd1f75542c 100644 --- a/tests/ui/imports/shadow-glob-module-resolution-2.rs +++ b/tests/ui/imports/shadow-glob-module-resolution-2.rs @@ -14,5 +14,7 @@ use a::*; use e as b; //~^ ERROR: unresolved import `e` use b::c::D as e; +//~^ ERROR: cannot determine resolution for the import +//~| ERROR: cannot determine resolution for the import fn main() { } diff --git a/tests/ui/imports/shadow-glob-module-resolution-2.stderr b/tests/ui/imports/shadow-glob-module-resolution-2.stderr index 205459ec9e638..d8132d0ce5bf5 100644 --- a/tests/ui/imports/shadow-glob-module-resolution-2.stderr +++ b/tests/ui/imports/shadow-glob-module-resolution-2.stderr @@ -1,3 +1,17 @@ +error: cannot determine resolution for the import + --> $DIR/shadow-glob-module-resolution-2.rs:16:5 + | +LL | use b::c::D as e; + | ^^^^^^^^^^^^ + +error: cannot determine resolution for the import + --> $DIR/shadow-glob-module-resolution-2.rs:16:5 + | +LL | use b::c::D as e; + | ^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error[E0432]: unresolved import `e` --> $DIR/shadow-glob-module-resolution-2.rs:14:5 | @@ -12,6 +26,6 @@ LL - use e as b; LL + use a as b; | -error: aborting due to 1 previous error +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/shadow-glob-module-resolution-4.rs b/tests/ui/imports/shadow-glob-module-resolution-4.rs index 38fe7d17a367f..581cdc185d3f3 100644 --- a/tests/ui/imports/shadow-glob-module-resolution-4.rs +++ b/tests/ui/imports/shadow-glob-module-resolution-4.rs @@ -12,6 +12,8 @@ use e as b; use b::C as e; //~^ ERROR: unresolved import `b::C` +//~| ERROR: cannot determine resolution for the import +//~| ERROR: cannot determine resolution for the import fn e() {} diff --git a/tests/ui/imports/shadow-glob-module-resolution-4.stderr b/tests/ui/imports/shadow-glob-module-resolution-4.stderr index d94a59347a5b8..063beb612b132 100644 --- a/tests/ui/imports/shadow-glob-module-resolution-4.stderr +++ b/tests/ui/imports/shadow-glob-module-resolution-4.stderr @@ -1,9 +1,23 @@ +error: cannot determine resolution for the import + --> $DIR/shadow-glob-module-resolution-4.rs:13:5 + | +LL | use b::C as e; + | ^^^^^^^^^ + +error: cannot determine resolution for the import + --> $DIR/shadow-glob-module-resolution-4.rs:13:5 + | +LL | use b::C as e; + | ^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error[E0432]: unresolved import `b::C` --> $DIR/shadow-glob-module-resolution-4.rs:13:5 | LL | use b::C as e; | ^^^^^^^^^ -error: aborting due to 1 previous error +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0432`. From 24c895ae7061032c9f25f5c039eb234052a6d47b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 10 Jun 2026 23:32:13 +0200 Subject: [PATCH 56/59] HIR ty lowering: Turn comment into FIXME --- compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index efadba92f2643..085980b364e10 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1683,7 +1683,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let kind = match assoc_tag { ty::AssocTag::Type => ty::AliasTermKind::InherentTy { def_id: assoc_item }, ty::AssocTag::Const => { - // drop once `InherentConst` accepts IAC-shaped args (issue #156181) + // FIXME(mgca): drop once `InherentConst` accepts IAC-shaped args (issue #156181) // without this, `new_from_args` errors (#155341). self.require_type_const_attribute(assoc_item, span)?; ty::AliasTermKind::InherentConst { def_id: assoc_item } From 7fe440879ea356529798f3a2dc762906c631b059 Mon Sep 17 00:00:00 2001 From: JayanAXHF Date: Sun, 12 Apr 2026 18:48:27 +0530 Subject: [PATCH 57/59] fix(mgca): Allow specifying generic args (of enum) on enum itself in unit & tuple variant constructions in (direct) const args --- .../src/hir_ty_lowering/mod.rs | 50 +++++++++++++++---- ...eric-args-on-enum-variant-segments-fail.rs | 19 +++++++ ...-args-on-enum-variant-segments-fail.stderr | 41 +++++++++++++++ .../generic-args-on-enum-variant-segments.rs | 16 ++++++ 4 files changed, 115 insertions(+), 11 deletions(-) create mode 100644 tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.rs create mode 100644 tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.stderr create mode 100644 tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments.rs diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 5a86e8186a5aa..5aab360f73985 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2862,33 +2862,61 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let args = self.lower_generic_args_of_path_segment(span, did, segment); ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(did, args)) } - Res::Def(DefKind::Ctor(ctor_of, CtorKind::Const), did) => { + Res::Def(kind @ DefKind::Ctor(ctor_of, CtorKind::Const), did) => { assert_eq!(opt_self_ty, None); - let [leading_segments @ .., segment] = path.segments else { bug!() }; - let _ = self - .prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None); + let generic_segments = + self.probe_generic_path_segments(path.segments, opt_self_ty, kind, did, span); + let indices: FxHashSet<_> = + generic_segments.iter().map(|GenericPathSegment(_, index)| index).collect(); + let _ = self.prohibit_generic_args( + path.segments.iter().enumerate().filter_map(|(index, seg)| { + if !indices.contains(&index) { Some(seg) } else { None } + }), + GenericsArgsErrExtend::DefVariant(&path.segments), + ); let parent_did = tcx.parent(did); let generics_did = match ctor_of { CtorOf::Variant => tcx.parent(parent_did), CtorOf::Struct => parent_did, }; - let args = self.lower_generic_args_of_path_segment(span, generics_did, segment); - + let args = self.lower_generic_args_of_path_segment( + span, + generics_did, + &path.segments[generic_segments[0].1], + ); self.construct_const_ctor_value(did, ctor_of, args) } - Res::Def(DefKind::Ctor(_, CtorKind::Fn), did) => { + Res::Def(DefKind::Ctor(ctor_of, CtorKind::Fn), did) => { assert_eq!(opt_self_ty, None); - let [leading_segments @ .., segment] = path.segments else { bug!() }; - let _ = self - .prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None); + let generic_segments = self.probe_generic_path_segments( + path.segments, + opt_self_ty, + DefKind::Ctor(ctor_of, CtorKind::Const), + did, + span, + ); + let indices: FxHashSet<_> = + generic_segments.iter().map(|GenericPathSegment(_, index)| index).collect(); + let _ = self.prohibit_generic_args( + path.segments.iter().enumerate().filter_map(|(index, seg)| { + if !indices.contains(&index) { Some(seg) } else { None } + }), + GenericsArgsErrExtend::DefVariant(&path.segments), + ); + let parent_did = tcx.parent(did); let generics_did = if let DefKind::Ctor(CtorOf::Variant, _) = tcx.def_kind(did) { tcx.parent(parent_did) } else { parent_did }; - let args = self.lower_generic_args_of_path_segment(span, generics_did, segment); + let args = self.lower_generic_args_of_path_segment( + span, + generics_did, + &path.segments[generic_segments[0].1], + ); + ty::Const::zero_sized(tcx, Ty::new_fn_def(tcx, did, args)) } Res::Def(DefKind::AssocConst { .. }, did) => { diff --git a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.rs b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.rs new file mode 100644 index 0000000000000..9e4443b1fc1c5 --- /dev/null +++ b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.rs @@ -0,0 +1,19 @@ +#![feature(min_generic_const_args)] +#![feature(adt_const_params, unsized_const_params)] +#[derive(PartialEq, Eq, std::marker::ConstParamTy)] +pub enum Enum { + Unit, + Tuple(), + Store(T), +} +pub mod module { + pub use super::Enum::Store; +} +fn main() { + type const _: Enum<()> = Enum::<()>::Unit::<()>; + //~^ ERROR: type arguments are not allowed on unit variant `Unit` [E0109] + type const _: Enum<()> = Enum::<()>::Tuple::<()>(); + //~^ ERROR: type arguments are not allowed on tuple variant `Tuple` [E0109] + type const _: Enum<()> = self::::Enum::<()>::Store; + //~^ ERROR: type arguments are not allowed on module `generic_args_on_enum_variant_segments_fail` [E0109] +} diff --git a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.stderr b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.stderr new file mode 100644 index 0000000000000..ec129b3e33213 --- /dev/null +++ b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.stderr @@ -0,0 +1,41 @@ +error[E0109]: type arguments are not allowed on unit variant `Unit` + --> $DIR/generic-args-on-enum-variant-segments-fail.rs:13:49 + | +LL | type const _: Enum<()> = Enum::<()>::Unit::<()>; + | ---- ^^ type argument not allowed + | | + | not allowed on unit variant `Unit` + | + = note: generic arguments are not allowed on both an enum and its variant's path segments simultaneously; they are only valid in one place or the other +help: remove the generics arguments from one of the path segments + | +LL - type const _: Enum<()> = Enum::<()>::Unit::<()>; +LL + type const _: Enum<()> = Enum::<()>::Unit; + | + +error[E0109]: type arguments are not allowed on tuple variant `Tuple` + --> $DIR/generic-args-on-enum-variant-segments-fail.rs:15:50 + | +LL | type const _: Enum<()> = Enum::<()>::Tuple::<()>(); + | ----- ^^ type argument not allowed + | | + | not allowed on tuple variant `Tuple` + | + = note: generic arguments are not allowed on both an enum and its variant's path segments simultaneously; they are only valid in one place or the other +help: remove the generics arguments from one of the path segments + | +LL - type const _: Enum<()> = Enum::<()>::Tuple::<()>(); +LL + type const _: Enum<()> = Enum::<()>::Tuple(); + | + +error[E0109]: type arguments are not allowed on module `generic_args_on_enum_variant_segments_fail` + --> $DIR/generic-args-on-enum-variant-segments-fail.rs:17:37 + | +LL | type const _: Enum<()> = self::::Enum::<()>::Store; + | ---- ^^^ type argument not allowed + | | + | not allowed on module `generic_args_on_enum_variant_segments_fail` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0109`. diff --git a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments.rs b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments.rs new file mode 100644 index 0000000000000..caac7a3b23a50 --- /dev/null +++ b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments.rs @@ -0,0 +1,16 @@ +//@ check-pass + +#![feature(min_generic_const_args)] +#![feature(adt_const_params, unsized_const_params)] + +#[derive(PartialEq, Eq, std::marker::ConstParamTy)] +enum Enum { + Unit, + Tuple(), + Store(T), +} + +type const _: Enum<()> = Enum::<()>::Unit; +type const _: Enum<()> = Enum::<()>::Tuple(); + +fn main() {} From c451b16b8017021984cba6be4db6504c436ae08f Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 15 May 2026 22:20:17 +0000 Subject: [PATCH 58/59] core: Stabilize `new_range_api_legacy` Newly stable API: core::range::legacy --- library/core/src/range.rs | 2 +- library/core/src/range/legacy.rs | 1 + ...ugg-stable-import-first-issue-140240.stderr | 4 ++-- tests/ui/new-range/disabled.rs | 3 +-- tests/ui/new-range/enabled.rs | 1 + tests/ui/range/new_range_stability.rs | 5 +---- tests/ui/range/new_range_stability.stderr | 18 ++++-------------- 7 files changed, 11 insertions(+), 23 deletions(-) diff --git a/library/core/src/range.rs b/library/core/src/range.rs index 87e6ad6931249..f674b97879573 100644 --- a/library/core/src/range.rs +++ b/library/core/src/range.rs @@ -20,7 +20,7 @@ use crate::hash::Hash; mod iter; -#[unstable(feature = "new_range_api_legacy", issue = "125687")] +#[stable(feature = "new_range_api_legacy", since = "CURRENT_RUSTC_VERSION")] pub mod legacy; #[doc(inline)] diff --git a/library/core/src/range/legacy.rs b/library/core/src/range/legacy.rs index aa11331382dd0..03f024354479d 100644 --- a/library/core/src/range/legacy.rs +++ b/library/core/src/range/legacy.rs @@ -7,4 +7,5 @@ //! The types here are equivalent to those in [`core::ops`]. #[doc(inline)] +#[stable(feature = "new_range_api_legacy", since = "CURRENT_RUSTC_VERSION")] pub use crate::ops::{Range, RangeFrom, RangeInclusive, RangeToInclusive}; diff --git a/tests/ui/did_you_mean/sugg-stable-import-first-issue-140240.stderr b/tests/ui/did_you_mean/sugg-stable-import-first-issue-140240.stderr index 2e268082cefb8..158d91d347a38 100644 --- a/tests/ui/did_you_mean/sugg-stable-import-first-issue-140240.stderr +++ b/tests/ui/did_you_mean/sugg-stable-import-first-issue-140240.stderr @@ -10,10 +10,10 @@ LL + use std::collections::btree_map::Range; | LL + use std::collections::btree_set::Range; | -LL + use std::ops::Range; - | LL + use std::range::Range; | +LL + use std::range::legacy::Range; + | error: aborting due to 1 previous error diff --git a/tests/ui/new-range/disabled.rs b/tests/ui/new-range/disabled.rs index 528c464117a13..2202ed23ff1d2 100644 --- a/tests/ui/new-range/disabled.rs +++ b/tests/ui/new-range/disabled.rs @@ -1,7 +1,6 @@ +//! Without the `new_range` feature enabled, `..` syntax resolves to the legacy types. //@ check-pass -#![feature(new_range_api_legacy)] - fn main() { // Unchanged let a: core::ops::RangeFull = ..; diff --git a/tests/ui/new-range/enabled.rs b/tests/ui/new-range/enabled.rs index 6d9a1259b7756..9f2833855b2fb 100644 --- a/tests/ui/new-range/enabled.rs +++ b/tests/ui/new-range/enabled.rs @@ -1,3 +1,4 @@ +//! With the `new_range` feature enabled, `..` syntax resolves to the new range types. //@ check-pass #![feature(new_range)] diff --git a/tests/ui/range/new_range_stability.rs b/tests/ui/range/new_range_stability.rs index 965be17efa747..cea1b33aac467 100644 --- a/tests/ui/range/new_range_stability.rs +++ b/tests/ui/range/new_range_stability.rs @@ -7,6 +7,7 @@ use std::range::{ RangeFrom, RangeFromIter, Range, + legacy, }; fn range_inclusive(mut r: RangeInclusive) { @@ -60,8 +61,4 @@ fn range(mut r: Range) { i.remainder(); //~ ERROR unstable } -// Unstable module - -use std::range::legacy; //~ ERROR unstable - fn main() {} diff --git a/tests/ui/range/new_range_stability.stderr b/tests/ui/range/new_range_stability.stderr index ac269a2b2227e..f280d15de1065 100644 --- a/tests/ui/range/new_range_stability.stderr +++ b/tests/ui/range/new_range_stability.stderr @@ -1,15 +1,5 @@ -error[E0658]: use of unstable library feature `new_range_api_legacy` - --> $DIR/new_range_stability.rs:65:5 - | -LL | use std::range::legacy; - | ^^^^^^^^^^^^^^^^^^ - | - = note: see issue #125687 for more information - = help: add `#![feature(new_range_api_legacy)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error[E0658]: use of unstable library feature `new_range_remainder` - --> $DIR/new_range_stability.rs:23:7 + --> $DIR/new_range_stability.rs:24:7 | LL | i.remainder(); | ^^^^^^^^^ @@ -19,7 +9,7 @@ LL | i.remainder(); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `new_range_remainder` - --> $DIR/new_range_stability.rs:44:7 + --> $DIR/new_range_stability.rs:45:7 | LL | i.remainder(); | ^^^^^^^^^ @@ -29,7 +19,7 @@ LL | i.remainder(); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `new_range_remainder` - --> $DIR/new_range_stability.rs:60:7 + --> $DIR/new_range_stability.rs:61:7 | LL | i.remainder(); | ^^^^^^^^^ @@ -38,6 +28,6 @@ LL | i.remainder(); = help: add `#![feature(new_range_remainder)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. From 1c8c2e548e795ade34f4b6c97a25c9d63d90d685 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Fri, 15 May 2026 22:44:46 +0000 Subject: [PATCH 59/59] core: Stabilize `RangeFull` and `RangeTo` re-exports in `core::range` Stabilized under `new_range_api_exports`. Newly stable API: core::range::RangeFull; core::range::RangeTo; --- library/core/src/range.rs | 18 +++++++----------- tests/ui/new-range/disabled.rs | 5 ++--- tests/ui/new-range/enabled.rs | 5 ++--- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/library/core/src/range.rs b/library/core/src/range.rs index f674b97879573..b6eecffe2f7aa 100644 --- a/library/core/src/range.rs +++ b/library/core/src/range.rs @@ -23,6 +23,8 @@ mod iter; #[stable(feature = "new_range_api_legacy", since = "CURRENT_RUSTC_VERSION")] pub mod legacy; +use core::ops::Bound::{self, Excluded, Included, Unbounded}; + #[doc(inline)] #[stable(feature = "new_range_from_api", since = "1.96.0")] pub use iter::RangeFromIter; @@ -33,19 +35,13 @@ pub use iter::RangeInclusiveIter; #[stable(feature = "new_range_api", since = "1.96.0")] pub use iter::RangeIter; -// FIXME(#125687): re-exports temporarily removed -// Because re-exports of stable items (Bound, RangeBounds, RangeFull, RangeTo) -// can't be made unstable. -// -// #[doc(inline)] -// #[unstable(feature = "new_range_api", issue = "125687")] -// pub use crate::iter::Step; -// #[doc(inline)] -// #[unstable(feature = "new_range_api", issue = "125687")] -// pub use crate::ops::{Bound, IntoBounds, OneSidedRange, RangeBounds, RangeFull, RangeTo}; use crate::iter::Step; -use crate::ops::Bound::{self, Excluded, Included, Unbounded}; +// FIXME(one_sided_range): These types should move into this module. +// FIXME(range_into_bounds): Ditto. Also consider re-exporting `RangeBounds` and related. use crate::ops::{IntoBounds, OneSidedRange, OneSidedRangeBound, RangeBounds}; +#[doc(inline)] +#[stable(feature = "new_range_api_exports", since = "CURRENT_RUSTC_VERSION")] +pub use crate::ops::{RangeFull, RangeTo}; /// A (half-open) range bounded inclusively below and exclusively above. /// diff --git a/tests/ui/new-range/disabled.rs b/tests/ui/new-range/disabled.rs index 2202ed23ff1d2..25e35614c66a8 100644 --- a/tests/ui/new-range/disabled.rs +++ b/tests/ui/new-range/disabled.rs @@ -6,9 +6,8 @@ fn main() { let a: core::ops::RangeFull = ..; let b: core::ops::RangeTo = ..2; - // FIXME(#125687): re-exports temporarily removed - // let _: core::range::RangeFull = a; - // let _: core::range::RangeTo = b; + let _: core::range::RangeFull = a; + let _: core::range::RangeTo = b; // Changed let a: core::range::legacy::RangeFrom = 1..; diff --git a/tests/ui/new-range/enabled.rs b/tests/ui/new-range/enabled.rs index 9f2833855b2fb..ed227e088fcfa 100644 --- a/tests/ui/new-range/enabled.rs +++ b/tests/ui/new-range/enabled.rs @@ -8,9 +8,8 @@ fn main() { let a: core::ops::RangeFull = ..; let b: core::ops::RangeTo = ..2; - // FIXME(#125687): re-exports temporarily removed - // let _: core::range::RangeFull = a; - // let _: core::range::RangeTo = b; + let _: core::range::RangeFull = a; + let _: core::range::RangeTo = b; // Changed let a: core::range::RangeFrom = 1..;